1

Тема: AHK: Объединить 2 скрипта / Процессы

Доброго времени суток!
Нужна помощь в переносе одной функции из 1 скрипта, в мой скрипт.
Постараюсь объяснить максимально внятно.
Есть программка на AHK с GUI, в написании которой активно помогали serzh82saratov, __Михаил__ и stealzy (за что им большое спасибо)
Решил доработать в ней функцию поиска нужного мне процесса.
На текущий момент она просто ищет последние запущенные процессы после нажатия кнопки "Отследить игру" в моем GUI.
Но так как данная функция ищет часто ненужные процессы, я хочу её доработать.
Нашел почти то, что мне нужно, скрипт от teadrinker: http://forum.script-coding.com/viewtopi … 447#p40447
Он при наведении курсора на кнопку "Пуск" показывает ToolTip с названием наиболее загружающего процесса и процент процессорного времени, занимаемого данным процессом.
Мне из данной функции нужно как раз определение наиболее загружаемого процесса, и его название отображать в GroupBox'е в моем GUI.
Вот полная, доработанная версия моей программки:

#SingleInstance Force
#NoEnv
SetBatchLines -1

Name = Cam OverLay

GroupAdd, AppGroup, % Name


;Gui +ToolWindow
Gui -MaximizeBox
Gui Color, 0x000000
Gui Add, Button, x125 y50 w102 h23, 4. Подтвердить
Gui Add, ListBox, vG1 gПодтвердить hwndhListbox x25 y151 w196 h160
Gui Add, Button, gNewApp hwndhBut x125 y19 w102 h23, 3. Отследить игру
Gui Add, Button, gGames x15 y50 w102 h23, 2. Папка GAMES
Gui Add, Button, gOBS x15 y19 w102 h23, 1. Запустить OBS
Gui Add, Button, gReverse x125 y104 w102 h23, Реверс
Gui Add, Text, x18 y90 w210 h2 +0x10
Gui Font, c0xFFFFFF
Gui Add, GroupBox, x18 y134 w211 h188, Выбрать процесс
Gui Font
Gui Add, Edit, hwndhSear gGet vPoisk x17 y105 w100 h21, Поиск процесса...


for Process in ComObjGet("Winmgmts:").ExecQuery("Select * From Win32_Process")
 Txt .= Process.Caption "|"

GuiControl,, % hListbox, % Txt	; Вставить из переменной.

Gui Show, w246 h340, % Name
Return

GuiEscape:
GuiClose:
ExitApp

Games:
Run, C:\Users\Администратор\Desktop\Games
Return

OBS:
Run, C:\Program Files\obs-studio\bin\64bit\obs64.exe, C:\Program Files\obs-studio\bin\64bit\
Sleep, 4000
WinSetTitle, ahk_class Qt5152QWindowIcon, , OBS
Sleep, 1000
MouseMove, 100, 745
Sleep, 200
MouseClick, left, 100, 745
MouseClick, right, 100, 745
Sleep, 200
MouseMove, 200, 635
MouseClick, left, 200, 635
Sleep, 200
If Not ОкноБезРамокДляВебки
{
		WinMove Оконный проектор (Источник) - Cam,, 0, 0, 408, 308 ; перемещаем окошко в угол + ресайз
		WinSet Style, -0x800000, Оконный проектор (Источник) - Cam ; -рамка
		WinSet Style, -0x40000, Оконный проектор (Источник) - Cam ; -рамка
		WinSet Style, -0x400000, Оконный проектор (Источник) - Cam ; -рамка
		ОкноБезРамокДляВебки := true
}
;Sleep, 200
;WinMinimize OBS
Sleep, 200
WinActivate Cam OverLay



#IfWinActive, Ahk_Group AppGroup

; Перехват клавиши Enter в своём окне:
Enter::
KeyWait, %A_ThisHotkey%, U

ControlGetFocus, F_Now, % Name	; Получить текущий выбранный контрол.
If (F_Now = "ListBox1")		; Если фокус на списке сохранить пункт и выйти:
{
 Gui, Submit, NoHide
 ToolTip, Переменная = %G1%
 Sleep, 300
 ToolTip
 Return
}
Else If (F_Now = "Edit1")	; Поиск в списке:
{
 GoTo, Get
}

;Else
; Send, {%A_ThisHotkey%}	; Нажать Enter если нет совпадений.
Return

#If


Get:
Gui, Submit, NoHide
T=
Loop, Parse, Txt, |
{
 If InStr(A_LoopField, Poisk)
 {
  SendMessage, 390, A_Index-1, 0,, ahk_id %hListbox%	; Выделить найденный пункт.
  T := A_Index
  Break
 }
}
If !T
{
 ToolTip, Нет такого.,0,0
 Sleep, 400
}
ToolTip
Return


Подтвердить:
Gui, Submit, NoHide
;ToolTip, Пункт: %G1% ; отображение выбранного пункта
Return


Reverse:
Reverse := !Reverse
GoSub, App

If Reverse
 Sort, Txt, R D|

GuiControl,, % hListbox, |	; Очистить список.
GuiControl,, % hListbox, % Txt	; Вставить из переменной.
Return


NewApp:
Txt2 := Txt			; Резерв тек. списка.
GuiControl,, % hListbox, |	; Очистить список.
GuiControl,, % hListbox, "Ожидание..."
GuiControl, Disable, % hBut	; Блок кнопки.
GuiControl, Disable, % hSear	; Разблок поиска.
SetTimer, NewP, 1000		; Тест каждую секунду.
Return


NewP:	; Отсев новых программ.
GoSub, App
Txt_New = 
D = |
Loop, Parse, Txt, %D%
{
 If !InStr(D Txt2 D, D A_LoopField D)
  Txt_New := A_LoopField "|"
}
If Txt_New
{
 Txt := Txt_New
 SetTimer, NewP, Off		; Выключить тестер.
 GuiControl,, % hListbox, |	; Очистить список.
 GuiControl,, % hListbox, % Txt_New	; Вставить из переменной.
 GuiControl, Enable, % hBut	; Разблок кнопки.
 GuiControl, Enable, % hSear	; Разблок поиска.
}
Return

App:	; Создать список запущенных.
Txt = 
for Process in ComObjGet("Winmgmts:").ExecQuery("Select * From Win32_Process")
 Txt .= Process.Caption "|"
Return

F9:: 
 	If Not ОкноБезРамокДляИгр       
	{	
		BorderSize:=0
	    WinMove, ahk_exe %G1%,, -BorderSize, -BorderSize, 1920+2*BorderSize, 1080+2*BorderSize
		WinSet, Style, -0xC00000, ahk_exe %G1% ; убрать рамку
		ОкноБезРамокДляИгр := true
	}

