Тема: AHK: Закрыть рабочую папку скрипта
Всем доброго времени суток, есть небольшой вопрос. У меня в определенной папке есть скрипт, нужно чтобы при выполнении скрипта рабочая папка этого скрипта закрывалась, как это можно реализовать?
Вы не вошли. Пожалуйста, войдите или зарегистрируйтесь.
Страницы 1
Чтобы отправить ответ, вы должны войти или зарегистрироваться
Всем доброго времени суток, есть небольшой вопрос. У меня в определенной папке есть скрипт, нужно чтобы при выполнении скрипта рабочая папка этого скрипта закрывалась, как это можно реализовать?
Есть встроенная переменная A_WorkingDir.
Это я знаю, а закрыть папку то как?
Попозже напишу.
Можно по-разному понять выражение "закрыть папку". Или в проводнике открыта, это одно дело, или же закрыть на уровне файловой системы, ограничив права доступа.
Меня даже как-то озадачило, что у teadrinker'a никаких вопросов не возникло. ![]()
Off: да ему проще написать скрипт, где в одной строке будут выполняться оба действия, чем задумываться о таких мелочах ))
Можно по-разному понять выражение "закрыть папку". Или в проводнике открыта, это одно дело, или же закрыть на уровне файловой системы, ограничив права доступа.
Мне к примеру нужно чтобы закрылась папка которая открыта в проводнике.
Мне как-то сразу стало понятно, что речь идёт о закрытии окна (видно, экстрасенсорные способности пока не подводят). Другое дело, я был уверен, что зная путь к папке, легко закрыть её окно, т. е. путь с заголовком перепутал.
for item in ComObjCreate("Shell.Application").Windows
{
Path := SubStr(item.LocationURL, 9)
StringReplace, Path, Path, /, \, 1
StringReplace, Path, Path, `%20, % " ", 1
if (Path = A_WorkingDir)
{
WinClose, % "ahk_id" item.hwnd
item := ""
break
}
}Спасибо огромное, работает как часы!
Если в пути есть символы например "[]", то не работает ![]()
Подозреваю, что возможны ещё и другие.
У меня пока так:
WinClose, ahk_exe explorer.exe ahk_class CabinetWClass, %Dir%У меня пока так:
А если открыты две папки с одинаковым названием?
Вот так должно сработать:
WinClose, % "ahk_id" GetFolderHwnd(A_WorkingDir)
GetFolderHwnd(FolderPath)
{
for item in ComObjCreate("Shell.Application").Windows
{
url := SubStr(item.LocationURL, 9)
StringReplace, url, url, /, \, 1
url := UriDecode(url)
if (url = FolderPath && hwnd := item.hwnd)
Return hwnd
}
}
UriDecode(Uri, Enc = "UTF-8")
{
While Pos := RegExMatch(Uri, "i)(%[\da-f]{2})+", Code, A_Index = 1 ? 1 : Pos+Len)
{
VarSetCapacity(Var, Len := StrLen(Code)//3, 0)
StringTrimLeft, Code, Code, 1
Loop, Parse, Code, `%
NumPut("0x" . A_LoopField, Var, A_Index - 1, "UChar")
StringReplace, Uri, Uri, `%%Code%, % StrGet(&Var, Enc)
}
Return Uri
}А если открыты две папки с одинаковым названием?
Ну это просто:
While WinExist("ahk_exe explorer.exe ahk_class CabinetWClass", Dir)
WinClose У меня проблема в том, что мне нужно как раз не закрывать окно.
А нужно запустить проводник и выделить в нём файл, и вот если окно с папкой в которой файл, уже открыта, то активировать это окно и выделить файл. Пока приходится закрывать:
WinClose, ahk_exe explorer.exe ahk_class CabinetWClass, %Dir%
Run, explorer /select`, "%FilePath%"
Собственно вопрос как в окне проводника выделить файл, остальное пока ясно.
Ну это просто:
Не совсем понял, закрыть-то только одну нужно. Как выделить — попозже напишу.
Не совсем понял, закрыть-то только одну нужно.
Так это одну и закрывает:
WinClose, ahk_exe explorer.exe ahk_class CabinetWClass, %Dir%так что, я тоже
А если открыты две папки с одинаковым названием
не понял.
Как выделить — попозже напишу.
Спасибо.
А если открыты две папки с одинаковым названием
не понял.
Ну вот смотри, предположим, открыты две папки: одна с путём С:\MyFolder, другая E:\MyFolder. Оба окна будут называться MyFolder. Как с помощью представленного тобой кода можно закрыть одну, не закрывая другую?
Вот более простой вариант получения hwnd папки с конкретным путём, без необходимости декодировать url:
Run, % A_WorkingDir
Loop
Sleep, 100
until hwnd := GetFolderHwnd(A_WorkingDir)
MsgBox, % hwnd
GetFolderHwnd(FolderPath)
{
for item in ComObjCreate("Shell.Application").Windows
if (item.Document.Folder.Self.Path = FolderPath)
Return item.hwnd
}Выделяем так:
SelectFilePath(FilePath)
{
for item in ComObjCreate("Shell.Application").Windows
{
window := item, ShellFolderView := item.Document
for item in ShellFolderView.Folder.Items
{
if (item.path = FilePath)
{
ShellFolderView.SelectItem(item, 1|4) ; 1 — select the item, 4 — deselect all but the specified item.
WinActivate, % "ahk_id" hwnd := window.hwnd
break 2
}
}
}
if !hwnd
Run, explorer /select`, "%FilePath%"
}Ну вот смотри, предположим, открыты две папки: одна с путём С:\MyFolder, другая E:\MyFolder. Оба окна будут называться MyFolder. Как с помощью представленного тобой кода можно закрыть одну, не закрывая другую?
While WinExist("ahk_exe explorer.exe ahk_class CabinetWClass", Dir)
WinClose Никак нет ![]()
Dir = E:\MyFolderЗакроется только E:\MyFolder.
В любом случае
SetTitleMatchMode RegEx рассудит.
Вот более простой вариант получения hwnd папки с конкретным путём, без необходимости декодировать url:
Круто, Я знал что только teadrinker найдёт нужные методы.
Выделяем так:
Ооо... Класс, давно искал. Большое Спасибо!
А возможно подлечить?
Папка открыта, выбран - файл номер1. Файл который должен выбран - файл номер2. Ок. Запускаем. Файл номер2 выбран выделен, окно проводника не перезапускается! Но, на файле номер1, остаётся полувыделение. Термин полувыделение, будет понятен при тестах.
Пробовал сначала:
4 — deselect all but the specified item.
а потом:
1 — select the item
не вышло.
Закроется только E:\MyFolder.
Ок, а если такие папки:
D:\MyFolder
D:\MyFolder\MyFolder
Активна в данный момент последняя, закрыть нужно D:\MyFolder.
А возможно подлечить?
SelectFilePath(FilePath)
{
for item in ComObjCreate("Shell.Application").Windows
{
window := item, ShellFolderView := item.Document
for item in ShellFolderView.Folder.Items
{
if (item.path = FilePath)
{
ShellFolderView.SelectItem(item, 1|4|16) ; 1 — select the item, 4 — deselect all but the specified item, 16 — give the item the focus.
WinActivate, % "ahk_id" hwnd := window.hwnd
break 2
}
}
}
if !hwnd
Run, explorer /select`, "%FilePath%"
}Каюсь. Наивно полагал, что так будет всё ок:
SetTitleMatchMode RegEx
run D:\MyFolder
run D:\MyFolder\MyFolder
Sleep 500
Dir = D:\MyFolder
While WinExist("ahk_exe explorer.exe ahk_class CabinetWClass", "im`a)^\Q" Dir "\E$")
WinClose
Return
видимо неправильно понял справку ![]()
-----------
Спасибо за доработку!
В справке написано
RegEx (v1.0.45+): Changes WinTitle, WinText, ExcludeTitle, and ExcludeText to be regular expressions.
Но не срабатывает почему-то.
Вот так сработало:
SetTitleMatchMode RegEx
run D:\MyFolder
run D:\MyFolder\MyFolder
Sleep 2000
Dir := "D:\MyFolder"
if WinExist("ahk_class CabinetWClass", "\Q" Dir "\E$")
WinClose
![]()
Значит работают некие непонятно\неполноценные шаблоны ![]()
Ну да, так что мой способ, имхо, предпочтительнее, он всё-таки определяет окно папки однозначно по адресу.
Так это сразу было очевидно, диалог был интересен только с познавательной стороны. И имхо оправдался познанием заморочек с SetTitleMatchMode RegEx.
Кстати, а что тут означает 2:
break 2или просто опечатка?
Прерывание и своего, и следующего по иерархии цикла (по умолчанию 1).
Прерывание и своего, и следующего по иерархии цикла (по умолчанию 1).
Понял.
Работает SetTitleMatchMode RegEx, просто был неверный шаблон:
SetTitleMatchMode RegEx
run D:\MyFolder
run D:\MyFolder\MyFolder
Sleep 1100
Dir = D:\MyFolder
While WinExist("ahk_exe explorer.exe ahk_class CabinetWClass", "im`a)^.*?: \Q" Dir "\E$")
WinClose
Return
Ещё вопрос. При запуске файл выделяется. Но, если список длинный, и был выделен последний файл, а наш файл первый, то как сделать так чтобы выделенный файл было видно?
А, нашёл, нужна восьмёрка:
SelectItem(item, 1|4|16|8)Ни с того ни с сего, начало ругатся что "Folder" неизвестное имя... С чего бы. Хотя и выдавая ошибку всё равно дальше работает.
По случаю переделал код, чтобы не перебирать все файлы во всех окнах.
OpenDir(FilePath) {
SplitPath, FilePath,, FolderPath
for window in ComObjCreate("Shell.Application").Windows
{
try if (window.Document.Folder.Self.Path = FolderPath)
{
try for item in window.Document.Folder.Items
{
if (item.path = FilePath)
{
WinActivate, % "ahk_id" window.hwnd
window.Document.SelectItem(item, 1|4|16|8)
Return
}
}
}
}
Run, explorer /select`, "%FilePath%"
}
Ни с того ни с сего, начало ругатся что "Folder" неизвестное имя...
Да, это я упустил, что у окна IE (которое тоже относится к Shell) нет такого свойства. Так проще:
SelectFilePath(FilePath)
{
for item in ComObjCreate("Shell.Application").Windows
{
window := item, ShellFolderView := item.Document
try for item in ShellFolderView.Folder.Items
{
if (item.path = FilePath)
{
ShellFolderView.SelectItem(item, 1|4|16) ; 1 — select the item, 4 — deselect all but the specified item, 16 — give the item the focus.
WinActivate, % "ahk_id" hwnd := window.hwnd
break 2
}
}
}
if !hwnd
Run, explorer /select`, "%FilePath%"
}Хотя да, отсеивать лишние окна не помешает, просто посмотрел невнимательно. Но тогда уж, чтобы не получать одни и те же объекты несколько раз, так:
SelectFilePath(FilePath)
{
SplitPath, FilePath,, Dir
for window in ComObjCreate("Shell.Application").Windows
{
ShellFolderView := window.Document
try if ((Folder := ShellFolderView.Folder).Self.Path != Dir)
continue
catch
continue
for item in Folder.Items
{
if (item.Path != FilePath)
continue
ShellFolderView.SelectItem(item, 1|4|8|16)
WinActivate, % "ahk_id" window.hwnd
Return
}
}
Run, explorer /select`, "%FilePath%"
}Если в папке, где содержится целевой объект, находится большое количество других объектов (например, это C:\Windows\System32), тогда с указанием SetBatchLines, -1 чувствуется разница в скорости:
SelectFilePath(A_WinDir . "\System32\taskmgr.exe")
SelectFilePath(FilePath)
{
SetBatchLines, -1
SplitPath, FilePath,, Dir
for window in ComObjCreate("Shell.Application").Windows
{
ShellFolderView := window.Document
try if ((Folder := ShellFolderView.Folder).Self.Path != Dir)
continue
catch
continue
for item in Folder.Items
{
if (item.Path != FilePath)
continue
WinActivate, % "ahk_id" window.hwnd
ShellFolderView.SelectItem(item, 1|4|8|16)
Return
}
}
Run, explorer /select`, "%FilePath%"
}Заметил такой баг, так как не показывал этот файл:
MsgBox % FileExist("C:\Windows\System32\SnippingTool.exe")У меня FileExist не видит этот файл. Хотя с taskmgr.exe из этой папки всё Ок.
Убрав FileExist (из своего кода) также не работало, пока не заменил:
Run, explorer /select`, "%FilePath%"на:
Run, %A_WinDir%\explorer.exe /select`, "%FilePath%" Страницы 1
Чтобы отправить ответ, вы должны войти или зарегистрироваться