2009-02-08 13 views
11

Jak wykryć, że moja aplikacja .NET uległa awarii, a następnie ponownie uruchomić?Wykrywanie i ponowne uruchamianie uszkodzonej aplikacji .NET

+0

Znalazłem rozwiązania tego pytania (zanim je zadałem), więc pomyślałem, że byłoby miło mieć odpowiedzi w SO. Jeśli masz dodatkowe odpowiedzi, bądź moim gościem. Lub po prostu wybierz najlepszą odpowiedź, aby poprowadzić innych. Prosimy również o ponowne rozpatrzenie tego pytania, jeśli uznasz to za stosowne. –

+0

Dodano informacje o ponownym uruchomieniu aplikacji konsolowej, ponieważ jest to najwyraźniej to, czego używasz. – RoadWarrior

Odpowiedz

14

Innym rozwiązaniem (na podstawie this example) jest stworzenie wyrzutnię, która kontroluje aplikację:

class LauncherProgram 
{ 
    static int count = 3; 

    static void Main() 
    { 
     Launch(); 
     Thread.Sleep(Timeout.Infinite); 
    } 

    static void Launch() 
    { 
     Process process = new Process(); 
     process.StartInfo.FileName = "MyApp.exe"; 
     process.EnableRaisingEvents = true; 
     process.Exited += LaunchIfCrashed; 
    } 

    static void LaunchIfCrashed(object o, EventArgs e) 
    { 
     Process process = (Process) o; 
     if (process.ExitCode != 0) 
     { 
      if (count-- > 0) // restart at max count times 
       Launch(); 
      else 
       Environment.Exit(process.ExitCode); 
     } 
     else 
     { 
      Environment.Exit(0); 
     } 
    } 
+1

Jedynym możliwym ulepszeniem byłoby uczynienie z "watchdoga" usługi Windows. –

+0

lepiej dodać kod znacznika czasowego i wykryć, czy aplikacja uległa awarii podczas uruchamiania – Sean

1

Możliwym rozwiązaniem jest stworzenie innego procesu, aby monitorować aplikację i uruchomić ją ponownie, jeśli jest rozwiązana:

class ProcessMonitorProgram 
{ 
    const string myProcess = "MyApp.exe"; 

    static void Main() 
    { 
     new Timer(CheckProcess, null, 0, 60 * 1000); 
     Thread.Sleep(Timeout.Infinite); 
    } 

    static void CheckProcess(object obj) 
    { 
     if (Process.GetProcessesByName(myProcess).Length == 0) 
      Process.Start(myProcess); 
    } 
} 

Jednym z problemów, z tego rozwiązania jest to, że będzie na bieżąco proces ponownego uruchamiania zawsze, aż ta aplikacja monitorująca została zakończona.

5
  • uruchomienia prac wewnątrz AppDomain; użyj głównej AppDomain do monitorowania (nie chroni przed zabiciem procesu).
  • wiele wyjątków! czyli nie daj błąd krytyczny zburzyć proces
  • uruchomić go w coś, co ma już wbudowany w recyklingu - IIS na przykład
+1

Dzięki Marc. Czy mógłbyś dodać przykład, jak zaimplementować proponowane rozwiązanie oparte na AppDomain? –

+0

Zakładając, że jest to aplikacja Windows Forms lub konsola, możesz użyć Application.Restart - zobacz moją odpowiedź, by poznać szczegóły. – RoadWarrior

8

Jeśli jest to Windows Forms aplikacji:

  • Set jitDebugging = true w App.Config. Zapobiega to uruchomieniu wbudowanego programu obsługi formularzy nieobsługiwanego formularza Windows Forms.

Teraz, niezależnie od tego, czy jest to aplikacja Windows Forms lub aplikację konsoli:

  • rejestracji na Application.ThreadException zdarzenia, na przykład w języku C#:

    Application.ThreadException + = new Threading.ThreadExceptionHandler (CatchFatalException);

W tym momencie Twoja aplikacja jest już w drodze do czarnej dziury. Co dzieje się dalej, zależy od tego, czy jest to aplikacja Windows Forms:

  • Jeśli jest to Windows Forms aplikacji, należy wywołać metodę Application.Restart w swojej obsługi zdarzeń CatchFatalException.
  • W przeciwnym razie konieczne będzie p/wywołanie funkcji macierzystych application restart and recovery. Ten link omawia Vista, ale w moich testach działa dobrze na XP.
+0

Dziękuję. Czy aplikacja konsolowa może zrobić coś podobnego do 'Application.ThreadException + = MyHandler;'? –

+0

Tak, aplikacja konsoli może zrobić to samo. – RoadWarrior

+0

Ale nie ma dostępu do klasy Application, prawda? –

Powiązane problemy