alme123
Goto Top

Speicherort per PID herausfinden

ich habe folgendes Problem:

ich habe mehrere cmd Prozesse, von denen ich die PID weiß.
Kann man per PID (oder anderer Prozess Info aus tasklist oder pslist) den Speicherort mit Batch-Dateinamen herausfinden?
Dies soll möglichst auf Batch oder VbScript beziehen.

Vielen Dank im Vorraus,

Alme123

[Edit 12.05.13: Frage verbessert]
[Edit 2; 15.11.13: Fehler nach Neuinstallation, siehe Theard #comment-839423]

Content-ID: 206325

Url: https://administrator.de/forum/speicherort-per-pid-herausfinden-206325.html

Ausgedruckt am: 25.12.2024 um 01:12 Uhr

rubberman
rubberman 11.05.2013 um 22:14:23 Uhr
Goto Top
Hallo Alme123.

Ich gehe davon aus dass du auf den Pfad des entsprechenden Programms hinaus willst.
Funktioniert mittels WMI. Die Win32_Process Klasse hat eine CommandLine Eigenschaft, aus der du das extrahieren kannst. Sowohl per VBScript als auch per Batch. Wenn du dich für eines von beiden entschieden hast, bin ich auch gerne weiter behilflich.

Grüße
rubberman
Alme123
Alme123 12.05.2013 um 07:14:42 Uhr
Goto Top
Hallo rubberman,

vielen Dank für deine Rückmeldung.

Dieser Prozess soll(te) mit Batch programmiert werden.
Wie WMI funktioniert, weiß ich leider nicht.

Grüße,

Alme123
bastla
bastla 12.05.2013 um 09:23:20 Uhr
Goto Top
Hallo Alme123!

Dann etwa so:
for /f "delims=" %%i in ('"wmic process where ProcessId='%PID%' get ExecutablePath"') do set "ExePath=%%i"
Grüße
bastla
Alme123
Alme123 12.05.2013 aktualisiert um 09:55:49 Uhr
Goto Top
@bastla und @rubberman

Entschuldigung, das ich mich falsch ausgedrückt habe:

Es sind cmd Prozesse, von denen der BatchPfad ausgelesen werden soll.

@bastla, dein Script funktioniert; jedoch nicht für das obenstehende.

Alme123
76109
76109 12.05.2013 um 10:59:23 Uhr
Goto Top
Hallo Alme123!

@bastla, dein Script funktioniert; jedoch nicht für das obenstehende
Dann verwende 'CommandLine' anstatt 'ExecutablePath'

Gruß Dieter
bastla
bastla 12.05.2013 um 11:04:24 Uhr
Goto Top
Hallo Alme123!

Versuch es damit:
for /f "tokens=2*" %%i in ('"wmic process where ProcessId='%PID%' get CommandLine"') do set "ExePath=%%~j"
Grüße
bastla
Alme123
Alme123 12.05.2013 um 12:04:33 Uhr
Goto Top
@bastla

Dein Script funktioniert, aber es zeigt noch die Anführungszeichen und ein Leerzeichen an.
Ausgabe: "C:/batch.bat" "

Mit
set "ExePath=%ExePath:~1%"  
set "ExePath=%ExePath:~0,-5%"  

könnte man es beheben.

Kann man es schon mit deinem Befehl ändern?

Alme123
Alme123
Alme123 12.05.2013 um 12:05:19 Uhr
Goto Top
@76109

nein, dies funktioniert nicht, siehe @bastla

Alme123
rubberman
rubberman 12.05.2013 um 12:53:40 Uhr
Goto Top
Hallo Alme123,

wenn die Batchdatei per Doppelklick ausgeführt wurden, dann vermutlich so:
@echo off &setlocal

set /a PID=2260

call :getBatPath %PID% strBatPath
echo(%strBatPath%
pause
goto :eof

:getBatPath iPID RefVar
  setlocal
  set /a iPID=%~1
  set "RefVar="  
  set "CmdLn="  
  for /f "tokens=1* delims==" %%i in (  
    'WMIC Process WHERE "ProcessId=%iPID%" GET CommandLine /value 2^>nul'  
  ) do for /f "delims=" %%k in ("%%j") do (  
    set "CmdLn=%%k"  
    setlocal EnableDelayedExpansion
      set "CmdLn=!CmdLn:cmd /c "=!"  
      for %%l in (!CmdLn!) do (
        if "!!"=="" endlocal  
        if not defined RefVar if /i "%%~xl"==".bat" set "RefVar=%%~l"  
      )
  )
  endlocal &set "%~2=%RefVar%"  
goto :eof

Grüße
rubberman
bastla
bastla 12.05.2013 um 14:38:16 Uhr
Goto Top
... obwohl auch
for /f "tokens=2*" %%i in ('"wmic process where ProcessId='%PID%' get CommandLine"') do set "ExePath=%%~j"  
for %%i in (%ExePath:"=%) do set "ExePath=%%i"  
schon genügen sollte ...

Grüße
bastla
rubberman
rubberman 12.05.2013 aktualisiert um 15:44:33 Uhr
Goto Top
Hallo bastla,

nur dann, wenn keine Leerzeichen im Pfad sind, oder habe ich einen Denkfehler?

Grüße
rubberman

PS: Ich glaube dort sind wir schon einen Meter weiter gekommen face-smile
bastla
bastla 12.05.2013 um 18:23:28 Uhr
Goto Top
Hallo rubberman!

Hast recht - die Zeile 2 wäre so besser:
for /f "delims=" %%i in ("%ExePath:"=%") do set "ExePath=%%i"
Grüße
bastla
Alme123
Alme123 12.05.2013 um 18:39:13 Uhr
Goto Top
Hallo,

Danke an @rubberman und @bastla .

Diese Frage ist gelöst.

Wen es interessiert: Hier ging es weiter mit der gleichen Frage (etwas anders, aber vollständig)

Alme123

[Theard closed]
rubberman
rubberman 12.05.2013 um 18:44:20 Uhr
Goto Top
Hallo bastla,

nee, das sieht nur gut aus, wenn man sich die Leerzeichen am Ende auch noch wegzaubert face-wink FOR /F ist dafür nicht so toll geeignet.

Grüße
rubberman
bastla
bastla 12.05.2013 aktualisiert um 18:58:34 Uhr
Goto Top
Hallo rubberman!

Yep, ist richtig (das kommt vom Posten zwischen Tür und Angel) face-sad

Ich hätte gleich VBS nehmen sollen ...

Grüße
bastla
rubberman
rubberman 12.05.2013 um 20:56:25 Uhr
Goto Top
Hallo bastla,

ist doch kein Beinbruch face-wink
Ich bin aber davon überzeugt, dass es mit VBS auch nicht einfacher würde. Die Anforderungen aus dem oben verlinkten Beitrag mal mit einbezogen ergibt das:
Das VBScript würde aus einem Batch aufgerufen werden. Dabei soll für alle cmd.exe Prozesse die PID und der Pfad der dazugehörigen Batchdatei ermittelt werden. Der aufrufende Batchprozess soll dabei ausgeschlossen werden.
Bedeutet:
  1. Parent PID des VBScripts ermitteln.
  2. PID und Kommandozeile für jeden cmd.exe Prozess (außer dem mit der Parent PID) ermitteln.
  3. Pfade der Batchdateien aus den Kommandozeilen extrahieren.

Punkt 1 ist schon eine kleine Herausforderung, aber machbar.
Bei Punkt 3 fällt mir Split() mit " als Trenner ein. Das wäre aber auch eine Alternative für FOR /F in Batch (auch wenn die Syntax dafür etwas gewohnheitsbedürftig ist). Hättest du es anders gelöst?

Grüße
rubberman
bastla
bastla 12.05.2013 um 21:13:40 Uhr
Goto Top
Hallo rubberman!
Hättest du es anders gelöst?
Ich hätte vermutlich, spät, aber doch, eher mal die Frage nach dem Sinn der ganzen Aktion gestellt ...

Grüße
bastla
76109
76109 13.05.2013 aktualisiert um 22:00:42 Uhr
Goto Top
Hallo bastla, rubberman!

Per VBS könnte man es doch vom Prinzip her, in etwa so machen:
Const sSqlExec = "Select * from Win32_Process Where Name='cmd.exe'"  

Dim oWMIService, oProcess, sCaller, sPath, sResult

With WScript.Arguments
    If .Count <> 1 Then
        WScript.Echo "Aufruf ohne Argument!":  WScript.Quit 1  
    Else
        sCaller = .Item(0)
    End If
End With

Set oWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")  
    
For Each oProcess In oWMIService.ExecQuery(sSqlExec)
    If LCase(Left(oProcess.CommandLine, 3)) = "cmd" Then  
        sPath = Split(oProcess.CommandLine, Chr(34))(2)
        If sPath <> sCaller Then sResult = sResult & sPath & vbCrLf
    End If
Next
WScript.Echo sResult
Wobei ich die PID jetzt mal außer acht gelassen habe...

Es sollen ja, wenn ich das richtig verstanden habe nur die CMD-Scripte ermittelt werden, also ist das VB-Script ja eigentlich uninteressant.
Wenn das VB-Script über Batch aufgerufen werden soll, dann wird die Variable %0 als Argument an das VB-Script übergeben, um die aufrufende Batch ausschließen zu können.
cscript //nologo xy.vbs "%~f0"  
Pause

In der CmdLine beginnen alle Scriptaufrufe mit "cmd" Left(3). Somit befindet sich der Pfad im Split-Token (2) und mit Right(3) kann man bei Bedarf auch noch auf die Extension "bat" testen ...

Gruß Dieter

[edit] Script-Aufruf auf Anraten von rubberman entsprechend geändert [/edit]
rubberman
rubberman 13.05.2013 um 19:37:20 Uhr
Goto Top
Hallo Dieter,

gute Idee. Nur aus Sicherheitsgründen (je nach dem, wie die Batchdatei selbst aufgerufen wurde), würde ich das %0 zu "%~f0" machen. Ansonsten ist das ziemlich clever gelöst, ich habe da wieder mal viel zu kompliziert gedacht.
Die PID noch mit zu verwursten ist dann Makulatur face-wink

Grüße
rubberman
76109
76109 13.05.2013 um 20:34:04 Uhr
Goto Top
Hallo rubberman!

Danke für den Tipp mit "%~f0". Hab's oben geändert.

... ich habe da wieder mal viel zu kompliziert gedacht.
Das dachte ich auchface-wink

Gruß Dieter
Alme123
Alme123 15.11.2013 aktualisiert um 17:30:29 Uhr
Goto Top
An alle,

ich muss den Theard wieder etwas aufreißen, weil bei mir eure Scripte nicht mehr funktionieren.
Ich habe Windows neuinstalliert und danach gab es nur noch Chaos.
Ich habe alle Batchscripte probiert, aber keins bringt das gewünschte Ergebnis.

Ich möchte einfach meine Lösung schreiben, euch fragen ob dieses Script funktioniert, ob bei euch die alten Scripte (Wie bastla's erstes) noch funktionieren und
fragen, ob es auch ggf. eleganter geht:

@echo off
set "ExePath="  
set "PID="  
for /f "tokens=*" %%i in ('%windir%\system32\tasklist.exe ^| %windir%\system32\findstr.exe /I "datei.exe"') do set "PID=%%i"  
echo %PID% | %windir%\system32\findstr.exe /I "Console" >nul  
if errorlevel 1 start /min "" "%ProgramFiles%\VirusDumper\datei.exe" && goto :Eof  
set "PID=%PID:~0,34%"  
set "PID=%PID:~-4%"  
for /f "delims=" %%i in ('"wmic process where ProcessId='%PID%' get ExecutablePath"') do for /f "delims=" %%a in ('"echo %%i | findstr /I "%homedrive%""') do set "ExePath=%%a"  
set "ExePath=%ExePath:~0,-3%"  
echo Speicherort: %ExePath%
Der Code prüft, ob die "datei.exe" geöffnet ist. Wenn nicht, wird sie gestartet und das Script beendet. Wenn doch wird die PID geformt.
Darauf wird der Speicherort gesucht und extrahiert.
Nachteil: Wenn der Speicherort der Datei völlig unklar ist, kann man nur %homedrive% benutzen, was bei anderen Laufwerken zu Fehlern führt.
Das Problem bei euren Scripts (hier bastla's erstes) trat bei der Erhaltung des Speicherorts ein: Es kam statt dem Speicherort folgendes raus:
ExecutablePath
C:\Users\Benutzer\Desktop\datei.exe
Diese Ausgabe bestand aus 3 Zeilen, die letzte war eine Leerzeile oder eine Zeile nur mit Leerstellen.


Alme123
rubberman
Lösung rubberman 15.11.2013, aktualisiert am 14.12.2013 um 21:11:06 Uhr
Goto Top
Hallo Alme123.

Wenn der Speicherort der Datei völlig unklar ist
Warum sollte er das sein? Wenn der Prozess gestartet wurde, ist auch klar wo das Executable liegt.

Ungetestet
for /f "delims=" %%i in ('"wmic process where ProcessId='%PID%' get ExecutablePath /value"') do (  
  for /f "tokens=1* delims==" %%a in ("%%i") do set "ExePath=%%b"  
)

Grüße
rubberman

EDIT Zeile 2 korrigiert
Alme123
Alme123 15.11.2013 um 19:59:26 Uhr
Goto Top
@rubberman

dies funktioniert prächtig! Funktionieren die alten Scripts noch bei dir und weißt du vielleicht, wieso sie bei mir nicht funktionieren?

Alme123
rubberman
rubberman 15.11.2013 um 20:53:57 Uhr
Goto Top
Hallo Alme123,

meine Scripts funktionieren nach wie vor. Habe ich auf der selben Windowsversion geschrieben (Win7 x86).
Ich kann nur mutmaßen: Je nach WMIC Version kommt die Ausgabe in einem verstümmelten Unicode Zeichensatz mit merkwürdigen Zeilenumbrüchen. Diese kann man mit einer verschachtelten FOR /F Schleife "normalisieren".

Grüße
rubberman
Alme123
Alme123 15.11.2013, aktualisiert am 16.11.2013 um 12:10:43 Uhr
Goto Top
@rubberman

Ich nutze die Windows 7 64 Bit Version nicht die 32iger (ich denke doch x86 ist 32 Bit, ggf. aufklären)
Kodierung der Dateien sind bei mir immer ANSI und cmd hat keine speziellen Voreinstellungen.
Was mir aufgefallen ist: Wenn die PID 3 stellig ist, steht am Anfang der PID ein Leerzeichen.
Der Vorgang schlägt dann fehl.

Alme123
rubberman
rubberman 15.11.2013 aktualisiert um 22:39:51 Uhr
Goto Top
Hallo Alme123,

du hast mich missverstanden. Mir ging es um die Dateiversion von wmic.exe und deren Ausgabeformat. Bei mir ist es UTF-16 LE.
>test.txt WMIC OS Get LocalDateTime
Hexdump von test.txt
FFFE4C006F00630061006C004400610074006500540069006D006500200020002000200020002000200020002000200020002000200020000D000A00320030003100330031003100310035003200310034003300340035002E003400340035003000300030002B00300036003000200020000D000A00

Wenn du so etwas in einer FOR /F Schleife verwurstest, wird's komisch.
>test.txt (for /f "delims=" %%i in ('WMIC OS Get LocalDateTime') do echo(%%i)  
Hexdump von test.txt
4C6F63616C4461746554696D6520202020202020202020202020200D0D0A32303133313131353231353330392E3939353030302B30363020200D0D0A0D0D0A
Ein normaler Zeilenumbruch unter Windows wäre 0D0A. So etwas wie 0D0D0A macht eine normale Verarbeitung unmöglich. Darum die verschachtelte Schleife.
>test.txt (for /f "delims=" %%i in ('WMIC OS Get LocalDateTime') do for /f "delims=" %%j in ("%%i") do echo(%%j)  
Hexdump von test.txt
4C6F63616C4461746554696D6520202020202020202020202020200D0A32303133313131353232303030362E3935323030302B30363020200D0A
Ich hoffe nun ist es klar geworden.


if "%tmpPID%"==" " set "PID=%PID:~1%"
Hmm, und was machst du wenn die PID mal nur 2-stellig ist? Vielleicht solltest du besser mit dem CSV Format bei TASKLIST arbeiten.
Alternativ (statt deinen Zeilen 10 bis 14)
for /f "tokens=*" %%i in ("%PID:~29,4%") do set "PID=%%i"
oder noch einfacher
set /a PID=%PID:~29,4%


Grüße
rubberman