Win32-APIManchmal benötigt man die Information wo denn die Datei eines bestimmten Prozess liegt. Das .NET Framework bietet zwar einiges an Möglichkeiten mit Prozessen umzugehen, jedoch keine um den Pfad der Datei eines bestimmten Prozess zu ermitteln. Zumindest ist mir keine bekannt. Bevor jetzt begonnen wird auf gut Glück die Verzeichnisse der Laufwerke zu durchsuchen oder etwa in der Windows Registrierung gestöbert wird, lohnt sich ein Blick in die Win32-API. Gerade was die Prozess-Verwaltung angeht, wird hier viel geboten. Mit der Funktion GetProcessImageFileName bietet die Win32-API genau das was benötigt wird. Diese Funktion gibt den Namen mitsamt komplettem Pfad eines bestimmten Prozess zurück. Der Aufruf der Funktion aus der psapi.dll (Process Status API) ist nicht weiter tragisch. Lediglich im DllImportAttribute muss das Feld CharSet mit dem Wert Unicode der CharSet-Enumerationbelegt werden, da sonst evtl. nur Zeichen-Salat zurückgegeben wird.

Wie zu sehen ist, benötigt der erste Parameter ein Prozess-Handle um den Pfad ermitteln zu können. Um das Handle eines bestimmten Prozess zu erhalten, wird die Funktion OpenProcess verwendet.

Diese Funktion erwartet als letzten Parameter eine ProzessID. Der erste Parameter dwDesiredAccess ist ein Wert der ein Prozess spezifisches Zugriffsrecht darstellt. Für meinen Anwendungsfall reicht hier das Recht PROCESS_QUERY_INFORMATION vollkommen aus, da nur der Pfad ermittelt werden soll. Wer mehr darüber erfahren will, kann sich diesen Artikel über Prozess-Sicherheit und Zugriffsrechte durchlesen.

Da geöffnete Handle so bald als möglich wieder geschlossen werden sollten, ist anzuraten auch gleich die Funktion CloseHandle zu implementieren.

Der von der Funktion GetProcessImageFileName zurückgegebene Pfad erscheint allerdings nicht ganz in dem Format in dem wir es gewohnt sind. Windows verwendet intern keine Laufwerksbuchstaben, sondern die Gerätekennung eines Laufwerks. Für uns Anwender werden diesen Gerätekennungen dann Buchstaben zugewiesen, welche wir als Laufwerksbuchstaben kennen. Der Rückgabewert von GetProcessImageFileName für die Datei test.exe könnte also in etwa so aussehen:

 \Device\Harddisk0\Partition1\Program Files\test.exe

Jetzt muss noch ein Weg gefunden werden, diesen Gerätepfad in einen Laufwerkspfad zu übersetzen. Die einzige mir bekannte Funktion der Win32-API die ähnliches bietet, ist die Funktion QueryDosDevice. Beim Import der Funktion muss unbedingt darauf geachtet werden, welche Funktion implementiert wird, da die gleiche Funktion einmal für Ansi und einmal für den Unicode-Zeichensatz vorhanden ist. Ich verwende in C# wenn möglich immer Implementierungen die mit dem Ansi-Zeichensatz arbeiten. Das Unterscheidungsmerkmal der beiden Funktionen ist das A für Ansi und W für den Unicode-Zeichensatz am Ende des Funktionsnamen.

Mit ihr kann zwar nicht direkt der Laufwerksbuchstabe eines Gerätes abgefragt werden, jedoch kann über die Angabe eines Laufwerksbuchstaben der Namen des zugrundeliegenden Gerätes ermittelt werden. Das ist der Ansatz den ich verwendet habe. Im folgenden Screenshot des Überwachen Fensters einer Debugsitzung ist das Auflösen eines Gerätepfad in einen Laufwerkspfad sehr schön zu sehen:

ProcessPath 

Damit der ganze Artikel nicht zu theoretisch bleibt, möchte ich zum Schluss noch eine real verwendete Methode zeigen, die auf der beschriebenen Implementierung basiert. Als Basis zum verwenden von Laufwerksbuchstaben habe ich ein Zeichenfolgen-Array mit dem Alphabet verwendet. Vielleicht gibt es dafür ja einen besseren oder eleganteren Weg. Hier nun die Methode, von der auch der obige Screenshot stammt.

Wie bereits im Kommentar der Methode beschrieben, können mit dieser Methode nicht die Pfade zu Prozessen ermittelt werden die als Dienst gestartet wurden.

Technorati-Tags:  |  |  | 
Wenn ihnen der Artikel gefallen hat oder er für sie hilfreich war, bitte "kicken" sie ihn.
kick it on dotnet-kicks.de