;	If Not ОкноБезРамокДляВебки
;	{
;		WinMove Оконный проектор (Источник) - Cam,, 0, 0, 408, 308 ; перемещаем окошко в угол + ресайз
;		WinSet Style, -0x800000, Оконный проектор (Источник) - Cam ; -рамка
;		WinSet Style, -0x40000, Оконный проектор (Источник) - Cam ; -рамка
;		WinSet Style, -0x400000, Оконный проектор (Источник) - Cam ; -рамка
;		ОкноБезРамокДляВебки := true
;	}

;	IfWinExist ahk_class Qt5152QWindowIcon ahk_exe obs64.exe
	IfWinExist, Оконный проектор (Источник) - Cam
	{
		WinGet ExStyle, ExStyle
		if Not (ExStyle & 0x8)  ; 0x8 is WS_EX_TOPMOST. The window is always-on-top.
		{
			WinSet ExStyle, +0x20 ; чтобы клики проходили сквозь окошко
			WinSet Transparent, 255 ; прозрачность окна: 0 - максимальная, 255 - непрозрачное 
			WinSet AlwaysOnTop, On
		} else 
		 {
			WinSet ExStyle, -0x20
			WinSet Transparent, 255
			WinSet AlwaysOnTop, Off
			; переключаем режим "поверх всех" в окне игры, чтобы окошко ушло на задний план
			WinSet AlwaysOnTop, On, A
			WinSet AlwaysOnTop, Off, A
		 }
	}
Return

F12::
Run, R:\VIDEOS\РОЛИКИ НА ОБРАБОТКУ
Return

Прошу помощи в реализации данной идеи, заранее огромное спасибо!

2

Re: AHK: Объединить 2 скрипта / Процессы

Michael пишет:

Нашел почти то, что мне нужно, скрипт от teadrinker

Скрипт уже устарел, он для AHK-basic.

Michael пишет:

Мне из данной функции нужно как раз определение наиболее загружаемого процесса, и его название отображать в GroupBox'е в моем GUI.

Не совсем понятно, с чем именно не можете справиться, с определением процесса, или с отображением информации о нём?

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

3

Re: AHK: Объединить 2 скрипта / Процессы

teadrinker
Информация о нем по сути не нужна, нужно автоматическое нахождение самого прожорливого процесса после нажатия кнопки в ГУИ и вывод его в GroupBox для дальнейших манипуляций.

4 (изменено: teadrinker, 2021-02-12 14:27:51)

Re: AHK: Объединить 2 скрипта / Процессы

Вот пример, как показать в GUI:

#NoEnv
#Persistent
SetBatchLines, -1

RunAsAdmin(true)
if SetPrivilege("SeDebugPrivilege") != 0
   throw "Failed to set debug privelege"

Gui, % "+E" . (WS_EX_COMPOSITED := 0x2000000) | (WS_EX_LAYERED := 0x80000)
Gui, Add, Text, vProcessName w170, Name:
Gui, Add, Text, vPID y+5 wp, PID:
Gui, Add, Text, vLoad y+5 wp, Load:
Gui, Add, Button, y+10 x+-100 gShowMaxLoad, Show Max Load Process
Gui, Show
Return

GuiClose:
   ExitApp

ShowMaxLoad:
   SortedProcesses := GetSortedProcessesByLoad()
   if MaxLoad := SortedProcesses[1] {
      GuiControl,, ProcessName, % "Name: " . MaxLoad.ProcessName
      GuiControl,, PID        , %  "PID: " . MaxLoad.PID
      GuiControl,, Load       , % "Load: " . Round(MaxLoad.Load, 2) . "%"
   }
   SetTimer, ShowMaxLoad, -1000
   Return
   
GetSortedProcessesByLoad() {
   static LoadByPid := {}, prevSystemTime := ""
   Processes := WTSEnumProcesses()
   systemTime := GetSystemTimes()
   for k, v in Processes {
      processTime := GetProcessTimes(v.PID)
      if LoadByPid[v.PID]
         v.Load := 100*(processTime - LoadByPid[v.PID]) / (systemTime - prevSystemTime)
      LoadByPid[v.PID] := processTime
   }
   if prevSystemTime
      SortedProcesses := SortByLoad(Processes)
   prevSystemTime := systemTime
   Return SortedProcesses
}

WTSEnumProcesses() {
   DllCall("Wtsapi32\WTSEnumerateProcesses", "Ptr", 0, "UInt", 0, "UInt", 1, "PtrP", pProcessInfo, "PtrP", count)
   Processes := []
   pPtr := pProcessInfo
   Loop % count {
      Processes.Push({ PID:         NumGet(pPtr + 4, "UInt")
                     , ProcessName: StrGet(NumGet(pPtr + 8)) })
      pPtr += A_PtrSize = 4 ? 16 : 24
   }
   DllCall("Wtsapi32\WTSFreeMemory", "Ptr", pProcessInfo)
   Return Processes
}

RunAsAdmin(exitIfNotAdmin := false) {
   commandLine := DllCall("GetCommandLine", "str")
   isRestarted := !!RegExMatch(commandLine, " /restart(?!\S)")
   while !( A_IsAdmin || isRestarted ) {
      try Run, % "*RunAs " . (A_IsCompiled ? """" . A_ScriptFullPath . """ /restart"
                                           : """" . A_AhkPath . """ /restart """ . A_ScriptFullPath . """")
      catch
         break 
      ExitApp
   }
   if !A_IsAdmin {
      MsgBox, Failed to run the script as admin!
      if exitIfNotAdmin
         ExitApp
   }
}

SetPrivilege(privilege, enable := true) {
   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)
   
   DllCall("Advapi32\LookupPrivilegeValue", "Ptr", 0, "Str", privilege, "Int64P", luid)
   VarSetCapacity(TOKEN_PRIVILEGES, 16, 0)
   NumPut(1, TOKEN_PRIVILEGES, "UInt")
   NumPut(luid, TOKEN_PRIVILEGES, 4, "Int64")
   NumPut(SE_PRIVILEGE_ENABLED, TOKEN_PRIVILEGES, 12, "UInt")
   DllCall("Advapi32\AdjustTokenPrivileges", "Ptr", token, "Int", !enable, "Ptr", &TOKEN_PRIVILEGES, "UInt", 0, "Ptr", 0, "Ptr", 0)
   res := A_LastError
   DllCall("CloseHandle", "Ptr", token)
   DllCall("CloseHandle", "Ptr", hProc)
   Return res  ; success — 0
}

GetProcessTimes(PID) {
   hProc := DllCall("OpenProcess", "UInt", PROCESS_QUERY_INFORMATION := 0x400, "int", 0, "UInt", PID, "Ptr")
   DllCall("GetProcessTimes", "Ptr", hProc, "Int64P", CreationTime, "Int64P", ExitTime, "Int64P", KernelTime, "Int64P", UserTime)
   DllCall("CloseHandle", "Ptr", hProc)
   Return KernelTime + UserTime
}

GetSystemTimes() {
   DllCall("GetSystemTimes", "Int64P", IdleTime, "Int64P", KernelTime, "Int64P", UserTime)
   Return KernelTime + UserTime
}

