2009-12-26 2 views
5

Ich habe den folgenden Code-Abschnitt, wie viele Prozesse sind Excel zu zählen entwickelt derzeit offen:Wenn 'Process.HasExited' eine Ausnahme auslöst, kann ich davon ausgehen, dass der Prozess weg ist?

Func<int> OpenExcelProcessesCount = 
    () => System.Diagnostics.Process.GetProcessesByName("Excel") 
       .Where(p => !p.HasExited) 
       .Count(); 

Und dann später habe ich die Zählung an verschiedenen Punkten abrufen, mit dem Code wie den folgenden:

int excelAppCount = OpenExcelProcessesCount(); 

Dieser Code läuft seit Monaten zu 100%. Dann plötzlich, heute ist es konsequent zu geben mir eine Ausnahme, die folgenden Wortlaut:

Exception: ApplicationThreadException 

Message: Access is denied 

Stack Trace: 

    at System.Diagnostics.ProcessManager.OpenProcess(Int32 

processId, Int32 Zugang, Boolean throwIfExited)

at System.Diagnostics.Process.GetProcessHandle(Int32 

Zugang, Boolean throwIfExited)

at System.Diagnostics.Process.get_HasExited() 

    etc... 

Grundsätzlich der Anruf an Process.HasExited (das oben in der Stack-Ablaufverfolgung als System.Diagnostics.Process.get_HasExited() angezeigt wird) schlägt fehl. Die Fehlermeldung "Zugriff verweigert" klingt, als hätte ich keine Administratorrechte für den Prozess, aber die einzigen vorhandenen Excel-Prozesse würden unter meiner aktuellen Benutzeranmeldung erstellt, und der Benutzer kann immer auf seine eigenen Prozesse zugreifen. Mein .NET-Code läuft ebenfalls unter voller Vertrauenswürdigkeit.

Die Linie, die letztendlich ausfällt, ist System.Diagnostics.ProcessManager.OpenProcess(Int32 processId, Int32 access, Boolean throwIfExited). Ich frage mich, ob es für den 'throwIfExited' Parameter in einem Wert von 'true' übergeben wird. Wenn dies der Fall ist, nehme ich an, dass ich den Anruf mit einem try-catch-Block auf Process.HasExited schützen könnte, und nehme an, dass, wenn dies fehlschlägt, HasExited tatsächlich "wahr" ist. Aber ist das eine sichere Annahme?

Ich bin unbehaglich machen eine Vermutung wie diese, vor allem seit die Fehlermeldung lautet "Zugriff verweigert". Hat jemand irgendwelche Ideen, wie ich das angehen könnte oder was ich testen könnte, um herauszufinden, was vor sich geht?

Der einzige ähnliche Thread, den ich auf Stack Overflow finden konnte, war der folgende: Why did hasExited throw ‘System.ComponentModel.Win32Exception’?. Die Antwort war:

„Da Sie runas tun, Sie nur Zugriff auf den Griff SYNCHRONIS bekommen, nicht PROCESS_QUERY_INFORMATION Zugang, daher GetExitCodeProcess versagt, die Ergebnisse in hasEnded eine Win32 Ausnahme werfen. "

Ich verstehe diese Antwort nicht wirklich und weiß nicht, ob das in meinem Fall zutrifft, aber ich dachte, ich sollte es erwähnen. Wenn jemand glaubt, dass es wahrscheinlich ist, dass dies die Situation ist, der ich gegenüberstehe, dann würde ich es sehr schätzen, wenn jemand versuchen würde, diese Antwort für mich zu klären. (Ich bin ein Excel-Programmierer, ich habe nicht viel Erfahrung mit Prozessen arbeiten.)

Viel Dank im Voraus ...

Update:

Beste ich kann sagen, dies war kompliziert eine einmalige Korruption in irgendeiner Form.Die Probleme, mit denen ich konfrontiert war, wurden immer bizarrer, da es bei einem perfekt funktionierenden Satz von Komponententests zu Ausfällen an anderen "unmöglichen" Orten kam. Ein einfacher Neustart korrigierte dieses Problem und alles andere, was mir bevorstand.

Meine beste Vermutung ist, dass ich eine Art bizarre Korruption hatte. Vielleicht war der ROT korrupt, und/oder ich hatte eine hängende Excel-Instanz, die so korrupt war, dass selbst "Prozess" -Operationen nicht unbedingt stabil waren. Nichts Schlüssiges, aber das ist alles, was ich für jetzt herausfinden kann.

An die Antwortenden, die sich die Zeit genommen haben, antworten und mir helfen, ich danke Ihnen.

+3

