Перейти на главную страничку сайта (список статей, файлы для скачивания)

ФОРУМ (здесь можно обсудить эту статью, а также саму программу AutoHotkey и проблемы её использования)

Проект перевода документации AutoHotkey: перечень переведённых статей и статей в работе.

Оригинал статьи в AutoHotkey.chm: "Process", в содержании - "Process Management" - "Process", v1.0.46.09.

Ники переводчиков: YMP, Gourmet.

Настоящие имена переводчиков: Юрий Попов, Валентина Гаврикова.

Process

Выполняет над процессом одну из следующих операций: проверяет существование, изменяет приоритет, закрывает, ожидает закрытия.

Process, Cmd, PID-or-Name [, Param3]

Параметры

Cmd Одно из следующих слов:

Exist: помещает в ErrorLevel идентификатор процесса (PID), если соответствующий процесс существует, иначе 0. Если параметр PID-or-Name пустой, определяется PID самого скрипта. Альтернативный способ узнать PID скрипта:
PID := DllCall("GetCurrentProcessId")
Close: завершает процесс. Если процесс завершён успешно, в ErrorLevel помещается его PID, иначе (если подходящего процесса не найдено или есть проблемы с его закрытием) ErrorLevel равен 0. Так как процесс будет завершён внезапно - возможно, с прерыванием его работы в критической точке или с потерей несохранённых данных - этот метод должен использоваться, только если процесс не может быть закрыт путём применения WinClose к одному из его окон.

List: хотя это значение пока не поддерживается, в разделе примеров показано, как можно получить список процессов через DllCall.

Priority: изменяет приоритет (как он показывается в Диспетчере задач Windows) первого из подходящих процессов, задавая ему значение, указанное в Param3, и помещает в ErrorLevel идентификатор этого процесса (PID). Если параметр PID-or-Name пустой, изменяется приоритет самого скрипта. Если подходящего процесса не найдено или есть проблемы с изменением его приоритета, ErrorLevel будет равен 0.

Param3 должен содержать одно из следующих слов: L (или Low), B (или BelowNormal), N (или Normal), A (или AboveNormal), H (или High), R (или Realtime). Поскольку BelowNormal и AboveNormal не поддерживаются в Windows 95/98/Me/NT4, в этих операционных системах они будут автоматически заменены на Normal. Замечание: любой процесс, не предназначенный для выполнения с приоритетом Realtime, может снизить стабильность системы, если ему задать этот уровень.

Wait: ожидает существования указанного процесса в течение заданного в Param3 количества секунд (число может содержать десятичную точку). Если Param3 опущен, команда будет ждать неограниченно долго. При обнаружении подходящего процесса в ErrorLevel помещается его идентификатор (PID). Если время ожидания истекло, ErrorLevel будет равен 0.

WaitClose: ждёт, пока не будут закрыты ВСЕ отвечающие параметру PID-or-Name процессы. Время ожидания в секундах задаётся в Param3 (число может содержать десятичную точку). Если все совпадающие процессы завершаются, ErrorLevel устанавливается в 0. Если истекает время ожидания, ErrorLevel будет содержать идентификатор (PID) первого из подходящих процессов, который ещё существует.
PID-or-Name Этот параметр может быть либо числом (PID), либо именем процесса, как описано ниже. Он также может быть оставлен пустым, чтобы изменить приоритет самого скрипта.

PID: идентификатор процесса, являющийся числом, которое однозначно идентифицирует какой-то один определённый процесс (только на то время, пока процесс существует; в следующий раз это число будет другим). PID вновь запускаемого процесса может быть определён через команду Run. PID окна можно узнать через WinGet. Сама команда Process также может определять PID.

Name: имя процесса. Обычно совпадает с именем исполняемого файла (без пути к нему), например, notepad.exe или winword.exe. Так как одно и то же имя могут иметь несколько процессов, операции выполняются только над первым из них. Имя процесса нечувствительно к регистру.

