Obsługa procesu końcowego aplikacji windows

Czy możliwe jest przechwycenie procesu końcowego Menedżera zadań aplikacji windows w tej samej aplikacji windows? Używam aplikacji C # 2.0 win i chciałbym wykonać pewne przetwarzanie bazy danych (zmienić flagę z " Y " na " N " w DB), gdy nastąpi koniec procesu.

Author: Rashmi Pandit, 2009-05-08

6 answers

Nie, nie jest możliwe połączenie decyzji systemu operacyjnego o zakończeniu procesu. Uwaga, nie jest to wykonywane przez żłobek zadań, za zakończenie procesu odpowiada jądro.

Tutaj będziesz musiał zrobić dwie rzeczy:

  1. Podłącz programy obsługi zdarzeń do zwykłych komunikatów interfejsu użytkownika, które informują aplikację o zakończeniu. Użyj tych zdarzeń do utrwalania danych, wolnych zasobów i w inny sposób czystego zakończenia.
  2. obsłuż wyjątki odpowiednio do wychwytywania błędów i sprzątania oraz Zapisz dane, jeśli to możliwe.

Oto trzy linki do bloga Raymonda wyjaśniające, dlaczego nie możesz zrobić tego, o co prosisz.

Podobne pytanie o StackOverflow zadałem również tutaj.

 10
Author: Foredecker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:17

A może nieco inne podejście:

Niech Twoja aplikacja zaktualizuje pole czasu daty, np. LastPollDate co jakiś czas, gdy jest uruchomiona, i ma osobne pole, np. "AppTerminatedNormally", które ustawisz na N, i zmień na Y, jeśli otrzymasz Zdarzenie zamknięcia formularza.

Jeśli aplikacja zostanie zabita za pomocą Menedżera zadań, data nie będzie już aktualizowana, a Twoja aplikacja nadal będzie nie.

W ten sposób można uruchomić zapytanie, które znajdzie wszystkie wiersze, w których LastPollDate jest starszy niż 10 minut i AppTerminatedNormally jest N, i masz wszystkie sesje, które zostały nienormalnie zakończone.

 3
Author: Bork Blatt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-12 15:40:07

Wszyscy będziecie pluć na ten post, ale zaczyna się...

Próbujesz rozwiązać problem na niewłaściwym poziomie(tzn. uruchamiasz kod w aplikacji, gdy kernal zabija aplikację). Prawdziwy problem polega na upewnieniu się, że baza danych poprawnie odzwierciedla obecność (lub nieobecność) aplikacji / aplikacji klienckich.

Aby to rozwiązać, unikaj pozwalania aplikacjom na "niezgodny Stan" między interakcjami użytkowników. Innymi słowy, nie rozpoczynaj transakcji, których nie możesz zatwierdzić szybko nie zapisuj danych do plików, które pozostawiają plik w stanie półpisanym lub nieczytelnym, ani nie przechowuj zasobów poza aplikacją w stanie niezgodnym z interakcjami użytkowników. Inaczej mówiąc, jeśli aplikacja nie jest zajęta odpowiadaniem na obsługę zdarzeń, powinna być gotowa do natychmiastowego zamknięcia.

Jeśli zastosujesz się do powyższej praktyki, znajdziesz kilka scenariuszy, w których musisz "szybko posprzątać"przed zakończeniem. Poza interakcjami, w których użytkownik kliknie " OK" lub "Zapisz", itp. dobrze napisana aplikacja powinna przetrwać natychmiastowe zakończenie bez żadnych trwałych uszkodzeń lub uszkodzeń magazynów danych.

Jeśli bezwzględnie musisz ustawić flagę w bazie danych po wyjściu (która brzmi typowo dla wzorca używanego do wykrywania, czy użytkownik jest zalogowany, czy nie), rozważ jedną z następujących alternatyw:

  1. Okresowo (być może raz na 30 sekund) wstawia/aktualizuje pole podobne do znacznika czasu w bazie danych, aby wskaż, jak niedawno aplikacja była online. Inne aplikacje mogą sprawdzić te znaczniki czasu, aby określić, jak ostatnio inna aplikacja była online... jeśli wartość jest w ciągu ostatnich 30 sekund, druga aplikacja jest nadal opnline.

  2. Jak słusznie zasugerował Woodhenge, Utwórz oddzielny proces (najlepiej usługę), aby monitorować stan głównej aplikacji. Usługi systemu Windows można skonfigurować tak, aby automatycznie uruchamiały się ponownie w przypadku awarii usługi. Monitorowanie to następnie proces wyda znaczniki czasu do bazy danych.

Zauważ, że obie powyższe sugestie rozwiązują rzeczywisty problem (wykrywają, czy aplikacje uzyskują dostęp do bazy danych) bez opuszczania bazy danych w "niespójnym stanie" (wspomniana flaga to "Y", gdy aplikacja jest faktycznie martwa, a flaga powinna być "N").

 2
Author: Mark,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-12 18:31:19

Jeśli kierujesz Windows Vista (lub nowszy), możesz być zainteresowany API Registeraplicationrecoverycallback...

Http://msdn.microsoft.com/en-us/library/aa373345.aspx

Pozwala określić procedurę wywołania zwrotnego w aplikacji, która zostanie wywołana, gdy proces ma ulec awarii. Uwaga: dotyczy to tylko awarii i nie zostanie automatycznie wywołany, jeśli proces zostanie celowo zabity.

Możesz P / wywołać do tego API z C# (zrobiłem to), ale należy pamiętać, że po wywołaniu wywołania zwrotnego aplikacja jest już w bardzo złym stanie i można dokonać bardzo niewielu założeń dotyczących stanu pamięci. Jeśli masz jakieś dane w pamięci, które chcesz użyć w tej rutyny, chciałbym umieścić go w statycznej w bardzo ogólnym zakresie, tak, że masz najlepszą możliwą szansę, że nie zostały "uporządkowane", gdy działa rutynowe wywołanie zwrotne.

Istnieje kilka innych ciekawych API, związanych z tym, które umożliwiają automatyczne ponowne uruchomienie Twoja aplikacja po awarii itp.

 2
Author: Martin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-23 11:27:59

To, co możesz zrobić, to uzyskać identyfikator procesu i monitorować proces, a możesz użyć właściwości HasExited, aby sprawdzić, czy proces się zakończył, czy nie. Poniżej znajduje się szybki kod VB (Przepraszam, nie mam VS teraz. To zostało napisane przeze mnie na innym forum)

Public Class Form1
    Dim p As ProcessStartInfo
    Dim process As Process
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        p = New ProcessStartInfo("iexplore.exe")
        process = process.Start(p)
    End Sub

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        MsgBox(process.Id)
        If process.HasExited Then
            MsgBox("yes")
        Else
            MsgBox("no")
        End If
    End Sub
End Class

Powyższy kod uruchamia Internetexplorer i przycisk sprawdza, czy proces się zakończył, czy nie. Możesz użyć podobnego procesu, aby uzyskać wszystkie uruchomione procesy i użyć processID.

 1
Author: Shoban,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-08 05:00:11

Myślę, że nie jest to możliwe z poziomu aplikacji. Celem zadania końcowego jest natychmiastowe zatrzymanie procesu. Nie pozwala to na wykonanie żadnego czyszczenia kodu.

Shoban wskazał inny sposób na osiągnięcie celu. Inna aplikacja lub usługa musiałaby szukać głównego procesu. Gdy drugi proces nie może znaleźć głównego procesu, możesz wykonać przetwarzanie bazy danych w tym momencie.

 1
Author: jhamm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-09 02:37:56