Mam następujący odcinek kod, zaprojektowany, aby policzyć ile procesy Excel są obecnie otwarte:Jeśli "Process.HasExited" zgłasza wyjątek, czy mogę założyć, że proces już nie istnieje?
Func<int> OpenExcelProcessesCount =
() => System.Diagnostics.Process.GetProcessesByName("Excel")
.Where(p => !p.HasExited)
.Count();
A potem odzyskać licznik w różnych punktach, z kodem takich jak:
int excelAppCount = OpenExcelProcessesCount();
Ten kod od 100 miesięcy działa poprawnie w 100%. Potem nagle, dzisiaj jest konsekwentnie daje mi wyjątek, który odczytuje następujące:
Exception: ApplicationThreadException Message: Access is denied Stack Trace: at System.Diagnostics.ProcessManager.OpenProcess(Int32
ProcessID, Int32 dostępu, Boolean throwIfExited)
at System.Diagnostics.Process.GetProcessHandle(Int32
dostępu, Boolean throwIfExited)
at System.Diagnostics.Process.get_HasExited() etc...
Zasadniczo połączenie z numerem Process.HasExited
(który pojawia się jako System.Diagnostics.Process.get_HasExited()
w śladzie stosu, powyżej) nie działa. Komunikat o błędzie "Odmowa dostępu" brzmi, jakbym nie miał uprawnień administratora do procesu, ale jedyne istniejące procesy Excela zostałyby utworzone przy moim bieżącym logowaniu użytkownika, a użytkownik zawsze może uzyskać dostęp do własnych procesów. Mój kod .NET również działa pod pełnym zaufaniem.
Linia, która ostatecznie zawodzi, to System.Diagnostics.ProcessManager.OpenProcess(Int32 processId, Int32 access, Boolean throwIfExited)
. Zastanawiam się, czy jest przekazywana w wartość "true" dla parametru "throwIfExited". W takim przypadku, przypuszczam, że mógłbym zabezpieczyć połączenie pod numerem Process.HasExited
z blokiem try-catch i założyć, że jeśli to się nie powiedzie, to HasExited
jest w rzeczywistości "prawdziwe". Ale czy to jest bezpieczne założenie?
Jestem nieswojo czyniąc takie założenie, zwłaszcza, że komunikat o błędzie to "Odmowa dostępu". Czy ktoś ma jakieś pomysły na to, w jaki sposób mogę rozwiązać ten problem lub co mogę przetestować próbując dowiedzieć się, co się dzieje?
Jedyny podobny wątek jaki mogłem znaleźć na Stack Overflow był następujący: Why did hasExited throw ‘System.ComponentModel.Win32Exception’?. Odpowiedź udzielona było:
„Skoro robisz runas, tylko Ci SYNCHRONIZUJ dostęp na rączce, nie PROCESS_QUERY_INFORMATION dostępu stąd GetExitCodeProcess zawiedzie, które skutkuje hasEnded rzucanie Win32 wyjątek. "
Nie bardzo rozumiem tę odpowiedź i nie wiem, czy ma to zastosowanie w moim przypadku, ale pomyślałem, że powinienem o tym wspomnieć. Jeśli ktoś czuje, że jest prawdopodobne, że jest to sytuacja, w której się znajduję, to jeśli ktoś mógłby spróbować wyjaśnić mi tę odpowiedź, byłbym bardzo wdzięczny. (Jestem programista Excel, nie mam dużego doświadczenia w pracy z procesów.)
Much z góry dzięki ...
Aktualizacja:
najlepsze, co mogę powiedzieć, to jest było jednorazowa korupcja.Problemy, z którymi się zetknąłem zaczęły stawać się coraz bardziej dziwaczne, ponieważ to, co było doskonale funkcjonującym zestawem testów jednostkowych, zaczynało mieć awarie w innych "niemożliwych" lokalizacjach. Prosty restart spowodował naprawienie tego problemu i wszystkiego, z czym miałem do czynienia.
Przypuszczam, że miałem dziwne zepsucie. Być może ROT został skonfiskowany i/lub miałem wiszące wystąpienie Excela, które było tak zepsute, że nawet operacje "Process" niekoniecznie były stabilne. Nic ostatecznego, ale to wszystko, co mogę na razie wymyślić.
Do osób, które odpowiedziały, odpowiedziały i pomogły mi, dziękuję.
„Zastanawiam się, czy jest ono przekazywane w wartości«true»dla parametru«throwIfExited»... jest to bezpieczne założenie? ? " Nie. Według Reflector, HasExited przekazuje wartość false dla throwIfExited. Ponadto, jeśli throwIfExited byłyby prawdziwe, wyjątek byłby wyjątkiem InvalidOperationException z komunikatem wskazującym, że proces został zakończony. (Niestety, nie mam odpowiedzi na twoje pytanie, ale pomyślałem, że warto o tym wspomnieć, aby nie tracić czasu na bezowocną teorię.) – itowlson
Dzięki, itowlson, naprawdę doceniam informacje, to zdecydowanie pomaga. –