Примечание от русскоязычных пользователей: как показала практика, регистр имеет значение, если в имени исполняемого файла есть русские буквы. Например, если Notepad.exe переименовать в Блокнот.exe, то при запуске с раздела диска, отформатированного в FAT32, имя процесса будет БЛОКНОТ.EXE, а в случае раздела NTFS - Блокнот.exe. В обоих случаях процесс будет найден, только если его имя в команде указано точно, с соблюдением регистра русских букв. Видимо, самый простой способ обхода этой проблемы - делать проверку для обоих вариантов имени.
Param3 Смотрите описание Cmd выше.

ErrorLevel

Смотрите описание Cmd выше.

Примечания

Для Wait и WaitClose. Процессы проверяются каждые 100 миллисекунд. Если ожидаемое обнаружено, команда не ждёт окончания указанного срока. Вместо этого она немедленно устанавливает ErrorLevel как описано выше, и выполнение скрипта продолжается. В период, когда команда находится в ожидании, новые потоки могут запускаться через горячие клавиши, пункты меню или таймеры.

Для работы в Windows NT4 команде Process требуется файл PSAPI.DLL, который обычно уже присутствует в папке установки AutoHotkey (т.е. не требуется никакой дополнительной установки даже для NT). Однако для того, чтобы использовать её в компилированном скрипте под Windows NT4, положите копию PSAPI.DLL в одну папку со скриптом или в какую-то из папок, указанных в системной переменной PATH (хотя некоторые системы NT4 могут уже иметь эту DLL).

Примеры

; Пример №1

Run Notepad.exe, , , NewPID
Process, priority, %NewPID%, High
MsgBox Процесс Блокнота имеет идентификатор %NewPID%.
; Пример №2

Process, wait, Notepad.exe, 5.5
NewPID = %ErrorLevel% ; Сразу сохранить значение, т.к. ErrorLevel часто изменяется.
if NewPID = 0
{
    MsgBox Указанный процесс не появился в течение 5.5 секунд.
    return
}
; Иначе
MsgBox Появился подходящий процесс (его идентификатор %NewPID%).
Process, priority, %NewPID%, Low
Process, priority, , High ; Установить приоритет процесса скрипта в High (высокий).
WinClose Безымянный - Блокнот
Process, WaitClose, %NewPID%, 5
if ErrorLevel ; Если PID ещё существует.
    MsgBox Процесс не завершился в течение 5 секунд.
; Пример №3: горячая клавиша для изменения приоритета процесса активного окна.

#z:: ; Комбинация Win+Z.
WinGet, active_pid, PID, A
WinGetTitle, active_title, A
Gui, 5:Add, Text,, Нажмите Esc для отмены или дважды щёлкните новый`nуровень приоритета для следующего окна:`n%active_title%
Gui, 5:Add, ListBox, vMyListBox gMyListBox r5, Normal|High|Low|BelowNormal|AboveNormal
Gui, 5:Add, Button, default, OK
Gui, 5:Show,, Установка приоритета
return

5GuiEscape:
5GuiClose:
Gui, Destroy
return

MyListBox:
if A_GuiEvent <> DoubleClick
    return
; Иначе перейти к следующей метке:
5ButtonOK:
GuiControlGet, MyListBox
Gui, Destroy
Process, Priority, %active_pid%, %MyListBox%
if ErrorLevel
    MsgBox Успех: приоритет заменён на "%MyListBox%".
else
    MsgBox Ошибка: приоритет не может быть заменён на "%MyListBox%".
return
; Пример №4: составляет список выполняющихся процессов через DllCall и показывает его в MsgBox.

