Jedyne co mi do głowy przychodzi, to możesz w aplikacji A wychwycić event zamknięcia i w tym evencie zamknąć aplikację B
class Program
{
static void Main(string[] args)
{
AppDomain.CurrentDomain.ProcessExit += CurrentDomain_ProcessExit;
}
private static void CurrentDomain_ProcessExit(object sender, EventArgs e)
{
var processes = Process.GetProcessesByName("whatever");
foreach(var process in processes)
{
process.Kill();
}
}
}
Przetestowałem ten sposób i daje efekt zgodny z oczekiwaniem. Dodatkowo, jako alternatywę zaimplementowałem destruktor i w num wywołałem zamknięcie B i również jest tak, jak oczekiwałem, ale to działa dobrze tylko w przypadku standardowego zamknięcia A. W przypadku zakończenia procesu A w menedżerze zadań ani jeden ani drugi sposób nie działa.
Wg mnie fakty które są związane z (jakimkolwiek) kończeniem procesu są potencjalnie skomplikowane i niestabilne.
Zgadzam się z tym i docelowo zamiast zabijania procesu B będę chciał spowodować zwykłe zamknięcie B za pomocą odpowiedniego polecenia wysłanego na standardowe wejście B. Natomiast zabijanie A nie jest przewidziane w normalnym użytkowaniu, jednak na taką ewentualność chcę się przygotować, żeby aplikacja B nie wisiała.
Co jest rzeczywistym celem? Ze wszystkich sił bym zagadnienie ustawił inaczej
Tak naprawdę, ten mechanizm będę chciał wykorzystywać wielokrotnie do różnych celów. W jednym z przypadków jest użycie wbudowanego WebBrowser w WinForms do uruchamiania JavaScript (np. odczyt jakiś informacji z map Google) i wcześniejsze testy wykazały, że jeżeli aplikacja wykorzystująca WebBrowser jest zawieszona, to WebBrowser również jest zawieszony, nie udało mi się uruchomić WebBrowsera w osobnym wątku, żeby mógł działać przy zawieszonym głównym interfejsie, a uruchomienie drugiej specjalnej aplikacji rozwiązało problem (aplikacja macierzysta jest dużym systemem, na którego implementację nie mam pełnego wpływu).
Porobiłem dalsze testy i w aplikacji B musi być pętla uruchomiona w osobnym wątku (przykład, który zapamiętuje każde polecenie, zamyka aplikację na polecenie "exit"):
void ProcessWorkLoop()
{
while (true)
{
string CMD_ = Console.ReadLine();
if (CMD_ == null)
{
CMD_ = "";
Environment.Exit(0);
Application.Exit();
}
LastCmdI = CMD_;
Console.WriteLine(LastCmdO);
string[] CMD = CMD_.Split('|');
switch (CMD[0].ToUpperInvariant())
{
case "exit":
Environment.Exit(0);
Application.Exit();
break;
}
}
}
Stwierdziłem, że w B normalnie pętla wisi na Console.ReadLine()
i odbiera polecenia, ale jak aplikacja A zniknie (zamknięcie lub zabicie z menedżera zadań), to Console.ReadLine()
w B nie zatrzymuje przetwarzania, tylko zwraca null i to wystarczy wychwycić i w takiej sytuacji zamknąć aplikację B.
Ostatecznie problem natenczas wydaje się rozwiązany, przy jednoczesnym zastosowaniu tego, co proponuje AdamWox, destruktora w A i reakcji na null w B nie stwierdziłem przypadków wiszącej aplikacji B przy braku aplikacji A.