Что нового

[Процессы] Запуск только четырех копий процесса

Vlad_007

Новичок
Сообщения
7
Репутация
1
Версия AutoIt: v3.3.6.1

Описание: Процессы

Примечания: Автоматизация запуска

Нужно отслеживать количество копий запущенной программы, и не давать запускать 5-ю копию.
Т.е если пользователь запустит 10 раз программу должно запуститься 4.
 

dwerf

Использует ArchLinux
Сообщения
478
Репутация
219
Работает только в откомпилированом виде.
Код:
RunOnly(4)

MsgBox(0, '', 'Ok to exit')

Func RunOnly($iMax = 1)
	Local $aProcessList = ProcessList(@ScriptName)
	If Not @error Then
		If Int($aProcessList[0][0]) > $iMax Then
			Local $hPsAPI = DllOpen('Psapi.dll')
			Local $hKernel = DllOpen('Kernel32.dll')
			Local $Counter = 0
			For $i = 1 To $aProcessList[0][0] Step +1
				If _ProcessGetPath($aProcessList[$i][1], $hKernel, $hPsAPI) = @ScriptFullPath Then $Counter += 1
			Next
			DllClose($hKernel)
			DllClose($hPsAPI)
			If $Counter >= $iMax+1 Then Exit
		EndIf
	EndIf
EndFunc

Func _ProcessGetPath($hPID, $hKernel, $hPsAPI)
    Local $sPath = DllStructCreate('char[1000]')
    Local $hProcess = DllCall($hKernel, 'int', 'OpenProcess', 'dword', 0x0400 + 0x0010, 'int', 0, 'dword', $hPID)
    DllCall($hPsAPI, 'long', 'GetModuleFileNameEx', 'long', $hProcess[0], 'int', 0, 'ptr', DllStructGetPtr($sPath), 'long', DllStructGetSize($sPath))
    DllCall($hKernel, 'int', 'CloseHandle', 'hwnd', $hProcess[0])
    Local $ret = DllStructGetData($sPath, 1)
    Return $ret
EndFunc
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
Vlad_007
А можно так:
Код:
HotKeySet("{ESC}", "_Exit")

While 1
	Local $aProcessList = ProcessList(@ScriptName)
	If $aProcessList[0][0] > 4 Then
		ProcessClose($aProcessList[5][0])
	EndIf
	Sleep(1000)
WEnd

Func _Exit()
	Exit
EndFunc   ;==>_Exit
Работает тоже только в откомпилированом виде.
 

dwerf

Использует ArchLinux
Сообщения
478
Репутация
219
madmasles сказал(а):
А можно так:
Код:
HotKeySet("{ESC}", "_Exit")

While 1
	Local $aProcessList = ProcessList(@ScriptName)
	If $aProcessList[0][0] > 4 Then
		ProcessClose($aProcessList[5][0])
	EndIf
	Sleep(1000)
WEnd

Func _Exit()
	Exit
EndFunc   ;==>_Exit
Работает тоже только в откомпилированом виде.
На компьютере может быть несколько exe-файлов с одинаковыми именами => у разных программ процессы могут называтся одинаково. Тогда возможно, что не запустится ни одна копия скрипта.
 

Garrett

Модератор
Локальный модератор
Сообщения
3,999
Репутация
967
madmasles
Опередили! ;D
Точно такой же вариант написал, правда, поставил $aProcessList[5][1]

dwerf [?]
На компьютере может быть несколько exe-файлов с одинаковыми именами => у разных программ процессы могут называтся одинаково. Тогда возможно, что не запустится ни одна копия скрипта.
Нет проблем:
Код:
ProcessClose($aProcessList[5][1])
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
Можно еще так попробовать:
Код:
#include <WinAPIEx.au3>
HotKeySet("{ESC}", "_Exit")

While 1
	$u = 0
	Local $aProcessList = ProcessList(@ScriptName)
	For $i = 1 To UBound($aProcessList) - 1
		If _WinAPI_GetModuleFileNameEx($aProcessList[$i][1]) = @ScriptFullPath Then
			$u += 1
			If $u > 4 Then
				ProcessClose($aProcessList[$i][0])
			EndIf
		EndIf
	Next
	Sleep(1000)
WEnd

Func _Exit()
	Exit
EndFunc   ;==>_Exit

WinAPIEx
 

dwerf

Использует ArchLinux
Сообщения
478
Репутация
219
Garrett сказал(а):
Нет проблем:
Код:
ProcessClose($aProcessList[5][1])

Я не о том. Если другие программы с таким же именем уже работают,
Код:
Local $aProcessList = ProcessList(@ScriptName)
If $aProcessList[0][0] > 4 Then

будет реагировать и на них.
Возможно запустятся только две копии скрипта или вообще не одной.
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
dwerf [?]
Если другие программы с таким же именем уже работают
Согласен. Проверил. Мой первый скрипт закрывает любые скрипты с одинаковыми именами. Второй вроде закрывает только собственные копии.
 

Garrett

Модератор
Локальный модератор
Сообщения
3,999
Репутация
967
dwerf
Всё! Понял, что вы хотите сказать! Сразу не сориентировался :smile:
 

kzru_hunter

Осваивающий
Сообщения
144
Репутация
49
Можно еще с помощью семафора :smile:
На деле не пробовал
 
Автор
V

Vlad_007

Новичок
Сообщения
7
Репутация
1
Всем Огромное спасибо, посыпаю свою голову пеплом :shok: - не полно поставил задачу. Требуется полезняшка которая не дает запустить 4-ю копию процесса. Для примера обычный калькулятор calc.exe.
Постоянное висение в памяти скрипта и завершение 5-й копии calc.exe не подходит, подходит если скрипт не будет позволять 5-й копии запускаться - не уверен что это вообще возможно :whistle:.
Предполагаю что-то вроде лоудера вида Проверялка-запускалка.
Переименуем calc.exe в calc_.exe, делаем скрипт обзываем его calc.exe - у него следующая логика работы -
1 запускать только одну копию скрипта - (защита от пользователя кто спит на клавиатуре и жмет ENTER на ярлыке или несколько десятков раз запускает иконку)
2 проверять сколько запущено процессов calc_exe
3 если =4 то end скрипт calc.exe
4 если <4 то запустить приложение в виде calc_exe %1 лежит там же где и скрипт и end скрипт
 

dwerf

Использует ArchLinux
Сообщения
478
Репутация
219
Vlad_007 сказал(а):
Предполагаю что-то вроде лоудера вида Проверялка-запускалка.
Как то так:
Код:
$sPath = 'C:\WinXP\system32\notepad.exe'
$iMax = 4

If Not FileExists($sPath) Then
	MsgBox(16, 'Ошибка', 'Файл не найден' & @CRLF & $sPath)
	Exit
EndIf

Local $sProcessName = StringTrimLeft($sPath, StringInStr($sPath, '\', 0, -1))
Local $aProcessList = ProcessList($sProcessName)
If Not @error Then
	If Int($aProcessList[0][0]) >= $iMax Then
		Local $hPsAPI = DllOpen('Psapi.dll')
		Local $hKernel = DllOpen('Kernel32.dll')
		Local $Counter = 0
		For $i = 1 To $aProcessList[0][0] Step +1
			If _ProcessGetPath($aProcessList[$i][1], $hKernel, $hPsAPI) = $sPath Then $Counter += 1
		Next
		DllClose($hKernel)
		DllClose($hPsAPI)
		If $Counter >= $iMax Then Exit
	EndIf
EndIf

Run($sPath & ' ' & $CmdLineRaw)

Func _ProcessGetPath($hPID, $hKernel, $hPsAPI)
    Local $sPath = DllStructCreate('char[1000]')
    Local $hProcess = DllCall($hKernel, 'int', 'OpenProcess', 'dword', 0x0400 + 0x0010, 'int', 0, 'dword', $hPID)
    DllCall($hPsAPI, 'long', 'GetModuleFileNameEx', 'long', $hProcess[0], 'int', 0, 'ptr', DllStructGetPtr($sPath), 'long', DllStructGetSize($sPath))
    DllCall($hKernel, 'int', 'CloseHandle', 'hwnd', $hProcess[0])
    Local $ret = DllStructGetData($sPath, 1)
    Return $ret
EndFunc
 
Автор
V

Vlad_007

Новичок
Сообщения
7
Репутация
1
Спасибо - работает отлично,
поменял путь на $sPath = @ScriptDir&'\target.exe'
:IL_AutoIt_1:
Можно закрывать тему.
 
Верх