„Ich frage mich, ob es in einem Wert von‚true‘für die‚throwIfExited‘Parameter übergeben wird ... das ist eine sichere Annahme? " Nein. Gemäß Reflector übergibt HasExited den Wert false für throwIfExited. Wenn thrumIfExited true wäre, wäre die Ausnahme eine InvalidOperationException mit einer Nachricht, die anzeigt, dass der Prozess beendet wurde. (Entschuldigung, ich habe keine Antwort auf Ihre Frage, aber ich dachte, es war es wert, dies zu erwähnen, so dass Sie keine Zeit mit einer unfruchtbaren Theorie verbracht haben.) – itowlson

+0

Danke, itowlson, ich schätze die Informationen sehr, das hilft definitiv. –

Antwort

4

Die Antwort, die Sie zitieren, trifft möglicherweise in Ihrem Fall zu. Wie ich es verstehe, heißt es grundsätzlich, dass nicht die Berechtigungen erhalten kann, die benötigt werden, um festzustellen, ob der Prozess beendet wurde, wenn der Prozess, den Sie betrachten, unter einem anderen Benutzerkonto ausgeführt wird.

Jetzt sagen Sie "die einzigen Excel-Prozesse, die vorhanden sind, würde unter meinem aktuellen Benutzer-Login erstellt werden." Aber angenommen, das ist nicht der Fall. Angenommen, es gibt einen anderen Excel-Prozess, der auf derselben Box unter einem anderen Benutzerkonto ausgeführt wird? (Vielleicht wurde jemand von einem anderen Prozess mit OLE-Automatisierung gestartet, und wurde nicht richtig aufgeräumt oder aufgehängt.) Dann würde GetProcessesByName es aufnehmen, aber HasExited würde fehlschlagen.

Bevor Sie Ihre OpenExcelProcessesCount() -Methode aufrufen, fügen Sie eine Protokollierung hinzu, um die Prozess-IDs aller von GetProcessesByName ("Excel") zurückgegebenen Prozesse auszugeben. Dann überprüfen Sie diese gegen den Task-Manager oder die Anzahl der Excel-Prozesse, die Sie in Ihrem Konto erwarten. Wenn es dort eine ID gibt, die nicht einem "erwarteten" Excel-Prozess entspricht, könnten Sie einen Täter haben.

+0

Vielen Dank, ich schätze Ihre Gedanken und Bemühungen hier sehr. Ich werde das mal sehen. Ich sehe nicht, dass dies ein Prozess ist, der bei einem anderen Login erstellt wurde, weil ich der einzige auf diesem Rechner bin und keine anderen Accounts. Ich denke jedoch, dass eine beschädigte/abgestürzte Instanz von Excel * dies verursacht haben könnte. Ich werde nach mehr Tests zurück sein ... –

+0

Meine beste Vermutung ist, dass ich eine Art bizarre Korruption hatte. Neustart hat alles gelöst.Meine Vermutung ist, dass der ROT korrupt war und/oder ich eine hängende Instanz von Excel hatte, die so korrupt war, dass sogar "Prozess" -Operationen nicht unbedingt stabil waren. Nichts Schlüssiges, aber das ist alles, was ich für jetzt herausfinden kann ... Ich schätze die Hilfe. –

1

Nach the documentation Lese:

Verwenden Sie diese Methode ein Array von neuen Prozesskomponenten und Mitarbeiter zu schaffen sie mit allen Prozessressourcen , die die gleiche ausführbaren Datei auf dem lokalen Computer ausgeführt werden.

Es sieht für mich aus, als ob Sie HasExited nicht überprüfen müssen, da es nur laufende Prozesse zurückgibt.

+0

Guter Punkt. Mein Code ist bestenfalls redundant und entspricht einer Race-Bedingung, bei der 'Process.HasExited' nur dann 'false' zurückgeben konnte, wenn ein über 'Process.GetProcessesByName' zurückgegebener Prozess in der Mikrosekunde zwischen dem Empfangen der 'Process'-Instanz und dem Testen beendet wurde "Hat" verlassen. Also habe ich jetzt den Aufruf zu 'HasExited' entfernt. Das vorherige Rätsel bleibt jedoch, aber danke für Ihre Hilfe! –

6

Process.HasExited kann eine Ausnahme mit Zugriffsverweigerung auslösen, wenn der Zielprozess aktiviert ist und Ihr Prozess nicht ausgeführt wird. Das Gleiche passiert auch mit der Eigenschaft StartTime.

Hier ist eine Blog-Post zu diesem Thema mit möglicher Abhilfe: Bugs in System.Diagnostics.Process Class

+1

Danke Giorgi, das ist wirklich gute Info. –

+0

@MikeRosenblum: Das Stacktrace sieht auch ähnlich wie das, das ich im Blog habe. – Giorgi

Verwandte Themen