SortByLoad(Processes) {
   str := ""
   for k, v in Processes {
      if v.PID
         str .= (str ? "`n" : "") . v.Load . "|" . v.ProcessName . "|" . v.PID
   }
   Sort, str, N R
   SortedProcesses := []
   Loop, parse, str, `n
   {
      RegExMatch(A_LoopField, "(.*)\|(.*)\|(.+)", m)
      SortedProcesses.Push({Load: m1, ProcessName: m2, PID: m3})
   }
   Return SortedProcesses
}

Как именно вы хотели вывести в GroupBox, я не совсем понял, надеюсь, сообразите.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

5 (изменено: Michael, 2021-02-12 17:41:21)

Re: AHK: Объединить 2 скрипта / Процессы

teadrinker
Сделал проверку с выводом в GroupBox в вашем скрипте, всё работает:

#NoEnv
#Persistent
SetBatchLines, -1

RunAsAdmin(true)
if SetPrivilege("SeDebugPrivilege") != 0
   throw "Failed to set debug privelege"

Gui, % "+E" . (WS_EX_COMPOSITED := 0x2000000) | (WS_EX_LAYERED := 0x80000)
Gui Add, GroupBox, x18 y134 w211 h188, Выбрать процесс
Gui Add, ListBox, vG1  hwndhListbox x25 y151 w196 h160
;Gui, Add, Text, vProcessName w170, Name:
;Gui, Add, Text, vPID y+5 wp, PID:
;Gui, Add, Text, vLoad y+5 wp, Load:
Gui, Add, Button, y+10 x+-100 gShowMaxLoad, Show Max Load Process
Gui, Show
Return

GuiClose:
   ExitApp

ShowMaxLoad:
   SortedProcesses := GetSortedProcessesByLoad()
   if MaxLoad := SortedProcesses[1] {
      GuiControl,, G1, % " " . MaxLoad.ProcessName
;      GuiControl,, PID        , %  "PID: " . MaxLoad.PID
;      GuiControl,, Load       , % "Load: " . Round(MaxLoad.Load, 2) . "%"
   }
   SetTimer, ShowMaxLoad, +1000
   Return
   
GetSortedProcessesByLoad() {
   static LoadByPid := {}, prevSystemTime := ""
   Processes := WTSEnumProcesses()
   systemTime := GetSystemTimes()
   for k, v in Processes {
      processTime := GetProcessTimes(v.PID)
      if LoadByPid[v.PID]
         v.Load := 100*(processTime - LoadByPid[v.PID]) / (systemTime - prevSystemTime)
      LoadByPid[v.PID] := processTime
   }
   if prevSystemTime
      SortedProcesses := SortByLoad(Processes)
   prevSystemTime := systemTime
   Return SortedProcesses
}

WTSEnumProcesses() {
   DllCall("Wtsapi32\WTSEnumerateProcesses", "Ptr", 0, "UInt", 0, "UInt", 1, "PtrP", pProcessInfo, "PtrP", count)
   Processes := []
   pPtr := pProcessInfo
   Loop % count {
      Processes.Push({ PID:         NumGet(pPtr + 4, "UInt")
                     , ProcessName: StrGet(NumGet(pPtr + 8)) })
      pPtr += A_PtrSize = 4 ? 16 : 24
   }
   DllCall("Wtsapi32\WTSFreeMemory", "Ptr", pProcessInfo)
   Return Processes
}

RunAsAdmin(exitIfNotAdmin := false) {
   commandLine := DllCall("GetCommandLine", "str")
   isRestarted := !!RegExMatch(commandLine, " /restart(?!\S)")
   while !( A_IsAdmin || isRestarted ) {
      try Run, % "*RunAs " . (A_IsCompiled ? """" . A_ScriptFullPath . """ /restart"
                                           : """" . A_AhkPath . """ /restart """ . A_ScriptFullPath . """")
      catch
         break 
      ExitApp
   }
   if !A_IsAdmin {
      MsgBox, Failed to run the script as admin!
      if exitIfNotAdmin
         ExitApp
   }
}

SetPrivilege(privilege, enable := true) {
   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)
   
   DllCall("Advapi32\LookupPrivilegeValue", "Ptr", 0, "Str", privilege, "Int64P", luid)
   VarSetCapacity(TOKEN_PRIVILEGES, 16, 0)
   NumPut(1, TOKEN_PRIVILEGES, "UInt")
   NumPut(luid, TOKEN_PRIVILEGES, 4, "Int64")
   NumPut(SE_PRIVILEGE_ENABLED, TOKEN_PRIVILEGES, 12, "UInt")
   DllCall("Advapi32\AdjustTokenPrivileges", "Ptr", token, "Int", !enable, "Ptr", &TOKEN_PRIVILEGES, "UInt", 0, "Ptr", 0, "Ptr", 0)
   res := A_LastError
   DllCall("CloseHandle", "Ptr", token)
   DllCall("CloseHandle", "Ptr", hProc)
   Return res  ; success — 0
}

GetProcessTimes(PID) {
   hProc := DllCall("OpenProcess", "UInt", PROCESS_QUERY_INFORMATION := 0x400, "int", 0, "UInt", PID, "Ptr")
   DllCall("GetProcessTimes", "Ptr", hProc, "Int64P", CreationTime, "Int64P", ExitTime, "Int64P", KernelTime, "Int64P", UserTime)
   DllCall("CloseHandle", "Ptr", hProc)
   Return KernelTime + UserTime
}

GetSystemTimes() {
   DllCall("GetSystemTimes", "Int64P", IdleTime, "Int64P", KernelTime, "Int64P", UserTime)
   Return KernelTime + UserTime
}

SortByLoad(Processes) {
   str := ""
   for k, v in Processes {
      if v.PID
         str .= (str ? "`n" : "") . v.Load . "|" . v.ProcessName . "|" . v.PID
   }
   Sort, str, N R
   SortedProcesses := []
   Loop, parse, str, `n
   {
      RegExMatch(A_LoopField, "(.*)\|(.*)\|(.+)", m)
      SortedProcesses.Push({Load: m1, ProcessName: m2, PID: m3})
   }
   Return SortedProcesses
}

2 проблемки:
1. Самый основной. Он показывает только запущенные ДО нажатия кнопки процессы, если я запущу новый EXEшник (который по загрузке должен быть на 1 месте и как раз выводиться, его там не будет, а будет ЕХЕшник из старого списка "самых жрущих ЦП"), хоть и Таймер обновляет каждую секунду, новых процессов он не цепляет.
2. Таймер, не пойму как его убрать, мне нужно просто по нажатию на кнопку выводить MaxLoadProcess, без обновления, для обновления нужно просто еще раз нажать кнопку.

UPDATE!!!
Обе вышеописанные проблемы решены:

#NoEnv
#Persistent
SetBatchLines, -1

RunAsAdmin(true)
if SetPrivilege("SeDebugPrivilege") != 0
   throw "Failed to set debug privelege"

Gui, % "+E" . (WS_EX_COMPOSITED := 0x2000000) | (WS_EX_LAYERED := 0x80000)
Gui Add, GroupBox, x18 y134 w211 h188, Выбрать процесс
Gui Add, ListBox, vG1  hwndhListbox x25 y151 w196 h160
;Gui, Add, Text, vProcessName w170, Name:
;Gui, Add, Text, vPID y+5 wp, PID:
;Gui, Add, Text, vLoad y+5 wp, Load:
Gui, Add, Button, y+10 x+-100 gShowMaxLoad, Show Max Load Process
Gui, Show
Return

GuiClose:
   ExitApp

ShowMaxLoad:
   SortedProcesses := GetSortedProcessesByLoad()
   MaxLoad := SortedProcesses[1] 
      GuiControl,, G1, % "" . MaxLoad.ProcessName
   Return
   
GetSortedProcessesByLoad() {
   static LoadByPid := {}, prevSystemTime := ""
   Processes := WTSEnumProcesses()
   systemTime := GetSystemTimes()
   for k, v in Processes {
      processTime := GetProcessTimes(v.PID)
      if LoadByPid[v.PID]
         v.Load := 100*(processTime - LoadByPid[v.PID]) / (systemTime - prevSystemTime)
      LoadByPid[v.PID] := processTime
   }
   if prevSystemTime
      SortedProcesses := SortByLoad(Processes)
   prevSystemTime := systemTime
   Return SortedProcesses
}

WTSEnumProcesses() {
   DllCall("Wtsapi32\WTSEnumerateProcesses", "Ptr", 0, "UInt", 0, "UInt", 1, "PtrP", pProcessInfo, "PtrP", count)
   Processes := []
   pPtr := pProcessInfo
   Loop % count {
      Processes.Push({ PID:         NumGet(pPtr + 4, "UInt")
                     , ProcessName: StrGet(NumGet(pPtr + 8)) })
      pPtr += A_PtrSize = 4 ? 16 : 24
   }
   DllCall("Wtsapi32\WTSFreeMemory", "Ptr", pProcessInfo)
   Return Processes
}

RunAsAdmin(exitIfNotAdmin := false) {
   commandLine := DllCall("GetCommandLine", "str")
   isRestarted := !!RegExMatch(commandLine, " /restart(?!\S)")
   while !( A_IsAdmin || isRestarted ) {
      try Run, % "*RunAs " . (A_IsCompiled ? """" . A_ScriptFullPath . """ /restart"
                                           : """" . A_AhkPath . """ /restart """ . A_ScriptFullPath . """")
      catch
         break 
      ExitApp
   }
   if !A_IsAdmin {
      MsgBox, Failed to run the script as admin!
      if exitIfNotAdmin
         ExitApp
   }
}

SetPrivilege(privilege, enable := true) {
   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)
   
   DllCall("Advapi32\LookupPrivilegeValue", "Ptr", 0, "Str", privilege, "Int64P", luid)
   VarSetCapacity(TOKEN_PRIVILEGES, 16, 0)
   NumPut(1, TOKEN_PRIVILEGES, "UInt")
   NumPut(luid, TOKEN_PRIVILEGES, 4, "Int64")
   NumPut(SE_PRIVILEGE_ENABLED, TOKEN_PRIVILEGES, 12, "UInt")
   DllCall("Advapi32\AdjustTokenPrivileges", "Ptr", token, "Int", !enable, "Ptr", &TOKEN_PRIVILEGES, "UInt", 0, "Ptr", 0, "Ptr", 0)
   res := A_LastError
   DllCall("CloseHandle", "Ptr", token)
   DllCall("CloseHandle", "Ptr", hProc)
   Return res  ; success — 0
}

GetProcessTimes(PID) {
   hProc := DllCall("OpenProcess", "UInt", PROCESS_QUERY_INFORMATION := 0x400, "int", 0, "UInt", PID, "Ptr")
   DllCall("GetProcessTimes", "Ptr", hProc, "Int64P", CreationTime, "Int64P", ExitTime, "Int64P", KernelTime, "Int64P", UserTime)
   DllCall("CloseHandle", "Ptr", hProc)
   Return KernelTime + UserTime
}

GetSystemTimes() {
   DllCall("GetSystemTimes", "Int64P", IdleTime, "Int64P", KernelTime, "Int64P", UserTime)
   Return KernelTime + UserTime
}

SortByLoad(Processes) {
   str := ""
   for k, v in Processes {
      if v.PID
         str .= (str ? "`n" : "") . v.Load . "|" . v.ProcessName . "|" . v.PID
   }
   Sort, str, N R
   SortedProcesses := []
   Loop, parse, str, `n
   {
      RegExMatch(A_LoopField, "(.*)\|(.*)\|(.+)", m)
      SortedProcesses.Push({Load: m1, ProcessName: m2, PID: m3})
   }
   Return SortedProcesses
}

Появился еще один нюанс, на кнопку почему то надо нажимать дважды (только в начале), чтобы отобразить процесс, после двойного клика процессы отображаются и по 1 клику. Как исправить - не пойму.

6

Re: AHK: Объединить 2 скрипта / Процессы

После первого нажатия скрипт не может оценить загрузку процесса, ему нужно взять два состояния, текущее и предыдущее, и посчитать разницу.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

7

Re: AHK: Объединить 2 скрипта / Процессы

То-есть, в вашем текущем варианте скрипт считает разницу между состоянием, когда вы нажали на кнопку последний раз и когда предыдущий. Если вы нажмёте кнопку второй раз через полчаса, буде выдан процесс, который забрал наибольшее процессорное время за эти полчаса, хотя в данный момент у него может быть нулевая загрузка.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

8

Re: AHK: Объединить 2 скрипта / Процессы

teadrinker

Жаль нет пояснений, например что за навороченная функция админки - 'RunAsAdmin'?
Для чего повышение (я так понял) привилегий - 'SetPrivilege'? От администратора запуск будет работать иначе?

Win10x64, AHK v1.1.37.01 (Unicode 64-bit) | AHK-Wiki | Переменные и выражения | RegEx101

9

Re: AHK: Объединить 2 скрипта / Процессы

Функция, которая проверяет, запущен ли скрипт от админа, и если нет, то перезапускает от админа, ничего особо навороченного там нет.
Без повышения привилегий не все системные процессы будут доступны, даже если скрипт запущен от админа.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

10

Re: AHK: Объединить 2 скрипта / Процессы

Обычный запуск от админа у меня без использования цикла.

+ открыть спойлер
Admin:
full_command_line := DllCall("GetCommandLine", "str")
If Not (A_IsAdmin or RegExMatch(full_command_line, " /restart(?!\S)"))
{
 Try
 {
  If A_IsCompiled
 RunWait *RunAs "%A_ScriptFullPath%" /restart
  Else
 RunWait *RunAs "%A_AhkPath%" /restart "%A_ScriptFullPath%"
 }
}
If Not A_IsAdmin
 Tool("Не удалось получить права Администратора.")
; MsgBox, Не удалось получить права Администратора.
Return
Win10x64, AHK v1.1.37.01 (Unicode 64-bit) | AHK-Wiki | Переменные и выражения | RegEx101

11

Re: AHK: Объединить 2 скрипта / Процессы

Там нет цикла, это просто приём. У вас примерно то же самое, но нет опции exitIfNotAdmin. Но RunWait там точно не нужен.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

12 (изменено: teadrinker, 2021-02-13 00:05:58)

Re: AHK: Объединить 2 скрипта / Процессы

Вот полноценный вариант скрипта, показывающего несколько процессов с наибольшей загрузкой.

#NoEnv
SetBatchLines, -1

processCount := 5 ; how many processes to show

RunAsAdmin(true)
if SetPrivilege("SeDebugPrivilege") != 0
   throw "Failed to set debug privelege"

hIL := IL_Create(processCount)

LVS_EX_DOUBLEBUFFER := 0x10000
Gui, +AlwaysOnTop
Gui, Font, s12, Calibri
Gui, Add, ListView, R%processCount% Grid vLV w285 LV%LVS_EX_DOUBLEBUFFER%, Name|PID|CPU, `%
LV_SetImageList(hIL, 1)
Loop % processCount
   LV_Add()
