Muszę napisać niezawodny kod w .NET, aby umożliwić ponowne uruchomienie usługi systemu Windows (serwer 2003). Jaki jest najlepszy sposób, aby to zrobić? Czy jest do tego jakiś interfejs API .NET?
Muszę napisać niezawodny kod w .NET, aby umożliwić ponowne uruchomienie usługi systemu Windows (serwer 2003). Jaki jest najlepszy sposób, aby to zrobić? Czy jest do tego jakiś interfejs API .NET?
Odpowiedzi:
Ustaw usługę na restart po awarii (dwukrotnie kliknij usługę w panelu sterowania i rozejrzyj się po tych zakładkach - zapomniałem jej nazwy). Następnie, za każdym razem, gdy chcesz, aby usługa została ponownie uruchomiona, po prostu zadzwoń Environment.Exit(1)
(lub jakikolwiek zwrot niezerowy), a system operacyjny zrestartuje ją za Ciebie.
Service.ExitCode = 1
a następnie wykonać Service.Stop()
wraz z zaznaczeniem pola wyboru „Włącz akcje dla zatrzymań z błędami” na ekranie ustawień odzyskiwania usługi. Zrobienie tego w ten sposób pozwala na prawidłowe zamknięcie i nadal powoduje ponowne uruchomienie.
Dim proc As New Process()
Dim psi As New ProcessStartInfo()
psi.CreateNoWindow = True
psi.FileName = "cmd.exe"
psi.Arguments = "/C net stop YOURSERVICENAMEHERE && net start YOURSERVICENAMEHERE"
psi.LoadUserProfile = False
psi.UseShellExecute = False
psi.WindowStyle = ProcessWindowStyle.Hidden
proc.StartInfo = psi
proc.Start()
Nie możesz być pewien, że konto użytkownika, na którym działa Twoja usługa, ma nawet uprawnienia do zatrzymywania i ponownego uruchamiania usługi.
Możesz utworzyć proces będący wierszem poleceń DOS, który uruchamia się ponownie:
Process process = new Process();
process.StartInfo.FileName = "cmd";
process.StartInfo.Arguments = "/c net stop \"servicename\" & net start \"servicename\"";
process.Start();
const string strCmdText = "/C net stop \"SERVICENAME\"&net start \"SERVICENAME\"";
Process.Start("CMD.exe", strCmdText);
gdzie SERVICENAME
jest nazwą Twojej usługi (podwójne cudzysłowy uwzględniają spacje w nazwie usługi, w przeciwnym razie można pominąć).
Czysty, nie jest wymagana konfiguracja automatycznego restartu.
Zależałoby to od tego, dlaczego chcesz, aby sam się zrestartował.
Jeśli szukasz tylko sposobu na okresowe czyszczenie usługi, możesz mieć uruchomiony licznik czasu w usłudze, który okresowo powoduje procedurę czyszczenia.
Jeśli szukasz sposobu na ponowne uruchomienie w przypadku awarii - sam host usługi może zapewnić tę możliwość podczas konfiguracji.
Dlaczego więc musisz restartować serwer? Co próbujesz osiągnąć?
Nie sądzę, abyś mógł w samodzielnej usłudze (gdy zadzwonisz do Restart, zatrzyma usługę, co przerwie polecenie Restart i nigdy więcej nie zostanie uruchomione). Jeśli możesz dodać drugi plik .exe (aplikację konsoli, która używa klasy ServiceManager), możesz uruchomić autonomiczny plik .exe i uruchomić ponownie usługę, a następnie zakończyć.
Po namyśle prawdopodobnie mógłbyś poprosić usługę o zarejestrowanie zaplanowanego zadania (na przykład za pomocą polecenia „at” w wierszu poleceń), aby uruchomić usługę, a następnie spowodować jej zatrzymanie; to prawdopodobnie by zadziałało.
Problem z wyrzucaniem do pliku wsadowego lub pliku EXE polega na tym, że usługa może mieć uprawnienia wymagane do uruchomienia aplikacji zewnętrznej lub nie.
Najczystszym sposobem, jaki znalazłem, jest użycie metody OnStop (), która jest punktem wejścia dla Menedżera sterowania usługami. Wtedy cały kod czyszczący zostanie uruchomiony i nie będziesz mieć żadnych zawieszonych gniazd ani innych procesów, zakładając, że kod zatrzymujący wykonuje swoją pracę.
Aby to zrobić, musisz ustawić flagę przed zakończeniem, która mówi metodzie OnStop, aby zakończyła pracę z kodem błędu; wtedy SCM wie, że usługa wymaga ponownego uruchomienia. Bez tej flagi nie będzie można ręcznie zatrzymać usługi z poziomu SCM. Zakłada się również, że usługa została skonfigurowana do ponownego uruchamiania w przypadku błędu.
Oto mój kod zatrzymania:
...
bool ABORT;
protected override void OnStop()
{
Logger.log("Stopping service");
WorkThreadRun = false;
WorkThread.Join();
Logger.stop();
// if there was a problem, set an exit error code
// so the service manager will restart this
if(ABORT)Environment.Exit(1);
}
Jeśli usługa napotka problem i musi zostać ponownie uruchomiona, uruchamiam wątek, który zatrzymuje usługę z SCM. Pozwala to usłudze posprzątać po sobie:
...
if(NeedToRestart)
{
ABORT = true;
new Thread(RestartThread).Start();
}
void RestartThread()
{
ServiceController sc = new ServiceController(ServiceName);
try
{
sc.Stop();
}
catch (Exception) { }
}
Użyłbym harmonogramu systemu Windows do zaplanowania ponownego uruchomienia usługi. Problem polega na tym, że nie możesz się zrestartować, ale możesz się zatrzymać. (Zasadniczo odpiłowałeś gałąź, na której siedzisz ... jeśli masz moją analogię) Potrzebujesz oddzielnego procesu, aby zrobić to za siebie. Harmonogram systemu Windows jest odpowiedni. Zaplanuj jednorazowe zadanie ponownego uruchomienia usługi (nawet z poziomu samej usługi) w celu natychmiastowego wykonania.
W przeciwnym razie będziesz musiał stworzyć proces „pasterski”, który zrobi to za Ciebie.
Pierwszą odpowiedzią na pytanie jest najprostsze rozwiązanie: „Environment.Exit (1)” Używam tego na Windows Server 2008 R2 i działa idealnie. Usługa zatrzymuje się, system operacyjny czeka 1 minutę, a następnie uruchamia ją ponownie.
Myślę, że nie może. Kiedy usługa zostaje „zatrzymana”, zostaje całkowicie rozładowana.
Cóż, OK, przypuszczam, że zawsze istnieje sposób. Na przykład możesz utworzyć odłączony proces, aby zatrzymać usługę, a następnie uruchomić ją ponownie, a następnie zakończyć.
Lepszym podejściem może być wykorzystanie usługi NT jako opakowania aplikacji. Po uruchomieniu usługi NT aplikacja może zostać uruchomiona w trybie „bezczynności”, czekając na uruchomienie polecenia (lub może zostać skonfigurowana do automatycznego uruchamiania).
Pomyśl o samochodzie, gdy jest uruchamiany, zaczyna się na biegu jałowym, czekając na polecenie ruchu do przodu lub do tyłu. Zapewnia to również inne korzyści, takie jak lepsza administracja zdalna, ponieważ możesz wybrać sposób udostępnienia aplikacji.
Tylko przekazuję: i pomyślałem, że dodam dodatkowe informacje ...
możesz również rzucić wyjątek, spowoduje to automatyczne zamknięcie usługi systemu Windows, a opcje automatycznego ponownego uruchomienia po prostu się włączy. Jedynym problemem jest to, że jeśli masz środowisko programistyczne na swoim komputerze, JIT próbuje się uruchomić, a pojawi się monit o debugowanie T / N. powiedz nie, a następnie zamknie się, a następnie uruchomi się ponownie. (na komputerze bez JIT wszystko działa). powodem, dla którego trolluję, jest to, że ten JIT jest nowy w Win 7 (działał dobrze z XP itp.) i próbuję znaleźć sposób na wyłączenie JIT ... mogę wypróbować wspomnianą tutaj metodę Environment.Exit zobacz jak to też działa.
Kristian: Bristol, Wielka Brytania
Utwórz plik restart.bat w ten sposób
@echo on
set once="C:\Program Files\MyService\once.bat"
set taskname=Restart_MyService
set service=MyService
echo rem %time% >%once%
echo net stop %service% >>%once%
echo net start %service% >>%once%
echo del %once% >>%once%
schtasks /create /ru "System" /tn %taskname% /tr '%once%' /sc onstart /F /V1 /Z
schtasks /run /tn %taskname%
Następnie usuń zadanie% taskname% po uruchomieniu% service%
Utwórz oddzielną domenę aplikacji do hostowania kodu aplikacji. Gdy wymaga ponownego uruchomienia, możemy zwolnić i ponownie załadować domenę aplikacji zamiast procesu (usługa Windows). W ten sposób działa pula aplikacji usług IIS, nie uruchamiają aplikacji asp.net bezpośrednio, używają oddzielnej aplikacji appdmain.
Najłatwiej jest mieć plik wsadowy zawierający:
net stop net start
i dodaj plik do harmonogramu z żądanym przedziałem czasu
private static void RestartService(string serviceName)
{
using (var controller = new ServiceController(serviceName))
{
controller.Stop();
int counter = 0;
while (controller.Status != ServiceControllerStatus.Stopped)
{
Thread.Sleep(100);
controller.Refresh();
counter++;
if (counter > 1000)
{
throw new System.TimeoutException(string.Format("Could not stop service: {0}", Constants.Series6Service.WindowsServiceName));
}
}
controller.Start();
}
}