Что нового

Как узнать user-a процесса и PID.

serzzz

Новичок
Сообщения
18
Репутация
0
Здраствуйте. Всех с наступившим Новым Годом!!! :smile:

Помогите с решением такой проблемы. Есть сервачек. Подсоединяются пользователи. Как узнать запущенна ли программа под этим пользователем.

В консоле эта команда все показывает.
tasklist /FI "IMAGENAME eq notepad.exe" /FI "USERNAME eq %u
sername%" /FI "Status eq running"

Но не получается в AutoIt-e. Хочется эту информацию в MsgBox вытянуть. Processexist вытягивает все и от всех пользователей. Может кто-нибудь такое делал?
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
serzzz,
Попробуйте так
Код:
#include <Array.au3>

$sProcess = 'notepad.exe'
$sUserSearch = 'Юзер'
$sUser = ''
$j = 0
Dim $aUser[$j + 1][3]

$aList = ProcessList($sProcess)
If $aList[0][0] Then
	For $i = 1 To $aList[0][0]
		$sUser = _ProcessGetOwner($aList[$i][1])
		If $sUser = $sUserSearch Then
			$j += 1
			ReDim $aUser[$j + 1][3]
			$aUser[$j][0] = $aList[$i][0]
			$aUser[$j][1] = $aList[$i][1]
			$aUser[$j][2] = $sUser
			$aUser[0][0] = $j
		EndIf
	Next
	If $j Then
		_ArrayDisplay($aUser)
	Else
		MsgBox(16, $sProcess, 'No User ' & $sUserSearch)
	EndIf
Else
	MsgBox(16, $sUserSearch, 'No Process ' & $sProcess)
EndIf

Func _ProcessGetOwner($PID, $sComputer = ".")
	Local $objWMI, $colProcs, $sUserName, $sUserDomain
	$objWMI = ObjGet("winmgmts:\\" & $sComputer & "\root\cimv2")
	If IsObj($objWMI) Then
		$colProcs = $objWMI.ExecQuery("Select ProcessId From Win32_Process Where ProcessId=" & $PID)
		If IsObj($colProcs) Then
			For $Proc In $colProcs
				If $Proc.GetOwner($sUserName, $sUserDomain) = 0 Then Return $sUserName
			Next
		EndIf
	EndIf
EndFunc   ;==>_ProcessGetOwner

Узнать имя пользователя, от которого запущен процесс
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Можно и на чистом API.

Код:
#RequireAdmin

#Include <Array.au3>
#Include <WinAPIEx.au3>

Opt('MustDeclareVars', 1)

Global $hToken, $Data, $aList = 0

; Enable SeDebugPrivilege privilege for obtain full access rights to another processes
$hToken = _WinAPI_OpenProcessToken(BitOR($TOKEN_ADJUST_PRIVILEGES, $TOKEN_QUERY))
_WinAPI_AdjustTokenPrivileges($hToken, $SE_DEBUG_NAME, 1)

; Retrieve user names for all processes the system
If Not (@error Or @extended) Then
	$aList = ProcessList()
	For $i = 1 To $aList[0][0]
		$Data = _WinAPI_GetProcessUser($aList[$i][1])
		If IsArray($Data) Then
			$aList[$i][1] = $Data[0]
		Else
			$aList[$i][1] = ''
		EndIf
	Next
EndIf

; Enable SeDebugPrivilege privilege by default
_WinAPI_AdjustTokenPrivileges($hToken, $SE_DEBUG_NAME, 2)
_WinAPI_CloseHandle($hToken)

If IsArray($aList) Then
	_ArrayDisplay($aList, '_WinAPI_GetProcessUser')
EndIf

; #FUNCTION# ====================================================================================================================
; Name...........: _WinAPI_GetProcessUser
; Description....: Retrieves the user and domain name for the specified process.
; Syntax.........: _WinAPI_GetProcessUser ( [$PID] )
; Parameters.....: $PID    - The PID of the process. Default (0) is the current process.
; Return values..: Success - The array that contains the following information.
;
;                            [0] - The user (account) name.
;                            [1] - The domain name.
;
;                  Failure - 0 and sets the @error flag to non-zero.
; Author.........: Yashied
; Modified.......:
; Remarks........: Using this function for some processes may require full access rights. Use _WinAPI_AdjustTokenPrivileges()
;                  function to enable SeDebugPrivilege privilege before calling _WinAPI_GetProcessUser().
; Related........:
; Link...........: None
; Example........: Yes
; ===============================================================================================================================