for k, v in [160, 50, 70]
   LV_ModifyCol(k, v)
ShowMaxLoad(processCount, hIL)
Gui, Show
Return

GuiClose:
   ExitApp
   
ShowMaxLoad(processCount, hIL) {
   static iconCount := 0, Icons := {}
   wholeLoad := 0
   for k, Process in GetSortedProcessesByLoad() {
      if (k <= processCount) {
         imagePath := GetProcessImageName( Process.PID )
         if !Icons.HasKey(imagePath) {
            Icons[imagePath] := ++iconCount
            IL_Add(hIL, "HICON:" . GetSysImgListIcon(imagePath).HICON)
         }
         LV_GetText(PID, A_Index, 2), LV_GetText(Load, A_Index, 3)
         if !(Process.PID = PID && Process.Load = Load)
            LV_Modify(A_Index, "Icon" . Icons[imagePath], Process.ProcessName, Process.PID, Round(Process.Load, 2))
      }
      wholeLoad += Process.Load
   }
   Gui, Show, NA, % "CPU: " . Round(wholeLoad, 2) . "%"
   Timer := Func(A_ThisFunc).Bind(processCount, hIL)
   SetTimer, % Timer, -1000
}

GetSortedProcessesByLoad() {
   static LoadByPid := {}, prevSystemTime := ""
   Processes := WTSEnumProcesses()
   systemTime := GetSystemTimes()
   for k, v in Processes {
      processTime := GetProcessTimes(v.PID)
      if LoadByPid[v.PID]
         v.Load := 100*(processTime - LoadByPid[v.PID]) / (systemTime - prevSystemTime)
      LoadByPid[v.PID] := processTime
   }
   if prevSystemTime
      SortedProcesses := SortByLoad(Processes)
   prevSystemTime := systemTime
   Return SortedProcesses
}

