51 (изменено: teadrinker, 2017-01-09 01:30:57)

Re: AHK: Самозакрытие при повторном запуске

И ещё немного, получше разобравшись в теме:

#Persistent
#SingleInstance, force
OnExit(Func("Exit"))
Return

Exit(ExitReason)  {
   if ExitReason not in Single,Reload
      Return
   
   MyPID := DllCall("GetCurrentProcessId")
   VarSetCapacity(buff, buffSize := 4096, 0)
   DllCall("Psapi\EnumProcesses", Ptr, &buff, UInt, buffSize, UIntP, bytes)
   Loop % bytes//4  {
      PID := NumGet(buff, A_Index * 4, "UInt")
      if (MyPID != PID && InStr(GetCommandLine(PID), A_ScriptFullPath))
         Process, Close, % PID
   }
}

GetCommandLine(PID)  {
   static PROCESS_QUERY_INFORMATION := 0x400, PROCESS_VM_READ := 0x10, STATUS_SUCCESS := 0
   
   VarSetCapacity(PBI, 48)
   hProc := DllCall("OpenProcess", UInt, PROCESS_QUERY_INFORMATION|PROCESS_VM_READ, Int, 0, UInt, PID, Ptr)

   (A_Is64bitOS && DllCall("IsWow64Process", Ptr, hProc, UIntP, IsWow64))
   if (!A_Is64bitOS || IsWow64)
      PtrSize := 4, szPtr := "UInt", pPtr := "UIntP", offsetCMD := 0x44
   else
      PtrSize := 8, szPtr := "Int64", pPtr := "Int64P", offsetCMD := 0x78

   if (A_PtrSize < PtrSize)  {    ; скрипт 32, процесс 64
      QueryInformationProcess := "Ntdll\NtWow64QueryInformationProcess64"
      ReadProcessMemory := "Ntdll\NtWow64ReadVirtualMemory64"
      info := 0, szPBI := 48, offsetPEB := 8
   }
   else  {
      QueryInformationProcess := "Ntdll\NtQueryInformationProcess"
      ReadProcessMemory := "ReadProcessMemory"
      if (A_PtrSize > PtrSize)    ; скрипт 64, процесс 32
         info := 26, szPBI := 8, offsetPEB := 0
      else
         info := 0, szPBI := PtrSize * 6, offsetPEB := PtrSize
   }
   if DllCall(QueryInformationProcess, Ptr, hProc, UInt, info, Ptr, &PBI, UInt, szPBI, UIntP, bytes) != STATUS_SUCCESS  {
      DllCall("CloseHandle", Ptr, hProc)
      Return
   }
   pPEB := NumGet(&PBI + offsetPEB, szPtr)
   DllCall(ReadProcessMemory, Ptr, hProc, szPtr, pPEB + PtrSize * 4, pPtr, pRUPP, szPtr, PtrSize, UIntP, bytes)
   DllCall(ReadProcessMemory, Ptr, hProc, szPtr, pRUPP + offsetCMD, pPtr, pCMD, szPtr, PtrSize, UIntP, bytes)
   DllCall(ReadProcessMemory, Ptr, hProc, szPtr, pRUPP + offsetCMD - PtrSize, UShortP, szCMD, szPtr, 2, UIntP, bytes)
   
   VarSetCapacity(buff, szCMD, 0)
   DllCall(ReadProcessMemory, Ptr, hProc, szPtr, pCMD, Ptr, &buff, szPtr, szCMD, UIntP, bytes)
   DllCall("CloseHandle", Ptr, hProc)
   Return StrGet(&buff, "UTF-16")
}

Нужно понимать, что в таком виде функция EnumProcesses перечисляет не все процессы, а QueryInformationProcess выдаёт информацию только о процессах, запущенных от имени пользователя. Для получения командной строки AHK-скриптов это не важно, а для получения информации обо всех процессах нужно добавить

SeDebugPrivilege()

SeDebugPrivilege()  {
   static PROCESS_QUERY_INFORMATION := 0x400, TOKEN_ADJUST_PRIVILEGES := 0x20, SE_PRIVILEGE_ENABLED := 0x2
   
   hProc := DllCall("OpenProcess", UInt, PROCESS_QUERY_INFORMATION, Int, false, UInt, DllCall("GetCurrentProcessId"), Ptr)
   DllCall("Advapi32\OpenProcessToken", Ptr, hProc, UInt, TOKEN_ADJUST_PRIVILEGES, PtrP, token)
   
   VarSetCapacity(TOKEN_PRIVILEGES, 16, 0)
   NumPut(1, TOKEN_PRIVILEGES, 0, "UInt")
   DllCall("Advapi32\LookupPrivilegeValue", Ptr, 0, Str, "SeDebugPrivilege", Int64P, luid)
   NumPut(luid, TOKEN_PRIVILEGES, 4, "Int64")
   NumPut(SE_PRIVILEGE_ENABLED, TOKEN_PRIVILEGES, 12, "UInt")
   DllCall("Advapi32\AdjustTokenPrivileges", Ptr, token, Int, false, Ptr, &TOKEN_PRIVILEGES, UInt, 0, Ptr, 0, Ptr, 0)
   
   DllCall("CloseHandle", Ptr, token)
   DllCall("CloseHandle", Ptr, hProc)
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg