Что нового

[Процессы] Нужен скрипт *убивающий мутекс* когда процесс открыт!!!

777lamer777

Новичок
Сообщения
2
Репутация
0
Версия AutoIt: 3.3.15.0

Описание: То есть (у меня есть процесс который хочу запустить дважды), вычислил *что* этот процесс создает мутекс с постоянным именем(который не дает второму окну процесса открываться. *ИМЯ ПРОЦЕССА и ИМЯ МУТЕКСА мне известно).
Отзавитесь кто сможет))(Сам я осилю только путь к процессу и имя мутекса указать).

Примечания: желательно полностью готовый скрипт!!!
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Откройте в 16-ричном редакторе ваш исполняемый файл, найдите строку с именем mutex'а и замените первые два символа на "\" и символ с кодом 0 (конец строки). После этого mutex создаваться не будет.
 
Автор
7

777lamer777

Новичок
Сообщения
2
Репутация
0
Вот именно пробовал сей метод, не работает он... есть строка CreateMutexW, проблема в том что ИМЕНИ НЕТУ, в памяти процесса тоже искал нету, это очень странно( имя мутекса примерно так выглядит*//E49C5EC071B44f14B2*), при всем при этом имя статичное(не меняется).
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Код:
#Include <APIConstants.au3>
#Include <Array.au3>
#Include <WinAPIEx.au3>

Opt('MustDeclareVars', 1)

Global $hToken, $aAdjust, $aObject, $PID = ProcessExists('Test.exe')

$hToken = _WinAPI_OpenProcessToken(BitOR($TOKEN_ADJUST_PRIVILEGES, $TOKEN_QUERY))
If (@Error) Or (Not _WinAPI_AdjustTokenPrivileges($hToken, $SE_DEBUG_NAME, $SE_PRIVILEGE_ENABLED, $aAdjust)) Then
	MsgBox(16, '', 'You do not have administrator rights.')
	Exit
EndIf

$aObject = _ProcessEnumHandles($PID, 14)
_ArrayDisplay($aObject)
If UBound($aObject) > 1 Then
	_ProcessCloseHandle($PID, $aObject[1])
EndIf
$aObject = _ProcessEnumHandles($PID, 14)
_ArrayDisplay($aObject)

_WinAPI_AdjustTokenPrivileges($hToken, $aAdjust, 0, $aAdjust)
_WinAPI_CloseHandle($hToken)

Func _ProcessCloseHandle($PID, $hObject)

	Local $hModule, $hProcess, $hProc, $List, $Ret, $Index = 0

	$List = _WinAPI_EnumProcessModules($PID)
	If @Error Then
		Return 0
	EndIf
	For $i = 1 To $List[0][0]
		If Not StringCompare(_WinAPI_PathStripPath($List[$i][1]), 'kernel32.dll') Then
			$Index = $i
			ExitLoop
		EndIf
	Next
	If Not $Index Then
		Return 0
	EndIf
	$hModule = _WinAPI_LoadLibrary($List[$Index][1])
	If Not $hModule Then
		Return 0
	EndIf
	$hProc = _WinAPI_GetProcAddress($hModule, 'CloseHandle')
	_WinAPI_FreeLibrary($hModule)
	If Not $hProc Then
		Return 0
	EndIf
	$hProcess = _WinAPI_OpenProcess(BitOR($PROCESS_CREATE_THREAD, $PROCESS_QUERY_INFORMATION, $PROCESS_VM_OPERATION, $PROCESS_VM_READ, $PROCESS_VM_WRITE), 0, $PID)
	If Not $hProcess Then
		Return 0
	EndIf
	$Ret = DllCall('kernel32.dll', 'ptr', 'CreateRemoteThread', 'ptr', $hProcess, 'ptr', 0, 'dword', 0, 'ptr', $List[$Index][0] + $hProc - $hModule, 'ptr', $hObject, 'dword', 0, 'ptr', 0)
	If (Not @Error) And ($Ret[0]) Then
		_WinAPI_WaitForSingleObject($Ret[0])
		_WinAPI_CloseHandle($Ret[0])
	Else
		$Ret = 0
	EndIf
	_WinAPI_CloseHandle($hProcess)
	If Not IsArray($Ret) Then
		Return 0
	Else
		Return 1
	EndIf
EndFunc   ;==>_ProcessCloseHandle

Func _ProcessEnumHandles($PID, $iObjectType)

	Local Const $tagSYSTEM_HANDLE_TABLE_ENTRY_INFO = 'ushort ProcessId;ushort Reserved;ubyte ObjectType;ubyte Flags;ushort Value;ptr Address;ulong GrantedAccess'

	Local $tSHI = DllStructCreate('ulong;ptr[1048576]')
	Local $pSHI = DllStructGetPtr($tSHI, 2)
	Local $Size = DllStructGetSize(DllStructCreate($tagSYSTEM_HANDLE_TABLE_ENTRY_INFO))
	Local $aResult[101] = [0]
	Local $tSHTEI, $Ret

	$Ret = DllCall('ntdll.dll', 'uint', 'ZwQuerySystemInformation', 'uint', 16, 'ptr', DllStructGetPtr($tSHI), 'ulong', DllStructGetSize($tSHI), 'ulong*', 0)
	If (@Error) Or ($Ret[0]) Then
		Return SetError(1, 0, 0)
	EndIf
	For $i = DllStructGetData($tSHI, 1) To 1 Step -1
		$tSHTEI = DllStructCreate($tagSYSTEM_HANDLE_TABLE_ENTRY_INFO, $pSHI + ($i - 1) * $Size)
		Switch $tSHTEI.ObjectType
			Case $iObjectType
				If $tSHTEI.ProcessId = $PID Then
					__Inc($aResult)
					$aResult[$aResult[0]] = Ptr($tSHTEI.Value)
				EndIf
			Case Else

		EndSwitch
	Next
	__Inc($aResult, -1)
	Return $aResult
EndFunc   ;==>_ProcessEnumHandles


Смысл в следующем. Есть две функции - _ProcessEnumHandles() и _ProcessCloseHandle(). Первая выдает список всех хэндлов указанного типа (в данном случае mutex - 14), принадлежащих заданному процессу. Вторая просто закрывает указанный хэндл для этого процесса. Как определить имя mutex'а по хэндлу или хэндл по имени я на скорую руку так и не нашел. Поэтому проще будет убить mutex по номеру в списке. Как правило, это будет последний (первый в массиве) созданный процессом mutex. Если не сработает, то можете узнайть номер mutex'а экспериментально, перебирая все хэндлы.

Если скомпилировать следующий скрипт в качестве целевой программы, которую нужно запустить в нескольких экземплярах, то все прекрасно работает. Запускаем Test.exe, затем представленный выше код, и снова Test.exe. В результате получаем 2 копии программы.

Test.exe

Код:
#Include <WinAPIEx.au3>

_WinAPI_CreateMutex('0123456789')
Switch _WinAPI_GetLastError()
	Case 183 ; ERROR_ALREADY_EXISTS
		MsgBox(0, '', 'Already exists!')
		Exit
	Case Else

EndSwitch

While 1
	Sleep(1000)
WEnd


P.S

Судя по этому:

ZwQuerySystemInformation is no longer available for use as of Windows 8. Instead, use the alternate functions listed in this topic.

в Windows 8+ все это работать не будет.
 
Верх