WTSEnumProcesses() {
   DllCall("Wtsapi32\WTSEnumerateProcesses", "Ptr", 0, "UInt", 0, "UInt", 1, "PtrP", pProcessInfo, "PtrP", count)
   Processes := []
   pPtr := pProcessInfo
   Loop % count {
      Processes.Push({ PID:         NumGet(pPtr + 4, "UInt")
                     , ProcessName: StrGet(NumGet(pPtr + 8)) })
      pPtr += A_PtrSize = 4 ? 16 : 24
   }
   DllCall("Wtsapi32\WTSFreeMemory", "Ptr", pProcessInfo)
   Return Processes
}

RunAsAdmin(exitIfNotAdmin := false) {
   commandLine := DllCall("GetCommandLine", "str")
   isRestarted := !!RegExMatch(commandLine, " /restart(?!\S)")
   while !( A_IsAdmin || isRestarted ) {
      try Run, % "*RunAs " . (A_IsCompiled ? """" . A_ScriptFullPath . """ /restart"
                                           : """" . A_AhkPath . """ /restart """ . A_ScriptFullPath . """")
      catch
         break 
      ExitApp
   }
   if !A_IsAdmin {
      MsgBox, Failed to run the script as admin!
      if exitIfNotAdmin
         ExitApp
   }
}

SetPrivilege(privilege, enable := true) {
   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)
   
   DllCall("Advapi32\LookupPrivilegeValue", "Ptr", 0, "Str", privilege, "Int64P", luid)
   VarSetCapacity(TOKEN_PRIVILEGES, 16, 0)
   NumPut(1, TOKEN_PRIVILEGES, "UInt")
   NumPut(luid, TOKEN_PRIVILEGES, 4, "Int64")
   NumPut(SE_PRIVILEGE_ENABLED, TOKEN_PRIVILEGES, 12, "UInt")
   DllCall("Advapi32\AdjustTokenPrivileges", "Ptr", token, "UInt", !enable, "Ptr", &TOKEN_PRIVILEGES, "UInt", 0, "Ptr", 0, "Ptr", 0)
   res := A_LastError
   DllCall("CloseHandle", "Ptr", token)
   DllCall("CloseHandle", "Ptr", hProc)
   Return res  ; success — 0
}

GetProcessTimes(PID) {
   hProc := DllCall("OpenProcess", "UInt", PROCESS_QUERY_INFORMATION := 0x400, "int", 0, "UInt", PID, "Ptr")
   DllCall("GetProcessTimes", "Ptr", hProc, "Int64P", CreationTime, "Int64P", ExitTime, "Int64P", KernelTime, "Int64P", UserTime)
   DllCall("CloseHandle", "Ptr", hProc)
   Return KernelTime + UserTime
}

GetSystemTimes() {
   DllCall("GetSystemTimes", "Int64P", IdleTime, "Int64P", KernelTime, "Int64P", UserTime)
   Return KernelTime + UserTime
}