Func _WinAPI_GetProcessUser($PID = 0)

	If Not $PID Then
		$PID = _WinAPI_GetCurrentProcessID()
		If Not $PID Then
			Return SetError(1, 0, 0)
		EndIf
	EndIf

	Local $tSID, $tData, $hProcess, $hToken, $Access, $Ret
	Local $Error = 1

	If _WinAPI_GetVersion() < '6.0' Then
		$Access = 0x00000400
	Else
		$Access = 0x00001000
	EndIf

	$hProcess = DllCall('kernel32.dll', 'ptr', 'OpenProcess', 'dword', $Access, 'int', 0, 'dword', $PID)
	If (@error) Or (Not $hProcess[0]) Then
		Return SetError(1, 0, 0)
	EndIf

	Do
		$hToken = _WinAPI_OpenProcessToken(0x00000008, $hProcess[0])
		If Not $hToken Then
			ExitLoop
		EndIf
		$tSID = DllStructCreate('ptr;byte[1024]')
		$Ret = DllCall('advapi32.dll', 'int', 'GetTokenInformation', 'ptr', $hToken, 'uint', 1, 'ptr', DllStructGetPtr($tSID), 'dword', DllStructGetSize($tSID), 'dword*', 0)
		If (@error) Or (Not $Ret[0]) Then
			ExitLoop
		EndIf
		$tData = DllStructCreate('wchar[1024];wchar[1024]')
		$Ret = DllCall('advapi32.dll', 'int', 'LookupAccountSidW', 'ptr', 0, 'ptr', DllStructGetData($tSID, 1), 'ptr', DllStructGetPtr($tData, 1), 'dword*', 1024, 'ptr', DllStructGetPtr($tData, 2), 'dword*', 1024, 'uint*', 0)
		If (@error) Or (Not $Ret[0]) Then
			ExitLoop
		EndIf
		$Error = 0
	Until 1
	If $hToken Then
		_WinAPI_CloseHandle($hToken)
	EndIf
	_WinAPI_CloseHandle($hProcess[0])
	If $Error Then
		Return SetError(1, 0, 0)
	EndIf

	Local $Result[2]

	For $i = 0 To 1
		$Result[$i] = DllStructGetData($tData, $i + 1)
	Next
	Return $Result
EndFunc   ;==>_WinAPI_GetProcessUser
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
Yashied,
У меня на Windows XP Ваш вариант работает значительно быстрее, чем через WMI. Правда у меня он не определяет LOCAL SERVICE и NETWORK SERVICE, но они, в принципе, и не нужны.

serzzz,
Если решите воспользоваться вариантом на API, то Вам надо скачать WinAPIEx.au3.
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
madmasles сказал(а):
Правда у меня он не определяет LOCAL SERVICE и NETWORK SERVICE, но они, в принципе, и не нужны.

Да, я попробывал. Видимо очередной баг XP. Процесс открывается, но Token не отдается!? В 7 все OK, как всегда. Единственное, если использовать API, нужны права администратора. Но как я понимаю, для поставленной задачи без этого все равно не обойтись.
 
Автор
S

serzzz

Новичок
Сообщения
18
Репутация
0
Мне первый вариант больше нравится, меньше кода и более понятен. Конечно я думал все несколько проще в принципе будет :smile: в сравнении с консольной командой.

Да! Прав админа юзер не имеет. Дело в том что программа запускается при логоне на каждого юзера и висит в трее. она проверяет запущенна ли основная апп и еще коекакие операции делает. Если нет основной апп, то сама себя должна закрыть или сделать лог офф.
 
Автор
S

serzzz

Новичок
Сообщения
18
Репутация
0
В любом случае спасибо за код! Он работает.

Думаю тему можно закрыть.
 
Верх