Hürde beim Warten auf ein Prozessende

In meinem Code von gestern habe ich gacutil.exe gestartet, um die (De)Registrierung einer Assembly im GAC vorzunehmen:

dim psi as New ProcessStartInfo("gacutil.exe", string.Format("/i {0}.dll", assName))
psi.UseShellExecute = false
p = new Process
p.Start(psi)

Das war schön und gut und hat funktioniert. Zwischendurch hatte ich dann mal gedacht, ich sollte vielleicht nach Start() darauf warten, dass der Prozess beendet wird. Also habe ich

p.WaitForExit()

danach eingesetzt. Allerdings hat das immer zu einem Fehler geführt :-( Da es nicht so wichtig war, habe ich es dann 'raus genommen.

Letztlich hat es mich aber nicht in Ruhe gelassen. Warum sollte so ein simpler Aufruf nicht funktionieren? Was konnte ich potenziell falsch gemacht haben? Also habe ich grad mal ein Testprogramm zusammengeklimpert, um das Problem zu isolieren:

dim psi as New ProcessStartInfo("notepad.exe")
psi.UseShellExecute = false
dim p as new Process()
p.Start(psi)
p.WaitForExit

Auch hier trat der Fehler auf. Gut so, also habe ich ein wenig herumexperimentiert. Bei WaitForExit() habe ich in der Doku einen Hinweis darauf gefunden, dass die Methode fehlschlägt, wenn dem Prozess keine Id oder kein Handle zugewiesen ist. Also habe ich mal Folgendes getestet:

...
p.Start(psi)
console.writeline(p.Id)

Das führte auch zu einem Fehler. Die Spur war also richtig. Aber warum sollte der Prozess, den ich mit new Process() erzeuge, keine Id haben??? Weil die Variable p auf keinen endgültig initialisierten Prozess verweist! Die Anweisungen

dim p as new Process()
p.Start(psi)

erzeugen nämlich zwei Prozessobjekte! Auf eines verweist p, ein anderes wird durch p.Start(psi) generiert, weil die Methode Start(ProcessStartInfo) eine statische Methode der Klasse Process ist. Wer hätte das gedacht? Hätte ich geschrieben

dim p as new Process()
p.StartInfo = psi
p.Start()

wäre alles gut gewesen. Der VS.NET Editor für VB.NET hatte mir jedoch auf p auch die Start()-Methode mit dem ProcessStartInfo-Parameter via IntelliSense gelistet, so dass ich mir das Setzen der Property StartInfo sparen wollte. Ich bin also in eine IntelliSense-Falle getappt. Für VB.NET listet VS.NET auf Instanzvariablen auch statische Methoden ihrer Klasse; der C# Codeeditor tut das nicht. Dort wäre mir das Problem nicht untergekommen.

Korrekt funktioniert es also in jedem Fall wie folgt:

dim p as Process = Process.Start(psi)
p.WaitForExit

Die statische Factory-Methode liefert ein vollständig initialisiertes Prozessobjekt zurück, auf dem dann WaitForExit() aufgerufen werden kann.

So schön VB.NET also ist, hier muss man ein wenig aufpassen. Klassenmethoden auf Instanzen aufrufen zu können, ist vielleicht doch keine so gute Idee. Mir fällt auch grad kein Grund ein, warum es nötig sein sollte. Guter OOP-Stil ist es jedenfalls nicht.

No Comments