d = `n ; разделитель строк
s := 4096 ; размер буферов и массивов (4 KB)

Process, Exist ; Устанавливает значение перем. ErrorLevel равным идентификатору процесса текущего скрипта
; Получает дескриптор (handle) этого скрипта через PROCESS_QUERY_INFORMATION (0x0400)
h := DllCall("OpenProcess", "UInt", 0x0400, "Int", false, "UInt", ErrorLevel)
; Открывает регулируемый маркер доступа (adjustable access token) этого процесса
; (TOKEN_ADJUST_PRIVILEGES = 32)
DllCall("Advapi32.dll\OpenProcessToken", "UInt", h, "UInt", 32, "UIntP", t)
VarSetCapacity(ti, 16, 0) ; структура полномочий
InsertInteger(1, ti, 0, 4) ; один элемент в массиве полномочий...
; Извлекает локальный уникальный идентификатор полномочий на отладку:
DllCall("Advapi32.dll\LookupPrivilegeValueA", "UInt", 0, "Str", "SeDebugPrivilege", "UIntP", luid)
InsertInteger(luid, ti, 4, 8)
InsertInteger(2, ti, 12, 4) ; включает это полномочие: SE_PRIVILEGE_ENABLED = 2
; Обновляет полномочия этого процесса новым маркером доступа:
DllCall("Advapi32.dll\AdjustTokenPrivileges"
, "UInt", t, "Int", false, "UInt", &ti, "UInt", 0, "UInt", 0, "UInt", 0)
DllCall("CloseHandle", "UInt", h) ; закрывает данный дескриптор процесса для экономии памяти

; увеличиваем производительность, предварительно загружая библиотеку:
hModule := DllCall("LoadLibrary", "Str", "Psapi.dll")
s := VarSetCapacity(a, s) ; массив, который получает список идентификаторов процессов
DllCall("Psapi.dll\EnumProcesses", "UInt", &a, "UInt", s, "UIntP", r)
Loop, % r // 4 ; производим разбор массива для таких идентификаторов, как DWORDs (32 bits):
{
   id := ExtractInteger(a, A_Index * 4)
   ; Открываем процесс с помощью: PROCESS_VM_READ (0x0010) | PROCESS_QUERY_INFORMATION (0x0400)
   h := DllCall("OpenProcess", "UInt", 0x0010 | 0x0400, "Int", false, "UInt", id)
   VarSetCapacity(m, s) ; массив, который получает список дескрипторов модулей:
   DllCall("Psapi.dll\EnumProcessModules", "UInt", h, "UInt", &m, "UInt", s, "UIntP", r)
   VarSetCapacity(n, s, 0) ; буфер, который получает базовое имя модуля:
   e := DllCall("Psapi.dll\GetModuleBaseNameA", "UInt", h, "UInt", m, "Str", n, "Chr", s)
   DllCall("CloseHandle", "UInt", h) ; закрываем дескриптор процесса для экономии памяти
   If n ; если образ не null, добавляем в список:
      l = %l%%n%%d%
}
DllCall("FreeLibrary", "UInt", hModule) ; выгружаем библиотеку, чтобы освободить память
; стираем первый и последний пункт списка (возможно, сигнатуры ASCII)
StringMid, l, l, InStr(l, d) + 1, InStr(l, d, false, 0) - 2 - InStr(l, d)
StringReplace, l, l, %d%, %d%, UseErrorLevel ; извлекаем число процессов
;Sort, l, C ; уберите комментарий с этой строки, чтобы отсортировать список в алфавитном порядке
MsgBox, 0, %ErrorLevel% процессов, %l%

ExtractInteger(ByRef pSource, pOffset = 0, pIsSigned = false, pSize = 4) ; см. описание DllCall
{
    Loop %pSize% ; собираем целое число, складывая его байты.
        result += *(&pSource + pOffset + A_Index-1) << 8*(A_Index-1)
    if (!pIsSigned OR pSize > 4 OR result < 0x80000000)
        return result ; в этих случаях не имеет значения, со знаком число или без
    return -(0xFFFFFFFF - result + 1)
}

InsertInteger(pInteger, ByRef pDest, pOffset = 0, pSize = 4)
{
    Loop %pSize% ; копируем каждый байт целого числа в структуру как сырые двоичные данные
        DllCall("RtlFillMemory", "UInt", &pDest + pOffset + A_Index-1
        , "UInt", 1, "UChar", pInteger >> 8*(A_Index-1) & 0xFF)
}

Перейти на главную страничку сайта (список статей, файлы для скачивания)

© 2007 http://www.script-coding.com При любом использовании материалов сайта обязательна ссылка на него как на источник информации, а также сохранение целостности и авторства материалов.