Kernel32.dll - GetProcessId

  • Hi,
    ich möchte die PID eines Prozesses mit der Funktion GetProcessId abfragen. Ich verstehe jedoch überhaupt nicht, wie ich folgenden Teil umsetzen kann (Beispiele sind auch nicht zu finden!):

    Zitat

    Process [in]

    A handle to the process. The handle must have the PROCESS_QUERY_INFORMATION or PROCESS_QUERY_LIMITED_INFORMATION access right. For more information, see Process Security and Access Rights.

    Windows Server 2003 and Windows XP: The handle must have the PROCESS_QUERY_INFORMATION access right.

    Meine UDF sieht bisher folgendermaßen aus:

    [autoit]

    Func _ProcessGetProcessId(Const $S_PROC)
    ;~ DWORD WINAPI GetProcessId(
    ;~ __in HANDLE Process
    ;~ );
    Local Const $AI_RET = DllCall("Kernel32.dll", "dword", "GetProcessId", "ptr", $S_PROC) ;~ ToDo...
    If @error Then Return SetError(1, 0, 0)

    [/autoit][autoit][/autoit][autoit]

    Return $ai_ret[0]
    EndFunc

    [/autoit]


    Kann mir da jemand weiterhelfen? ich benötige dies für eine weiter entwickelte UDF, die ich bald hier posten möchte! (Bei der Gelegenheit fällt mir ein, dass ich meine Dateisuche-UDF auch mal puplik machen wollte...)

  • rofl, ja, warum eigentlich nicht? Hatte nicht mehr in Erinnerung, dass die Funktion die PID zurückgibt. Ich dachte bis eben die würde bei Erfolg 1 zurückgeben.
    Naja, trotzdem würde es mich noch interessieren, wie man die obige Funktion realisieren kann (quasi ein ProcessExist in Autoit...)

  • Moin,

    http://msdn.microsoft.com/en-us/library/ms682629(VS.85).aspx
    http://msdn.microsoft.com/en-us/library/ms684320.aspx

    s. Beispiele !

    EDIT:

    [autoit]


    $aProcesses = EnumProcesses ()

    [/autoit][autoit][/autoit][autoit]

    _ArrayDisplay ($aProcesses)

    [/autoit][autoit][/autoit][autoit]

    Func EnumProcesses ()

    Local $aReturn[512], $aProcessIds, $pProcessIds, $cb, $pBytesReturned, $aRes

    $cbNeeded = DllStructCreate ('dword')
    $aProcessIds = DllStructCreate ('dword[511]')

    $aRes = DllCall ('Psapi.dll', 'int', 'EnumProcesses', _
    'dword', DllStructGetPtr ($aProcessIds), _
    'dword', DllStructGetSize ($aProcessIds), _
    'dword', DllStructGetPtr ($cbNeeded))
    If $aRes[0] <> 0 Then
    $aReturn[0] = DllStructGetData ($cbNeeded, 1) / 4 ; enthält Anzahl der Elemente
    For $i = 0 To $aReturn[0]
    $aReturn[$i + 1] = DllStructGetData ($aProcessIds, 1, $i)
    Next
    ReDim $aReturn[$aReturn[0] + 1]
    EndIf

    Return $aReturn

    EndFunc

    [/autoit][autoit][/autoit][autoit][/autoit]


    Gruß
    Greenhorn


    3 Mal editiert, zuletzt von Greenhorn (31. Juli 2008 um 10:00)

  • Danke für Deine Mühe, aber das ist eigentlich nicht das, nachdem ich gefragt hatte. Mir ging es um die Funktion GetProcessId und ihre Implementierung in AutoIt. Das Auflisten der Prozesse mittels EnumProcesses ähnelt ja eher ProcessList, hier geht es aber um ProcessExists.

    Leider war Deine Funktion nicht ganz korrekt, da DllStructGetData in der Schleife mit Index = 0 gestartet, der erste ist aber 1. Außerdem habe ich error handling hinzugefügt und die Erstellung des Arrays verbessert (kein ReDim mehr notwendig).
    Daher habe ich mal eine saubere UDF draus gemacht...

    ProcessEnum - Retrieves the process identifier for each process object in the system.

    Spoiler anzeigen
    [autoit]

    ;===============================================================================
    ; Function Name.....: _ProcessEnum
    ; Description.......: Retrieves the process identifier for each process object in the system.
    ; Version...........: 1.0.1
    ; Change Date.......: 2008-07-31
    ; AutoIt Version....: 3.2.12.1
    ;
    ; Parameter(s)......: None
    ; Requirements(s)...: "Psapi.dll" (included with Windows up from Windows 2000)
    ; Return Value(s)...: Success: Returns an one-dimensional array containing process identifiers:
    ; $ai_array[0] = Number of processes.
    ; $ai_array[1] = 1st process ID.
    ; $ai_array[n] = nth process ID.
    ; Failure: Returns 0 and sets @error to:
    ; 1 = Unable to use the DLL file "Psapi.dll".
    ; 2 = Unknown "return type" of the function "EnumProcesses".
    ; 3 = Unable to find the function "CloseHandle" in the DLL file "Psapi.dll".
    ; 4 = Unable to build the list.
    ;
    ; Author(s).........: Greenhorn <[email='Kl455e@web.de'][/email]>
    ; Modified by: teh_hahn <[email='sPiTsHiT@gmx.de'][/email]>
    ; Company...........: None
    ; URL...............: None
    ; Note(s)...........: - http://msdn.microsoft.com/en-us/library/ms682629(VS.85).aspx
    ; - ToDo: Find out maximum possible number of processes under Windows.
    ;===============================================================================
    Func _ProcessEnum()
    Local Const $STRUCT_BYTESRETURNED = DllStructCreate("dword")
    Local Const $STRUCT_PROCESSIDS = DllStructCreate("dword[32768]")

    [/autoit] [autoit][/autoit] [autoit]

    ;~ BOOL WINAPI EnumProcesses(
    ;~ __out DWORD *pProcessIds,
    ;~ __in DWORD cb,
    ;~ __out DWORD *pBytesReturned
    ;~ );
    Local Const $AV_RET = DllCall("Psapi.dll", "int", "EnumProcesses", _
    "dword", DllStructGetPtr($STRUCT_PROCESSIDS), _
    "dword", DllStructGetSize($STRUCT_PROCESSIDS), _
    "dword", DllStructGetPtr($STRUCT_BYTESRETURNED))
    If @error Then Return SetError(@error, 0, 0)
    If Not $AV_RET[0] Then Return SetError(4, 0, 0)

    [/autoit] [autoit][/autoit] [autoit]

    Local Const $I_SIZE = DllStructGetData($STRUCT_BYTESRETURNED, 1) / 4
    Local $ai_ret[$I_SIZE + 1] = [$I_SIZE]
    For $i = 1 To $I_SIZE
    $ai_ret[$i] = DllStructGetData($STRUCT_PROCESSIDS, 1, $i)
    Next

    [/autoit] [autoit][/autoit] [autoit]

    Return $ai_ret
    EndFunc ;==>_ProcessEnum

    [/autoit]
  • Naja, die Aussage:

    Zitat

    Retrieves the process identifier of the specified process.


    sollte das bestätigen, was ich möchte. Eben dieser Handle ist es ja auch, der mir Gedanken macht. Wenn ich zunächst einen Prozess öffnen muss, so kann ich dies ja nur anhand der PID, damit wäre diese Funktion sinnlos. Gibt es also eine Möglichkeit einen Prozesshandle mit Hilfe des Prozessnamen (z.B. notepad.exe) zu erstellen?

    Hier der der Test, ohne error handling. Die scheint wirklich ziemlich sinnfrei zu sein:

    Spoiler anzeigen
    [autoit]

    MsgBox(64, "_ProcessGetProcessID", _ProcessGetProcessID(ProcessExists("explorer.exe")))

    [/autoit] [autoit][/autoit] [autoit]

    Func _ProcessGetProcessID(Const $S_PROC)
    Local Const $AV_HWND = DllCall("Kernel32.dll", "ptr", "OpenProcess", _
    "dword", $PROCESS_ALL_ACCESS, _
    "int", False, _
    "dword", $S_PROC)

    [/autoit] [autoit][/autoit] [autoit]

    ;~ DWORD WINAPI GetProcessId(
    ;~ __in HANDLE Process
    ;~ );
    Local Const $AV_RET = DllCall("Kernel32.dll", "dword", "GetProcessId", "ptr", $AV_HWND[0])
    DllCall("Kernel32.dll", "int", "CloseHandle", "int", $AV_HWND[0])

    [/autoit] [autoit][/autoit] [autoit]

    Return $AV_RET[0]
    EndFunc ;==>_ProcessGetProcessID

    [/autoit]


    Muss ich das verstehen?

  • Danke für Deine Mühe, aber das ist eigentlich nicht das, nachdem ich gefragt hatte. Mir ging es um die Funktion GetProcessId und ihre Implementierung in AutoIt.


    Ich habe dir doch die Hinweise gegeben ...
    Hast Du dir die Beispiele nicht angesehen ?
    http://msdn.microsoft.com/en-us/library/ms682623(VS.85).aspx

    Dieses Bsp. listet alle laufenden Prozesse auf und ermittelt den Namen der Prozesse.
    Danach musst Du dann deinen Suchstring mit der Liste abgleichen, das war's ... ;)

    Genauso macht es AutoIt auch !
    Ich habe im Quelltext der Version 3.1.x nachgesehen ;)

    Also erst EnumProcesses, dann die Liste abklappern mit OpenProcess() und GetModuleBaseName() um den Namen des Prozesses zu bekommen, und dann nochmal oder zeitgleich mit deinem Suchstring vergleichen.
    Die Funktion, die ich geposted habe ist nur der erste Schritt, den Rest musst Du schon selbst machen.


    Gruß
    Greenhorn


    Einmal editiert, zuletzt von Greenhorn (31. Juli 2008 um 23:54)

  • Hallo

    Greenhorn: Er will nur die PID eines Prozesses herrausfinden, nicht sowas wie ProcessList()^^

    Mfg Spider

    Genau so ist es ! ;)

    Also, noch mal von vorn ...

    GetProcessID() verlangt einen HANDLE zu einem Prozess.
    Einen HANDLE zu einem Prozess erhält man mit OpenProcess().
    OpenProcess() verlangt wiederum eine ID zu einem Prozess.

    Zitat von teh_hahn

    Gibt es also eine Möglichkeit einen Prozesshandle mit Hilfe des Prozessnamen (z.B. notepad.exe) zu erstellen?


    Mit einer einzigen Win32API Funktion nicht !

    Zitat von teh_hahn

    Naja, trotzdem würde es mich noch interessieren, wie man die obige Funktion realisieren kann (quasi ein ProcessExist in Autoit...)


    ProcessExist ist Autoit ;)
    Aber wir können im Quellcode von AutoIt nachschauen, wie Jon es gemacht hat ... :)

    Zitat von Greenhorn

    Hast Du dir die Beispiele nicht angesehen ?
    http://msdn.microsoft.com/en-us/library/ms682623(VS.85).aspx


    Dieses Beispiel ist einfacher zu verstehen als die Funktion im AutoIt Quellcode, macht aber letzten Endes schon fast das Gleiche.
    Das einzige was fehlt ist der Stringvergleich auf z.B. "notepad.exe" !


    Gruß
    Greenhorn


  • So, nun habt ihr mit doch weichgekaut ... :rolleyes::D

    Listet alle PIDs eines Prozessnamens auf. ;)
    (Sofern die Bedingung erfüllt ist, dass der Prozess
    PROCESS_QUERY_INFORMATION (0x0400) und
    PROCESS_VM_READ (0x0010)
    unterstützt, und das tun nicht alle oder nur teilweise. S. z.B. svchost.exe, oder Bug in meinem Code)

    Eigentlich das gleiche wie ProcessList (), also eher Spielerei ... :rolleyes:
    Hm, irgendwo ist da noch der Wurm drin ... :whistling:

    Aber vllt hilft dir das trotzdem weiter bei deinen Forschungen ... ;)

    GetProcessIdByName ($szFileName)

    Spoiler anzeigen
    [autoit]

    ; GetProcessIdByName Demo.
    $aPID = GetProcessIdByName ('svchost.exe')

    [/autoit] [autoit][/autoit] [autoit]

    _ArrayDisplay ($aPID)
    $aPID = ProcessList ('svchost.exe')

    [/autoit] [autoit][/autoit] [autoit]

    _ArrayDisplay ($aPID)
    $aListPID = EnumProcesses ()
    _ArrayDisplay ($aListPID)

    [/autoit] [autoit][/autoit] [autoit]

    Func GetProcessIdByName ($szFileName)

    Local $hProcess, $ahModules, $szModuleName, $aReturnPID[512], $c = 1, $NULL = Ptr (0)

    $aListPID = EnumProcesses ()

    For $i = 1 To $aListPID[0]

    $hProcess = OpenProcess (BitOR (0x0400, 0x0010), False, $aListPID[$i])

    If $hProcess <> $NULL Then
    $ahModules = EnumProcessModules ($hProcess)
    If $ahModules[0] <> 0 Then
    $szModuleName = GetModuleBaseName ($hProcess, $ahModules[1])
    If $szFileName == $szModuleName Then
    $aReturnPID[0] += 1
    $aReturnPID[$aReturnPID[0]] = $aListPID[$i]
    EndIf
    EndIf
    EndIf
    CloseHandle ($hProcess)
    Next

    ReDim $aReturnPID[$aReturnPID[0] + 1]

    Return $aReturnPID

    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func GetModuleBaseName ($hProcess, $hModule = 0)

    Local $szReturn
    $szBasename = DllStructCreate ('char[260]')

    $aRes = DllCall ('Psapi.dll', 'int', 'GetModuleBaseName', _
    'ptr', $hProcess, _
    'ptr', $hModule, _
    'ptr', DllStructGetPtr ($szBasename), _
    'int', DllStructGetSize ($szBasename))
    If $aRes[0] <> 0 Then
    $szReturn = DllStructGetData ($szBasename, 1)
    EndIf

    Return $szReturn

    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func OpenProcess ($dwDesiredAccess, $bInheritHandle, $dwProcessId)

    $aRes = DllCall ('Kernel32.dll', 'ptr', 'OpenProcess', _
    'dword', $dwDesiredAccess, _
    'int' , $bInheritHandle, _
    'dword', $dwProcessId)
    Return $aRes[0]

    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func CloseHandle ($handle)

    $aRes = DllCall ('Kernel32.dll', 'int', 'CloseHandle', 'ptr', $handle)

    Return $aRes[0]

    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func EnumProcessModules ($hProcess)

    Local $aReturn[512], $ahProcessModules, $cbNeeded, $aRes

    $cbNeeded = DllStructCreate ('dword')
    $ahProcessModules = DllStructCreate ('ptr[511]')

    $aRes = DllCall ('Psapi.dll', 'int', 'EnumProcessModules', _
    'ptr' , $hProcess, _
    'ptr' , DllStructGetPtr ($ahProcessModules), _
    'dword', DllStructGetSize ($ahProcessModules), _
    'ptr' , DllStructGetPtr ($cbNeeded))
    If $aRes[0] <> 0 Then
    $aReturn[0] = DllStructGetData ($cbNeeded, 1) / 4 ; enthält Anzahl der Elemente
    For $i = 1 To $aReturn[0]
    $aReturn[$i] = DllStructGetData ($ahProcessModules, 1, $i)
    Next
    ReDim $aReturn[$aReturn[0] + 1]
    EndIf

    Return $aReturn

    [/autoit] [autoit][/autoit] [autoit]

    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func EnumProcesses ()

    Local $aReturn[512], $aProcessIds, $cbNeeded, $aRes

    $cbNeeded = DllStructCreate ('dword')
    $aProcessIds = DllStructCreate ('dword[511]')

    $aRes = DllCall ('Psapi.dll', 'int', 'EnumProcesses', _
    'dword', DllStructGetPtr ($aProcessIds), _
    'dword', DllStructGetSize ($aProcessIds), _
    'dword', DllStructGetPtr ($cbNeeded))
    If $aRes[0] <> 0 Then
    $aReturn[0] = DllStructGetData ($cbNeeded, 1) / 4 ; enthält Anzahl der Elemente
    For $i = 1 To $aReturn[0]
    $aReturn[$i] = DllStructGetData ($aProcessIds, 1, $i)
    Next
    ReDim $aReturn[$aReturn[0] + 1]
    EndIf

    Return $aReturn

    EndFunc

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit]


    Gruß
    Greenhorn


    2 Mal editiert, zuletzt von Greenhorn (1. August 2008 um 05:29)