SortByLoad(Processes) {
   str := ""
   for k, v in Processes {
      if v.PID
         str .= (str ? "`n" : "") . v.Load . "|" . v.ProcessName . "|" . v.PID
   }
   Sort, str, N R
   SortedProcesses := []
   Loop, parse, str, `n
   {
      RegExMatch(A_LoopField, "(.*)\|(.*)\|(.+)", m)
      SortedProcesses.Push({Load: m1, ProcessName: m2, PID: m3})
   }
   Return SortedProcesses
}

GetProcessImageName(PID) {
   static PROCESS_QUERY_INFORMATION := 0x400, MAX_PATH := 260
   hProc := DllCall("OpenProcess", "UInt", PROCESS_QUERY_INFORMATION, "Int", 0, "UInt", PID, "Ptr")
   VarSetCapacity(pathBuff, (chars := MAX_PATH) << !!A_IsUnicode, 0)
   DllCall("QueryFullProcessImageName", "Ptr", hProc, "UInt", 0, "Str", pathBuff, "UIntP", chars)
   DllCall("CloseHandle", "Ptr", hProc)
   Return pathBuff
}

GetSysImgListIcon(Path, Size := "SYSSMALL", Overlay := "")  {
   static SHIL := { LARGE: 0x00, SMALL: 0x01, EXTRALARGE: 0x02, SYSSMALL: 0x03, JUMBO: 0x04 }  ; возможные размеры
        , AW := A_IsUnicode ? "W" : "A"
        , cbSFI := A_PtrSize + 8 + (340 << A_IsUnicode)
        , IID_IIL_Str := "{46EB5926-582E-4017-9FDF-E8998DAA0950}"
        , SHGFI := {SYSICONINDEX: 0x4000, PIDL: 0x8}
        , SHGIOI := {SHARE: 0x0FFFFFFF, LINK: 0x0FFFFFFE, SLOWFILE: 0x0FFFFFFD, DEFAULT: 0x0FFFFFFC}
        , ILD_IMAGE := 0x20
   
   VarSetCapacity(IID_IIL, 16, 0) ; IID
   DllCall("Ole32\IIDFromString", "WStr", IID_IIL_Str, "Ptr", &IID_IIL, "UInt")
   
   HMOD := DllCall("GetModuleHandle", "Str", "shell32.dll", "UPtr")
   FileIconInit := DllCall("GetProcAddress", "Ptr", HMOD, "Ptr", 660, "UPtr")
   DllCall(FileIconInit, "UInt", True, "UInt")
   
   VarSetCapacity(SFI, cbSFI, 0) ; SHFILEINFO
   DllCall("Shell32\SHParseDisplayName", "Str", path, "Ptr", 0, "PtrP", ppidl, "UInt", 0, "UIntP", 0)
   Flags := SHGFI.PIDL | SHGFI.SYSICONINDEX
   if !DllCall("Shell32\SHGetFileInfo" . AW, "Ptr", ppidl, "UInt", 0, "Ptr", &SFI, "UInt", cbSFI, "UInt", Flags, "UPtr")
      Return False
   
   IconIndex := NumGet(SFI, A_PtrSize, "Int")
   if DllCall("Shell32\SHGetImageList", "Int", SHIL[Size], "Ptr", &IID_IIL, "PtrP", IIL, "UInt")
      Return False
   
   Flags := ILD_IMAGE
   if SHGIOI.HasKey(Overlay)
   && (IOV := DllCall("Shell32\SHGetIconOverlayIndex", "Ptr", 0, "UInt", SHGIOI[Overlay], "Int")) >= 0
      Flags |= IOV << 8
      
   DllCall("Comctl32\ImageList_GetIconSize", "Ptr", IIL, "IntP", CX, "IntP", CY, "UInt")
   hIcon := DllCall("Comctl32\ImageList_GetIcon", "Ptr", IIL, "Int", IconIndex, "UInt", Flags, "UPtr")
   
   Return { HICON: hIcon, W: CX, H: CY }
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

13

Re: AHK: Объединить 2 скрипта / Процессы

Немного подправил, убрал мерцание (заметно на Windows 7).

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

14

Re: AHK: Объединить 2 скрипта / Процессы

teadrinker пишет:

То-есть, в вашем текущем варианте скрипт считает разницу между состоянием, когда вы нажали на кнопку последний раз и когда предыдущий. Если вы нажмёте кнопку второй раз через полчаса, буде выдан процесс, который забрал наибольшее процессорное время за эти полчаса, хотя в данный момент у него может быть нулевая загрузка.

Понял, а возможно ли полученный процесс вывести в переменную или куда-нибудь ещё, чтобы работать с именем найденного процесса в других функциях? Если да, то как?

15

Re: AHK: Объединить 2 скрипта / Процессы

myVar := MaxLoad.ProcessName
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

16

Re: AHK: Объединить 2 скрипта / Процессы

teadrinker пишет:
myVar := MaxLoad.ProcessName

Пытаюсь использовать данный пример - пока не выходит.

Не работает с переменной:

ButtonПодтвердить:
myVar := MaxLoad.ProcessName[1]
Gui, Submit, NoHide
;ToolTip, Пункт: %G1% ; отображение выбранного пункта
WinActivate, ahk_exe %myVar%
Return

Работает, без переменной, если прописать ЕХЕшник вручную:

ButtonПодтвердить:
;myVar := MaxLoad.ProcessName[1]
Gui, Submit, NoHide
;ToolTip, Пункт: %G1% ; отображение выбранного пункта
WinActivate, ahk_exe firefox.exe
Return
+ Если нужен полный код
#SingleInstance Force
#NoEnv
SetBatchLines -1

Name = Cam OverLay

GroupAdd, AppGroup, % Name

;Gui +AlwaysOnTop
Gui -MaximizeBox
Gui Color, 0x000000
Gui Add, Button, x125 y50 w102 h23, Подтвердить
Gui Add, ListBox, vG1 gButtonПодтвердить hwndhListbox x25 y151 w196 h160
Gui Add, Button, gNewApp hwndhBut x125 y19 w102 h23, 3. Отследить игру
Gui Add, Button, gGames x15 y50 w102 h23, 2. Папка GAMES
Gui Add, Button, gOBS x15 y19 w102 h23, 1. Запустить OBS
Gui Add, Button, gReverse x125 y104 w102 h23, Реверс
Gui Add, Text, x18 y90 w210 h2 +0x10
Gui Font, c0xFFFFFF
Gui Add, GroupBox, x18 y134 w211 h188, Выбрать процесс
Gui Font
Gui Add, Edit, hwndhSear gGet vPoisk x17 y105 w100 h21, Поиск процесса...

for Process in ComObjGet("Winmgmts:").ExecQuery("Select * From Win32_Process")
 Txt .= Process.Caption "|"
GetSortedProcessesByLoad()
GuiControl,, % hListbox, % Txt	; Вставить из переменной.

Gui Show, w246 h340, % Name
Return

GuiEscape:
GuiClose:
ExitApp

Games:
Run, C:\Users\Администратор\Desktop\Games
Return

OBS:
Run, C:\Program Files\obs-studio\bin\64bit\obs64.exe, C:\Program Files\obs-studio\bin\64bit\
Sleep, 9000
WinSetTitle, ahk_class Qt5152QWindowIcon, , OBS
Sleep, 1000
MouseMove, 100, 760
Sleep, 200
MouseClick, left, 100, 760
MouseClick, right, 100, 760
Sleep, 200
MouseMove, 150, 650
MouseClick, left, 150, 650
Sleep, 200
If Not ОкноБезРамокДляВебки
{
		WinMove Оконный проектор (Источник) - Cam,, 0, 0, 408, 308 ; перемещаем окошко в угол + ресайз
		WinSet Style, -0x800000, Оконный проектор (Источник) - Cam ; -рамка
		WinSet Style, -0x40000, Оконный проектор (Источник) - Cam ; -рамка
		WinSet Style, -0x400000, Оконный проектор (Источник) - Cam ; -рамка
		ОкноБезРамокДляВебки := true
}
Sleep, 200
WinActivate Cam OverLay



#IfWinActive, Ahk_Group AppGroup

; Перехват клавиши Enter в своём окне:
Enter::
KeyWait, %A_ThisHotkey%, U

ControlGetFocus, F_Now, % Name	; Получить текущий выбранный контрол.
If (F_Now = "ListBox1")		; Если фокус на списке сохранить пункт и выйти:
{
 Gui, Submit, NoHide
 ToolTip, Переменная = %G1%
 Sleep, 300
 ToolTip
 Return
}
Else If (F_Now = "Edit1")	; Поиск в списке:
{
 GoTo, Get
}

;Else
; Send, {%A_ThisHotkey%}	; Нажать Enter если нет совпадений.
Return

#If


Get:
Gui, Submit, NoHide
T=
Loop, Parse, Txt, |
{
 If InStr(A_LoopField, Poisk)
 {
  SendMessage, 390, A_Index-1, 0,, ahk_id %hListbox%	; Выделить найденный пункт.
  T := A_Index
  Break
 }
}
If !T
{
 ToolTip, Нет такого.,0,0
 Sleep, 400
}
ToolTip
Return



ButtonПодтвердить:
myVar := MaxLoad.ProcessName[1]
Gui, Submit, NoHide
;ToolTip, Пункт: %G1% ; отображение выбранного пункта
WinActivate, ahk_exe %myVar%
Return


Reverse:
Reverse := !Reverse
GoSub, App

If Reverse
 Sort, Txt, R D|

GuiControl,, % hListbox, |	; Очистить список.
GuiControl,, % hListbox, % Txt	; Вставить из переменной.
Return


NewApp_Old:
Txt2 := Txt			; Резерв тек. списка.
GuiControl,, % hListbox, |	; Очистить список.
GuiControl,, % hListbox, Ожидание...
GuiControl, Disable, % hBut	; Блок кнопки.
GuiControl, Disable, % hSear	; Разблок поиска.
SetTimer, NewP, 1000		; Тест каждую секунду.
Return


NewP:	; Отсев новых программ.
   SortedProcesses := GetSortedProcessesByLoad()
   MaxLoad := SortedProcesses[1]
   GuiControl,, G1, % "|"        ; Очистить перед добавлением процесса.
   GuiControl,, G1, % "" . MaxLoad.ProcessName
   Return

;-------------------------------------------------------------------------------------------------------

; Обновлённый участок:
NewApp:	; Запуск / Стоп таймера - кнопка.
SW++
If !Mod(SW,2)
 GoTo, Stop

GuiControl,, G1, % "|"        ; Очистить перед добавлением процесса.
GuiControl,, G1, Ожидание...
GuiControl,, % hBut, 3. Остановить
GuiControl, Disable, % hSear	; Блок поиска.
SetTimer, NewP, 1000		; Тест каждую секунду.
Return

Stop:
GuiControl,, % hBut, 3. Отследить игру
GuiControl, Enable, % hSear	; Разблок поиска.
SetTimer, NewP, Off		; Выкл. обновление.
Return

;-------------------------------------------------------------------------------------------------------


GetSortedProcessesByLoad() {
   static LoadByPid := {}, prevSystemTime := ""
   Processes := WTSEnumProcesses()
   systemTime := GetSystemTimes()
   for k, v in Processes {
      processTime := GetProcessTimes(v.PID)
      if LoadByPid[v.PID]
         v.Load := 100*(processTime - LoadByPid[v.PID]) / (systemTime - prevSystemTime)
      LoadByPid[v.PID] := processTime
   }
   if prevSystemTime
      SortedProcesses := SortByLoad(Processes)
   prevSystemTime := systemTime
   Return SortedProcesses
}

WTSEnumProcesses() {
   DllCall("Wtsapi32\WTSEnumerateProcesses", "Ptr", 0, "UInt", 0, "UInt", 1, "PtrP", pProcessInfo, "PtrP", count)
   Processes := []
   pPtr := pProcessInfo
   Loop % count {
      Processes.Push({ PID:         NumGet(pPtr + 4, "UInt")
                     , ProcessName: StrGet(NumGet(pPtr + 8)) })
      pPtr += A_PtrSize = 4 ? 16 : 24
   }
   DllCall("Wtsapi32\WTSFreeMemory", "Ptr", pProcessInfo)
   Return Processes
}

RunAsAdmin(exitIfNotAdmin := false) {
   commandLine := DllCall("GetCommandLine", "str")
   isRestarted := !!RegExMatch(commandLine, " /restart(?!\S)")
   while !( A_IsAdmin || isRestarted ) {
      try Run, % "*RunAs " . (A_IsCompiled ? """" . A_ScriptFullPath . """ /restart"
                                           : """" . A_AhkPath . """ /restart """ . A_ScriptFullPath . """")
      catch
         break 
      ExitApp
   }
   if !A_IsAdmin {
      MsgBox, Failed to run the script as admin!
      if exitIfNotAdmin
         ExitApp
   }
}

SetPrivilege(privilege, enable := true) {
   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)
   
   DllCall("Advapi32\LookupPrivilegeValue", "Ptr", 0, "Str", privilege, "Int64P", luid)
   VarSetCapacity(TOKEN_PRIVILEGES, 16, 0)
   NumPut(1, TOKEN_PRIVILEGES, "UInt")
   NumPut(luid, TOKEN_PRIVILEGES, 4, "Int64")
   NumPut(SE_PRIVILEGE_ENABLED, TOKEN_PRIVILEGES, 12, "UInt")
   DllCall("Advapi32\AdjustTokenPrivileges", "Ptr", token, "Int", !enable, "Ptr", &TOKEN_PRIVILEGES, "UInt", 0, "Ptr", 0, "Ptr", 0)
   res := A_LastError
   DllCall("CloseHandle", "Ptr", token)
   DllCall("CloseHandle", "Ptr", hProc)
   Return res  ; success — 0
}

GetProcessTimes(PID) {
   hProc := DllCall("OpenProcess", "UInt", PROCESS_QUERY_INFORMATION := 0x400, "int", 0, "UInt", PID, "Ptr")
   DllCall("GetProcessTimes", "Ptr", hProc, "Int64P", CreationTime, "Int64P", ExitTime, "Int64P", KernelTime, "Int64P", UserTime)
   DllCall("CloseHandle", "Ptr", hProc)
   Return KernelTime + UserTime
}

GetSystemTimes() {
   DllCall("GetSystemTimes", "Int64P", IdleTime, "Int64P", KernelTime, "Int64P", UserTime)
   Return KernelTime + UserTime
}

SortByLoad(Processes) {
   str := ""
   for k, v in Processes {
      if v.PID
         str .= (str ? "`n" : "") . v.Load . "|" . v.ProcessName . "|" . v.PID
   }
   Sort, str, N R
   SortedProcesses := []
   Loop, parse, str, `n
   {
      RegExMatch(A_LoopField, "(.*)\|(.*)\|(.+)", m)
      SortedProcesses.Push({Load: m1, ProcessName: m2, PID: m3})
   }
   Return SortedProcesses
}
Return

App:	; Создать список запущенных.
Txt = 
for Process in ComObjGet("Winmgmts:").ExecQuery("Select * From Win32_Process")
 Txt .= Process.Caption "|"
Return

F9:: 
 	If Not ОкноБезРамокДляИгр       
	{	
		BorderSize:=0
	    WinMove, ahk_exe %G1%,, -BorderSize, -BorderSize, 1920+2*BorderSize, 1080+2*BorderSize
		WinSet, Style, -0xC00000, ahk_exe %G1% ; убрать рамку
		ОкноБезРамокДляИгр := true
	}

;	If Not ОкноБезРамокДляВебки
;	{
;		WinMove Оконный проектор (Источник) - Cam,, 0, 0, 408, 308 ; перемещаем окошко в угол + ресайз
;		WinSet Style, -0x800000, Оконный проектор (Источник) - Cam ; -рамка
;		WinSet Style, -0x40000, Оконный проектор (Источник) - Cam ; -рамка
;		WinSet Style, -0x400000, Оконный проектор (Источник) - Cam ; -рамка
;		ОкноБезРамокДляВебки := true
;	}

	IfWinExist, Оконный проектор (Источник) - Cam
	{
		WinGet ExStyle, ExStyle
		if Not (ExStyle & 0x8)  ; 0x8 is WS_EX_TOPMOST. The window is always-on-top.
		{
			WinSet ExStyle, +0x20 ; чтобы клики проходили сквозь окошко
			WinSet Transparent, 255 ; прозрачность окна: 0 - максимальная, 255 - непрозрачное 
			WinSet AlwaysOnTop, On
		} else 
		 {
			WinSet ExStyle, -0x20
			WinSet Transparent, 255
			WinSet AlwaysOnTop, Off
			; переключаем режим "поверх всех" в окне игры, чтобы окошко ушло на задний план
			WinSet AlwaysOnTop, On, A
			WinSet AlwaysOnTop, Off, A
		 }
	}
Return

F12::
Run, R:\VIDEOS\РОЛИКИ НА ОБРАБОТКУ
Return

17

Re: AHK: Объединить 2 скрипта / Процессы

teadrinker пишет:
myVar := MaxLoad.ProcessName

А у вас что?

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

18

Re: AHK: Объединить 2 скрипта / Процессы

teadrinker
Извиняюсь, что не упомянул об этом, но и это я пробовал:

 myVar := MaxLoad.ProcessName

В тултипе отображает нужный процесс, но при нажатии на кнопку ничего не происходит. Если писать прямой ЕХЕшник - все работает.

19

Re: AHK: Объединить 2 скрипта / Процессы

Проверьте так:

ButtonПодтвердить:
MsgBox % myVar := MaxLoad.ProcessName

Если появляется сообщение с правильным именем процесса, значит всё ок. А почему не активируется — это уж вам видней должно быть. Может, у выбранного процесса нет окна, может, их несколько, может, процесс запущен с повышенными правами.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

20

Re: AHK: Объединить 2 скрипта / Процессы

Michael пишет:
Gui Add, Button, gNewApp hwndhBut x125 y19 w102 h23, 3. Отследить игру

Чувствую, веткой ошиблись. Скрипты для игр должны быть в AutoHotKey — Games. Может, в этом проблема?

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

21 (изменено: Michael, 2021-02-14 16:23:12)

Re: AHK: Объединить 2 скрипта / Процессы

teadrinker пишет:

Если появляется сообщение с правильным именем процесса

Появляется, начал ковыряться в коде, что-то начало получаться, по крайней мере окно активируется нужное - уже хорошо

22

Re: AHK: Объединить 2 скрипта / Процессы

teadrinker
Назрел один очень важный вопрос, вроде по этой же тематике, поэтому задам его тут же.
У меня сейчас с поиском процесса максимально нагружающего ЦП - всё работает, c GUI всё отлично взаимодействует.
Но бывают случаи, что открытый браузер жрет больше чем игровой процесс, это единичные случае, но такое случается.
Так вот, возможно ли к скрипту поиска максимально жрущего ЦП процесса привязать, так сказать "отсев", список процессов, которые рассматриваться не будут? И с помощью каких команд?

23

Re: AHK: Объединить 2 скрипта / Процессы

Что угодно можно сделать, главное логику верно записать.
Просто делать проверку переменных на сходство и пропускать на запрещённые процессы.

Win10x64, AHK v1.1.37.01 (Unicode 64-bit) | AHK-Wiki | Переменные и выражения | RegEx101

24

Re: AHK: Объединить 2 скрипта / Процессы

__Михаил__
Можно небольшой пример реализации подобного? Похожих тем на форуме не нашел

25

Re: AHK: Объединить 2 скрипта / Процессы

А какой смысл тогда искать максимально загружающий процесс, если в любом случае нужен процесс игры? Может, проще сразу его по имени искать?

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

26

Re: AHK: Объединить 2 скрипта / Процессы

teadrinker
Дело в том, что игры постоянно меняются, соотвественно и ЕХЕшники + ко всему, многие игры запускают сращу несколько ЕХЕшников, но это уже другой разговор.
В момент, когда у меня запущенна игра - почти не бывает лишних процессов, жрущих такое же/бОльшее кол-во ЦП. Соотвественно поиск по текущим параметрам нужного ЕХЕшника вполне актуален. Но, как и везде, есть свои подводные камни, и чтобы их устранить, мне надо добавить 1-3 процесса, которые будут пропускаться, при выборе максимально ёмкого.

27

Re: AHK: Объединить 2 скрипта / Процессы

Обновите эту метку:

NewP:	; Отсев новых программ.
ZapList = System|explorer.exe|notepad.exe|chrome.exe

SortedProcesses := GetSortedProcessesByLoad()
MaxLoad := SortedProcesses[1]

If (MaxLoad.ProcessName ~= ZapList)
{
 ToolTip, % MaxLoad.ProcessName " Запрещён!"
 Return
}

GuiControl,, G1, % "|"        ; Очистить перед добавлением процесса.
GuiControl,, G1, % "" . MaxLoad.ProcessName
Return
Win10x64, AHK v1.1.37.01 (Unicode 64-bit) | AHK-Wiki | Переменные и выражения | RegEx101

28

Re: AHK: Объединить 2 скрипта / Процессы

__Михаил__
Огромное спасибо! Всё работает!