Eine laufende JAVA Anwendung erkennen

  • Hallo,

    ich muss eine JAVA Applikation installieren (FreeMind), dazu darf aber FreeMind nicht gestartet sein. Es muss also vor der Installation geprüft werden, ob die Anwendung noch läuft und dann eine Meldung generiert werden diese durch den Anwender zu schließen.

    Das Problem ist jetzt, dass man im Taskmanager keine FreeMind.exe findet, sondern nur JAVAW.EXE. Diese EXE kann aber auch durch eine weitere JAVA Applikation gestartet worden sein, d. h. es kann mehrere gestartete JAVAW.EXE geben.

    Mit Hilfe des ProcessExplorer von Sysinternals kann man die Parameter sehen. Für FreeMind steht da z. B.:
    "C:\Program Files\Java\jre6\bin\javaw.exe" -jar "C:\Program Files\FreeMind\lib\freemind.jar"

    Mit Hilfe von

    [autoit]

    $pid = WinGetProcess("[CLASS:SunAwtFrame]")

    [/autoit]


    bekomme ich die PID von einem JAVA Prozess, aber nicht von Allen und auch sonst keine Infos.

    Mit Hilfe von

    [autoit]


    $list = ProcessList("javaw.exe")
    for $i = 1 to $list[0][0]
    MsgBox(0,"PIDs", $list[$i][1] & " " & $list[$i][0])
    next

    [/autoit]


    kann ich mir die Prozesse mit ihren PIDs anschauen, erhalte aber auch weiter keine Infos.

    Mit Hilfe von

    [autoit]


    WinGetTitle("[CLASS:SunAwtFrame]")

    [/autoit]


    erhalte ich den kompletten Titeltext einer JAVA Anwendung, jedoch immer nur den Ersten (oder Letzten?) gestarteten... nicht aber Alle.

    Der folgende Code findet Freemind, allerdings so oft, wie die Schleife durchlaufen wird. (Anzahl von gestarteten JAVAW.EXE) und nicht nur so oft, wie Freemind gestartet wurde...

    [autoit]

    $list = ProcessList("javaw.exe") ; Get the number and a list of JAVA processes
    for $i = 1 to $list[0][0]
    $code = StringInStr(WinGetTitle("[CLASS:SunAwtFrame]"), "Freemind")
    if $code <> 0 Then ; check if window title of the process contain the searched JAVA application
    MsgBox(0, "freemind", WinGetTitle("[CLASS:SunAwtFrame]") & " is in use")
    EndIf
    Next

    [/autoit]

    Mit Hilfe von WinList kann ich mir alle geöffneten Fenster mit Freemind-Inhalt anzeigen lassen (also auch eine Textdatei mit dem Titel Freemind...):

    [autoit]

    $hwnd = WinList()
    For $i = 1 to $hwnd[0][0]
    If StringInStr($hwnd[$i][0], "Freemind") > 0 Then
    MsgBox(0, "Titel", $hwnd[$i][0])
    EndIf
    Next

    [/autoit]

    Es gelingt mir jedoch nicht, den Bezug über den Titel zur korrekten PID herzustellen, oder ich finde nur die richtige Funktion nicht...

    Während des Schreibens habe ich einen Workaround geschrieben... :)

    Die folgenden Zeilen scheinen zu funktionieren, doch wäre es mir lieber, ich könnte auf irgendeine Art und Weise die Paramter von JAVAW.EXE ebenso auslesen, wie es der ProcessExplorer macht. Vielleicht habt ihr ja noch eine Idee...:

    [autoit]

    $s_DisplayName = "FreeMind"

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

    ; List just javaw.exe processes
    $list = ProcessList("javaw.exe")
    for $i = 1 to $list[0][0]
    $pid = WinGetProcess("[CLASS:SunAwtFrame]")
    MsgBox(4096, "PIDs", "PID von WinGetProcess ist: " & $pid & @CRLF & "PID von ProcessList ist: " & $list[$i][1])
    if $pid == $list[$i][1] Then
    While 1
    if StringInStr(WinGetTitle("[CLASS:SunAwtFrame]"), "FreeMind") Then
    MsgBox(4096, "freemind", "[CLASS:SunAwtFrame]" & " zugeh. PID: " & $pid)
    $response = MsgBox(32 + 4096, "Accept please...", $s_DisplayName & " is in use." & @CRLF & "Please close " & $s_DisplayName & " and click on OK to continue installation.")
    Select
    Case $response = 1
    MsgBox(0,"msg","User select to check again.")
    Case Else
    MsgBox(0,"msg","Response is not managed.")
    Exit 1000
    EndSelect
    Else
    MsgBox(0,"msg","Application is not longer running.")
    ExitLoop
    EndIf
    WEnd
    EndIf
    Next

    [/autoit]

    (AutoIT 3.3.6.0, Windows Vista 32, Windows XP 32)

    mfg
    Axel

    There exist 10 different kind of people on earth.
    Those who understand binary, and those who don't.

    Einmal editiert, zuletzt von ahe (21. April 2010 um 12:00)

  • Eigentlich suchst du nur eine Funktion welche die Startparameter von einem Prozess ausliest.
    Hier ist ein Beispiel dafür:

    Spoiler anzeigen
    [autoit]

    $aProc = ProcessList("javaw.exe")
    For $i = 1 To $aProc[0][0]
    ConsoleWrite($aProc[$i][0] & ':' & @TAB & _WinAPI_GetCommandLineFromPID($aProc[$i][1]) & @CRLF)
    Next

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

    ; by trancexx (http://www.autoitscript.com/forum/index.ph…ndpost&p=780861)
    Func _WinAPI_GetCommandLineFromPID($iPID)
    Local $aCall = DllCall("kernel32.dll", "handle", "OpenProcess", _
    "dword", 1040, _ ; PROCESS_VM_READ | PROCESS_QUERY_INFORMATION
    "bool", 0, _
    "dword", $iPID)

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

    If @error Or Not $aCall[0] Then
    Return SetError(1, 0, "")
    EndIf
    Local $hProcess = $aCall[0]
    Local $tPROCESS_BASIC_INFORMATION = DllStructCreate("dword_ptr ExitStatus;" & _
    "ptr PebBaseAddress;" & _
    "dword_ptr AffinityMask;" & _
    "dword_ptr BasePriority;" & _
    "dword_ptr UniqueProcessId;" & _
    "dword_ptr InheritedFromUniqueProcessId")
    $aCall = DllCall("ntdll.dll", "int", "NtQueryInformationProcess", _
    "handle", $hProcess, _
    "dword", 0, _ ; ProcessBasicInformation
    "ptr", DllStructGetPtr($tPROCESS_BASIC_INFORMATION), _
    "dword", DllStructGetSize($tPROCESS_BASIC_INFORMATION), _
    "dword*", 0)
    If @error Then
    DllCall("kernel32.dll", "bool", "CloseHandle", "handle", $hProcess)
    Return SetError(2, 0, "")
    EndIf

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

    Local $tPEB = DllStructCreate("byte InheritedAddressSpace;" & _
    "byte ReadImageFileExecOptions;" & _
    "byte BeingDebugged;" & _
    "byte Spare;" & _
    "ptr Mutant;" & _
    "ptr ImageBaseAddress;" & _
    "ptr LoaderData;" & _
    "ptr ProcessParameters;" & _
    "ptr SubSystemData;" & _
    "ptr ProcessHeap;" & _
    "ptr FastPebLock;" & _
    "ptr FastPebLockRoutine;" & _
    "ptr FastPebUnlockRoutine;" & _
    "dword EnvironmentUpdateCount;" & _
    "ptr KernelCallbackTable;" & _
    "ptr EventLogSection;" & _
    "ptr EventLog;" & _
    "ptr FreeList;" & _
    "dword TlsExpansionCounter;" & _
    "ptr TlsBitmap;" & _
    "dword TlsBitmapBits[2];" & _
    "ptr ReadOnlySharedMemoryBase;" & _
    "ptr ReadOnlySharedMemoryHeap;" & _
    "ptr ReadOnlyStaticServerData;" & _
    "ptr AnsiCodePageData;" & _
    "ptr OemCodePageData;" & _
    "ptr UnicodeCaseTableData;" & _
    "dword NumberOfProcessors;" & _
    "dword NtGlobalFlag;" & _
    "ubyte Spare2[4];" & _
    "int64 CriticalSectionTimeout;" & _
    "dword HeapSegmentReserve;" & _
    "dword HeapSegmentCommit;" & _
    "dword HeapDeCommitTotalFreeThreshold;" & _
    "dword HeapDeCommitFreeBlockThreshold;" & _
    "dword NumberOfHeaps;" & _
    "dword MaximumNumberOfHeaps;" & _
    "ptr ProcessHeaps;" & _
    "ptr GdiSharedHandleTable;" & _
    "ptr ProcessStarterHelper;" & _
    "ptr GdiDCAttributeList;" & _
    "ptr LoaderLock;" & _
    "dword OSMajorVersion;" & _
    "dword OSMinorVersion;" & _
    "dword OSBuildNumber;" & _
    "dword OSPlatformId;" & _
    "dword ImageSubSystem;" & _
    "dword ImageSubSystemMajorVersion;" & _
    "dword ImageSubSystemMinorVersion;" & _
    "dword GdiHandleBuffer[34];" & _
    "dword PostProcessInitRoutine;" & _
    "dword TlsExpansionBitmap;" & _
    "byte TlsExpansionBitmapBits[128];" & _
    "dword SessionId")

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

    $aCall = DllCall("kernel32.dll", "bool", "ReadProcessMemory", _
    "ptr", $hProcess, _
    "ptr", DllStructGetData($tPROCESS_BASIC_INFORMATION, "PebBaseAddress"), _
    "ptr", DllStructGetPtr($tPEB), _
    "dword", DllStructGetSize($tPEB), _
    "dword*", 0)

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

    If @error Or Not $aCall[0] Then
    DllCall("kernel32.dll", "bool", "CloseHandle", "handle", $hProcess)
    Return SetError(3, 0, "")
    EndIf

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

    Local $tPROCESS_PARAMETERS = DllStructCreate("dword AllocationSize;" & _
    "dword ActualSize;" & _
    "dword Flags;" & _
    "dword Unknown1;" & _
    "word LengthUnknown2;" & _
    "word MaxLengthUnknown2;" & _
    "ptr Unknown2;" & _
    "handle InputHandle;" & _
    "handle OutputHandle;" & _
    "handle ErrorHandle;" & _
    "word LengthCurrentDirectory;" & _
    "word MaxLengthCurrentDirectory;" & _
    "ptr CurrentDirectory;" & _
    "handle CurrentDirectoryHandle;" & _
    "word LengthSearchPaths;" & _
    "word MaxLengthSearchPaths;" & _
    "ptr SearchPaths;" & _
    "word LengthApplicationName;" & _
    "word MaxLengthApplicationName;" & _
    "ptr ApplicationName;" & _
    "word LengthCommandLine;" & _
    "word MaxLengthCommandLine;" & _
    "ptr CommandLine;" & _
    "ptr EnvironmentBlock;" & _
    "dword Unknown[9];" & _
    "word LengthUnknown3;" & _
    "word MaxLengthUnknown3;" & _
    "ptr Unknown3;" & _
    "word LengthUnknown4;" & _
    "word MaxLengthUnknown4;" & _
    "ptr Unknown4;" & _
    "word LengthUnknown5;" & _
    "word MaxLengthUnknown5;" & _
    "ptr Unknown5;")

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

    $aCall = DllCall("kernel32.dll", "bool", "ReadProcessMemory", _
    "ptr", $hProcess, _
    "ptr", DllStructGetData($tPEB, "ProcessParameters"), _
    "ptr", DllStructGetPtr($tPROCESS_PARAMETERS), _
    "dword", DllStructGetSize($tPROCESS_PARAMETERS), _
    "dword*", 0)

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

    If @error Or Not $aCall[0] Then
    DllCall("kernel32.dll", "bool", "CloseHandle", "handle", $hProcess)
    Return SetError(4, 0, "")
    EndIf

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

    $aCall = DllCall("kernel32.dll", "bool", "ReadProcessMemory", _
    "ptr", $hProcess, _
    "ptr", DllStructGetData($tPROCESS_PARAMETERS, "CommandLine"), _
    "wstr", "", _
    "dword", DllStructGetData($tPROCESS_PARAMETERS, "MaxLengthCommandLine"), _
    "dword*", 0)
    If @error Or Not $aCall[0] Then
    DllCall("kernel32.dll", "bool", "CloseHandle", "handle", $hProcess)
    Return SetError(5, 0, "")
    EndIf
    DllCall("kernel32.dll", "bool", "CloseHandle", "handle", $hProcess)
    Return $aCall[3]
    EndFunc

    [/autoit]
  • Wow..."nur" ist gut... :)

    Ich habe deine Funktion ausprobiert und es funktioniert unter Vista 32, vielen Dank :) aber leider nicht unter XP Pro 32

    Hier mein Aufruf...

    [autoit]


    $s_DisplayName = "FreeMind"

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

    $aProc = ProcessList("javaw.exe")
    For $i = 1 To $aProc[0][0]
    While 1
    If StringInStr(_WinAPI_GetCommandLineFromPID($aProc[$i][1]), $s_DisplayName) Then
    ;MsgBox(4096, "freemind", "[CLASS:SunAwtFrame]" & " zugeh. PID: " & $aProc[$i][1])
    $response = MsgBox(32 + 4096, "Accept please...", $s_DisplayName & " is in use." & @CRLF & "Please close " & $s_DisplayName & " and click on OK to continue installation.")
    Select
    Case $response = 1
    MsgBox(0,"msg","User select to check again.")
    Case Else
    MsgBox(0,"msg","Response is not managed.")
    Exit 1000
    EndSelect
    Else
    ExitLoop
    EndIf
    WEnd
    Next
    MsgBox(0,"msg","Application is not longer running.")

    [/autoit]

    Hast du eine Idee, was falsch sein könnte? Könnte es sein, dass die kernel32.dll unter XP nicht die gleichen Funktionen enthält?

    Unter XP ist der Rückgabewert für $aProc[$i][1] leer, für $aProc[$i][0] kommt javaw.exe heraus...

    [autoit]

    2:
    javaw.exe:
    javaw.exe:

    [/autoit]

    mfg
    Axel

    There exist 10 different kind of people on earth.
    Those who understand binary, and those who don't.

  • Hab grad kein XP zur Hand aber das wär echt merkwürdig wenn der dir kein PID liefert.
    Teste in dem Fall mal was ProcessExists zurück gibt.
    Ansonsten wär eine Möglichkeit folgende Funktion:

    Spoiler anzeigen
    [autoit]

    ;by Manko (http://www.autoitscript.com/forum/index.ph…ndpost&p=633581)
    Func _WinAPI_GetCommandLineFromPID($PID)
    $ret1=DllCall("kernel32.dll", 'int', 'OpenProcess', 'int', $PROCESS_VM_READ+$PROCESS_QUERY_INFORMATION, 'int', False, 'int', $PID)
    $tag_PROCESS_BASIC_INFORMATION = "int ExitStatus;" & _
    "ptr PebBaseAddress;" & _
    "ptr AffinityMask;" & _
    "ptr BasePriority;" & _
    "ulong UniqueProcessId;" & _
    "ulong InheritedFromUniqueProcessId;"
    $PBI=DllStructCreate($tag_PROCESS_BASIC_INFORMATION)
    DllCall("ntdll.dll", "int", "ZwQueryInformationProcess", "hwnd", $ret1[0], "int", 0, "ptr", DllStructGetPtr($PBI), "int", _
    DllStructGetSize($PBI), "int",0)
    $dw=DllStructCreate("ptr")
    DllCall("kernel32.dll", "int", "ReadProcessMemory", "hwnd", $ret1[0], _
    "ptr", DllStructGetData($PBI,2)+0x10, _ ; PebBaseAddress+16 bytes <-- ptr _PROCESS_PARAMETERS
    "ptr", DllStructGetPtr($dw), "int", 4, "ptr", 0)
    $unicode_string = DllStructCreate("ushort Length;ushort MaxLength;ptr String")
    DllCall("kernel32.dll", "int", "ReadProcessMemory", "hwnd", $ret1[0], _
    "ptr", DllStructGetData($dw, 1)+0x40, _ ; _PROCESS_PARAMETERS+64 bytes <-- ptr CommandLine Offset (UNICODE_STRING struct) - Win XP / Vista.
    "ptr", DllStructGetPtr($unicode_string), "int", DllStructGetSize($unicode_string), "ptr", 0)
    $ret=DllCall("kernel32.dll", "int", "ReadProcessMemory", "hwnd", $ret1[0], _
    "ptr", DllStructGetData($unicode_string, "String"), _ ; <-- ptr Commandline Unicode String
    "wstr", 0, "int", DllStructGetData($unicode_string, "Length") + 2, "int*", 0) ; read Length + terminating NULL (2 bytes in unicode)
    DllCall("kernel32.dll", 'int', 'CloseHandle', "hwnd", $ret1[0])
    If $ret[5] Then Return $ret[3] ; If bytes returned, return commandline...
    Return "" ; Getting empty string is correct behaviour when there is no commandline to be had...
    EndFunc

    [/autoit]

    Oder der (langsamere) Weg über WMI:

    Spoiler anzeigen
    [autoit]

    Global $Prozessname = "javaw.exe"

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

    Global $oWMI = ObjGet("winmgmts:\\localhost\root\CIMV2")

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

    For $oProc In $oWMI.ExecQuery('SELECT CommandLine, Name FROM Win32_Process WHERE Name="' & $Prozessname & '"', "WQL", 48)
    MsgBox(0,"", $oProc.Name & ':' & @TAB & $oProc.CommandLine)
    Next
    $oWMI = 0

    [/autoit]
  • Hallo Aspirin,

    habe die WMI Lösung getestet, weil sie genau dem entsprach, was ich mir vorgestellt hatte (kurz und gut). Funktioniert einwandfrei auf Vista, unter XP wird die CommandLine jedoch nicht angezeigt.

    Ich habe daraufhin andere Attribute getestet, wie

    • $oProc.Caption
    • $oProc.Description
    • $oProc.ProcessID

    etc. diese funktionierten, nur CommandLine nicht... (beim SELECT habe ich "CommandLine, Name" durch * ersetzt. um dort evtl. Schreibfehler auszuschließen)

    Jedes Mal wird mir die javaw.exe mit dem gewünschten Attribut angezeigt, nur bei CommandLine nix, s. Beispiel-Ergebnis für $oProc.ProcessID:
    javaw.exe: 5992
    javaw.exe: 5764

    Mit einem Codegenerator für VBS erhielt ich dieses funktionierende Skript:

    [autoit]

    Set objWMI = GetObject("winmgmts:\\.\root\CIMV2")

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

    Set objTest = objWMI.ExecQuery("SELECT CommandLine, Name FROM Win32_Process WHERE Name='javaw.exe'", "WQL", 48 )
    For Each objFish2 In objTest
    WScript.Echo objFish2.CommandLine
    Next

    [/autoit]

    Dort wird als Ergebnis das Gleiche ausgegeben, wie unter Vista mit AutoIT:
    "C:\Program Files\Java\jre6\bin\javaw.exe" -Xms16m -Xmx256m -jar "C:\Program Files\GanttProject\eclipsito.jar" ganttproject-eclipsito-config.xml
    javaw.exe -Xmx256M -jar "lib\freemind.jar"

    Wo liegt jetzt der Fehler? Hast du noch eine Idee?


    mfg
    Axel

    There exist 10 different kind of people on earth.
    Those who understand binary, and those who don't.

  • Hallo Aspirin,

    habe jetzt die andere, nicht WMI-Methode, ausprobiert.

    Diese funktioniert sowohl unter XP, als auch unter Vista.

    Ich danke dir noch einmal für deine Hilfe. Jetzt muss ich mich erst einmal in diese Funktion einlesen, kapiert habe ich sie noch nicht, das war bei WMI einfacher :)

    Allerdings wüßte ich schon gerne, wo das Problem bei der WMI Variante liegt...

    mfg
    Axel

    There exist 10 different kind of people on earth.
    Those who understand binary, and those who don't.

  • Hallo,

    ich bin so ein Depp!

    Die WMI Variante funktioniert doch! Wenn man den Check nicht aus SciTE heraus startet, sondern den Test der Attribute mit einem Kompilat durchführt.

    Danke noch einmal für die Hilfe, das Problem ist gelöst.

    mfg
    Axel

    There exist 10 different kind of people on earth.
    Those who understand binary, and those who don't.