PID herausfinden

  • Wie kann ich den PID eines mit ShellExcute gestarteten Programms herausfinden?

    Gibt es auch andere Möglichkeiten an den Pid zu kommen?

    PS: Das Programm hat kein Fenster.

    Einmal editiert, zuletzt von MasterOfTime (12. Februar 2011 um 18:01)

  • Hier ist finde ich ein gutes Beispiel.
    Dort kannst du sogar prüfen welchen State das Fenster hat.
    Die PID wird oben ausgelesen

    Spoiler anzeigen
    [autoit]

    ;~ 1 = Fenster existiert.
    ;~ 2 = Fenster ist sichtbar.
    ;~ 4 = Fenster ist freigegeben.
    ;~ 8 = Fenster ist aktiv.
    ;~ 16 = Fenster ist minimiert.
    ;~ 32 = Fenster ist maximiert.
    #include <array.au3>
    #include <Process.au3>
    Global $list = ProcessList()
    For $i = 1 To $list[0][0]
    $state = WinGetState(_WinGetByPID($list[$i][1]), "")
    $processString = "ProcessName: " & $list[$i][0] & @CRLF
    $processString &= "ProcessID: " & $list[$i][1] & @CRLF
    $processString &= "ProcessPath: " & _GetProcessPath($list[$i][1]) & @CRLF

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

    If BitAND($state, 16) Then ; Fenster Modus siehe oben (minimiert)
    MsgBox(0, $list[$i][0], "Fenster ist minimiert" & @CRLF & @CRLF & $processString)
    EndIf
    If BitAND($state, 8) Then ; Fenster Modus siehe oben (aktiviert)
    MsgBox(0, $list[$i][0], "Fenster ist Aktiviert" & @CRLF & @CRLF & $processString)
    EndIf
    If BitAND($state, 32) Then ; Fenster Modus siehe oben (maximiert)
    MsgBox(0, $list[$i][0], "Fenster ist Maximiert" & @CRLF & @CRLF & $processString)
    EndIf
    Next

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

    Func _GetProcessPath($GPPpid)
    $colItems = ""
    $strComputer = "localhost"

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

    $objWMIService = ObjGet("winmgmts:\\localhost\root\CIMV2")
    $colItems = $objWMIService.ExecQuery('SELECT * FROM Win32_Process WHERE processid = ' & $GPPpid, "WQL", 0x10 + 0x20)

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

    If IsObj($colItems) Then
    For $objItem In $colItems
    Return $objItem.ExecutablePath
    Next
    Else
    Return ""
    EndIf
    EndFunc ;==>_GetProcessPath

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

    Func _WinGetByPID($iPID, $nArray = 1)
    If IsString($iPID) Then $iPID = ProcessExists($iPID)
    Local $aWList = WinList(), $sHold
    For $iCC = 1 To $aWList[0][0]
    If WinGetProcess($aWList[$iCC][1]) = $iPID And _
    BitAND(WinGetState($aWList[$iCC][1]), 2) Then
    If $nArray Then Return $aWList[$iCC][0]
    $sHold &= $aWList[$iCC][0] & Chr(1)
    EndIf
    Next
    If $sHold Then Return StringSplit(StringTrimRight($sHold, 1), Chr(1))
    Return SetError(1, 0, 0)
    EndFunc ;==>_WinGetByPID

    [/autoit]


    http://www.autoit.de/index.php?page=Thread&threadID=25652&highlight=

  • Mein Problem ist nicht das einfache herausfinden eines Pids, sondern den eines startenden Prozesses, weil dieser den selben Namen hat wie ein bereits bestehender Prozess, was aber nicht die selben Programme sind.

    Wenn ihr eine Lösung perat habt, lasst es mich wissen.


    €: AutoBerts Vorschlag geht, wieso bin ich da nicht drauf gekommen :party:

    Einmal editiert, zuletzt von MasterOfTime (12. Februar 2011 um 17:00)

  • @tuttifrutti:

    @MasterOfTime: warum verwendest du nicht einfach

    [autoit]

    run

    [/autoit]

    da bekommst du die PID zurück,

    mfg autoBert

    autoBert: Ein bisschen umändern zeigt auch alle Programme mit PID's an !

    Spoiler anzeigen
    [autoit]

    ;~ 1 = Fenster existiert.
    ;~ 2 = Fenster ist sichtbar.
    ;~ 4 = Fenster ist freigegeben.
    ;~ 8 = Fenster ist aktiv.
    ;~ 16 = Fenster ist minimiert.
    ;~ 32 = Fenster ist maximiert.
    #include <Array.au3>
    #include <Process.au3>
    Global $list = ProcessList()

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

    _ArrayDisplay($list,"test")

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

    For $i = 1 To $list[0][0]
    $state = WinGetState(_WinGetByPID($list[$i][1]), "")
    $processString = "ProcessName: " & $list[$i][0] & @CRLF
    $processString &= "ProcessID: " & $list[$i][1] & @CRLF
    $processString &= "ProcessPath: " & _GetProcessPath($list[$i][1]) & @CRLF

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

    ;~ If BitAND($state, 16) Then ; Fenster Modus siehe oben (minimiert)
    ;~ MsgBox(0, $list[$i][0], "Fenster ist minimiert" & @CRLF & @CRLF & $processString)
    ;~ EndIf
    ;~ If BitAND($state, 8) Then ; Fenster Modus siehe oben (aktiviert)
    ;~ MsgBox(0, $list[$i][0], "Fenster ist Aktiviert" & @CRLF & @CRLF & $processString)
    ;~ EndIf
    ;~ If BitAND($state, 32) Then ; Fenster Modus siehe oben (maximiert)
    ;~ MsgBox(0, $list[$i][0], "Fenster ist Maximiert" & @CRLF & @CRLF & $processString)
    ;~ EndIf
    Next

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

    Func _GetProcessPath($GPPpid)
    $colItems = ""
    $strComputer = "localhost"

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

    $objWMIService = ObjGet("winmgmts:\\localhost\root\CIMV2")
    $colItems = $objWMIService.ExecQuery('SELECT * FROM Win32_Process WHERE processid = ' & $GPPpid, "WQL", 0x10 + 0x20)

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

    If IsObj($colItems) Then
    For $objItem In $colItems
    Return $objItem.ExecutablePath
    Next
    Else
    Return ""
    EndIf
    EndFunc ;==>_GetProcessPath

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

    Func _WinGetByPID($iPID, $nArray = 1)
    If IsString($iPID) Then $iPID = ProcessExists($iPID)
    Local $aWList = WinList(), $sHold
    For $iCC = 1 To $aWList[0][0]
    If WinGetProcess($aWList[$iCC][1]) = $iPID And _
    BitAND(WinGetState($aWList[$iCC][1]), 2) Then
    If $nArray Then Return $aWList[$iCC][0]
    $sHold &= $aWList[$iCC][0] & Chr(1)
    EndIf
    Next
    If $sHold Then Return StringSplit(StringTrimRight($sHold, 1), Chr(1))
    Return SetError(1, 0, 0)
    EndFunc ;==>_WinGetByPID

    [/autoit]
  • €: AutoBerts Vorschlag geht, wieso bin ich da nicht drauf gekommen :party:


    schön, dann ist dein Problem ja gelöst, schön wäre es allerdings auch wenn du den Thread auf gelöst setzt. Einfach 1. Beitrag bearbeiten, Präfix (nähe Überschrift) ändern und speichern (absenden)

    mfg autoBert

  • Ich benutze folgende Funktion:

    _ShellExecuteEx
    [autoit]

    ; =================================================================================================
    ; Func _ShellExecuteEx($sCmd, $sParams = "", $sFolder = "", $sVerb = "", $iState = @SW_SHOWNORMAL,$bCloseProcessHandle=True)
    ;
    ; Parameters are the same as ShellExecute(), except for the addition of:
    ;
    ; $bCloseProcessHandle = If True (recommended unless planning on using Process Handles),
    ; then the Process Handle (if received) is closed
    ; If False, the Process Handle (if received) is returned - this can be used to do additional work with Processes
    ; Usage is mostly recommended for the _ShellExecuteExWait() function and/or getting exit code.
    ;
    ; Return is different from ShellExecute() in the following way:
    ; Success: @error = 0, and either the process ID (if $bCloseProcessHandle is True, and process ID received) is returned,
    ; or a 2-element array (if $bCloseProcessHandle is False):
    ; $array[0]=Process ID if new process started (and process handle+ID received),
    ; $array[1]=Process Handle if new process started (and process handle received)
    ; Failure: @error set and 0 is returned
    ; @error = 1 = parameters error
    ; @error = 2 = call failed (probably due to parameter error. can use _WinAPI_GetLastError())
    ;
    ; NOTE: Recommended to run on Windows 2000 or higher because:
    ; According to Microsoft at http://msdn2.microsoft.com/en-us/library/bb762154.aspx,
    ; Windows 95/98/Me: ShellExecuteEx is supported by the Microsoft Layer for Unicode (MSLU).
    ; To use this, you must add certain files to your application,
    ; as outlined in Microsoft Layer for Unicode on Windows Me/98/95 Systems.
    ; So it appears it will break on those machines without MSLU(?)
    ;
    ; Initial Code from MrCreatoR on AutoIt Forum Topic:: http://www.autoitscript.com/forum/index.php?showtopic=69868
    ; Enhancements/Modifications by: Ascend4nt
    ; (including process handle/ID extract & close-handle code, plus Unicode/path enhancements, & CoInitializeEx call)
    ; =================================================================================================

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

    Func _ShellExecuteEx($sCmd, $sParams = "", $sFolder = "", $sVerb = "", $iState = @SW_SHOWNORMAL,$bCloseProcessHandle=True)
    Local $stINFO,$stVerb,$stPath,$stArgs,$stWDir,$aRet,$hWnd=0,$aProcessArray[2]=[0,0]
    Local $iParamLen,$iCmdLen,$iFolderLen

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

    $iParamLen=StringLen($sParams)
    ; Verify string lengths are less than maximum.
    ; Through testing, 1997 (1996+1 NULL-term) is the maximum parameter length for this call (Unicode)
    If $iParamLen>1996 Then Return SetError(1,0,0)

    $iCmdLen=StringLen($sCmd)
    ; Verify string lengths are less than maximum. [MAX_PATH is 260, but Unicode allows exceptions]
    ; 32767 max length for Unicode strings if prefixed with '\\?\'
    If $iCmdLen>259 Then
    ; 32767-NULL=32766 - 4 (\\?\) = 32762
    If $iCmdLen>(32766-4) Then Return SetError(1,0,0)
    $sCmd='\\?\' & $sCmd
    EndIf

    $iFolderLen=StringLen($sFolder)
    ; Verify string lengths are less than maximum. [MAX_PATH is 260, but Unicode allows exceptions]
    ; 32767 max length for Unicode strings if prefixed with '\\?\'
    If $iFolderLen>259 Then
    ; 32767-NULL=32766 - 4 (\\?\) = 32762
    If $iFolderLen>(32766-4) Then Return SetError(1,0,0)
    $sFolder='\\?\' & $sFolder
    EndIf

    ; Setup string structures
    $stVerb = DllStructCreate("wchar["&(StringLen($sVerb)+1)&"]")
    $stPath = DllStructCreate("wchar[" &($iCmdLen+1)& "];wchar")
    $stArgs = DllStructCreate("wchar[" &($iParamLen+1)& "];wchar")
    $stWDir = DllStructCreate("wchar[" &($iFolderLen+1)& "];wchar")

    ; Initialize string structures (which are then used by pointer in the larger SHELLEXECUTEINFO structure)
    DllStructSetData($stVerb, 1, $sVerb)
    DllStructSetData($stPath, 1, $sCmd)
    DllStructSetData($stWDir, 1, $sFolder)
    DllStructSetData($stArgs, 1, $sParams)

    ; SHELLEXECUTEINFO structure
    $stINFO = DllStructCreate("ulong;ulong;long;ptr;ptr;ptr;ptr;long;long;ptr;ptr;long;ulong;long;long")

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

    ; SHELLEXECUTEINFO structure initialize
    DllStructSetData($stINFO, 1, DllStructGetSize($stINFO)) ; cbSize, size (in bytes) of structure
    ; ------------------------------------------------------------------------------------------------------
    ; fMask Options:
    ; 0x40 = SEE_MASK_NOCLOSEPROCESS. The 15th element in structure (hProcess) will be set with the Process handle
    ; NOTE: per MSDN, this handle *must* be closed by the caller. (similar to how "OpenProcess" must use "CloseProcess")
    ; 0x400 = SEE_MASK_FLAG_NO_UI = Do not display an error message box if an error occurs.
    ; This is not default ShellExecute() behavior, which will display the error message box
    ; ------------------------------------------------------------------------------------------------------
    DllStructSetData($stINFO, 2, BitOR(0x40,0x400)) ; fMask
    ; HWND - MSDN: A window handle to any message boxes that the system might produce while executing this function.
    DllStructSetData($stINFO, 3, $hWnd) ; Is this supposed to *receive* instead of send? I have yet to get clarity on this.
    DllStructSetData($stINFO, 4, DllStructGetPtr($stVerb)) ; lpVerb: pointer to the verb string
    DllStructSetData($stINFO, 5, DllStructGetPtr($stPath)) ; lpFile: pointer to the $cmd string
    DllStructSetData($stINFO, 6, DllStructGetPtr($stArgs)) ; lpParameters: pointer to the parameters/arguments string
    DllStructSetData($stINFO, 7, DllStructGetPtr($stWDir)) ; lpDirectory: pointer to working directory string
    DllStructSetData($stINFO, 8, $iState) ; nShow = state to show window as

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

    #cs
    ; ------------------------------------------------------------------------------------------------------
    ; Per MSDN Documentation, the following call should be done prior to calling ShellExecuteEx:
    ; CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE) ; COINIT_APARTMENTTHREADED = 0x2,COINIT_DISABLE_OLE1DDE = 0x4
    ; Reason:
    ; "Because ShellExecuteEx can delegate execution to Shell extensions (data sources, context menu handlers, verb implementations)
    ; that are activated using Component Object Model (COM), COM should be initialized before ShellExecuteEx is called.
    ; Some Shell extensions require the COM single-threaded apartment (STA) type. In that case, COM should be initialized as shown here.
    ; There are certainly instances where ShellExecuteEx does not use one of these types of Shell extension and those instances would not
    ; require COM to be initialized at all. Nonetheless, it is good practice to always initalize COM before using this function."
    ; ------------------------------------------------------------------------------------------------------
    #ce
    DllCall("ole32.dll", "int", "CoInitializeEx", "ptr", Chr(0), "dword", BitOR(2,4))
    ; I don't care if it succeeds. Doesn't seem to make much difference even to call it.

    $aRet=DllCall("shell32.dll", "int", "ShellExecuteExW", "ptr", DllStructGetPtr($stINFO))

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

    If @error Or Not $aRet[0] Then
    ; DLLStructDelete()'s:
    $stINFO=0
    $stVerb=0
    $stPath=0
    $stArgs=0
    $stWDir=0
    Return SetError(2,@error,0)
    EndIf
    ; Get Process Handle, if one exists (non-NULL if new process started, otherwise
    ; NULL if app that performs 'verb' is already running, or is perhaps a 'properties' dialog etc)
    $aProcessArray[1]=DllStructGetData($stINFO,15)
    ; Get Process ID from Handle
    If ($aProcessArray[1]) Then
    $aRet=DllCall("Kernel32.dll","dword","GetProcessId","long",$aProcessArray[1])
    If IsArray($aRet) Then $aProcessArray[0]=$aRet[0]
    EndIf

    ;ConsoleWrite("Handle passed to function:" & Number($hWnd) & ", Handle AFTER call:" & Number(DllStructGetData($stINFO,3)) & @CRLF)
    ;ConsoleWrite("Process Handle:" & Number($hProcess) & ", Process ID:" & Number($vProcessID) & @CRLF)

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

    ; Close Handle
    If $bCloseProcessHandle And $aProcessArray[1] Then DllCall('kernel32.dll','ptr', 'CloseHandle','ptr', $aProcessArray[1])

    ; DLLStructDelete()'s:
    $stINFO=0
    $stVerb=0
    $stPath=0
    $stArgs=0
    $stWDir=0
    If ($bCloseProcessHandle) Then Return SetError(0,0,$aProcessArray[0])
    SetError(0,0)
    Return $aProcessArray
    EndFunc

    [/autoit]

    Zur Nutzung dieses Forum's, ist ein Übersetzer für folgende Begriffe unerlässlich:

    "On-Bort, weier, verscheiden, schädliges, Butten steyling, näckstet, Parr, Porblem, scripe, Kompletenz, harken, manuel zu extramieren, geckukt, würglich, excell, acces oder Compilevorgeng"