2008-10-16 10 views
19

Mam program C#/.NET, który może działać zarówno jako aplikacja konsolowa, jak i jako usługa. Obecnie udostępniam jej opcję wiersza poleceń jako aplikację konsolową, ale chciałbym tego uniknąć.C#/.NET: Wykrywanie, czy program jest uruchamiany jako usługa lub aplikacja konsoli.

Czy można programowo wykryć, czy mój program jest uruchamiany jako usługa?

Jeśli to była czysta Win32, mógłbym spróbować uruchomić jako usługę z StartServiceCtrlDispatcher i spaść z powrotem do konsoli, jeśli zwrócony ERROR_FAILED_SERVICE_CONTROLLER_CONNECT, ale System.ServiceProcess.ServiceBase.Run() wyskakuje errordialog jeśli to się nie powiedzie, a następnie po prostu zwraca bez sygnalizowania błędu w programie.

Wszelkie pomysły?

+0

Być może OP nie wiedział, że to była dupka, ponieważ pytanie, na które już udzielono odpowiedzi, ma okropne imię. –

Odpowiedz

7

Rasmus, this is the earlier question.

Z odpowiedzi wydaje się, że najpopu- larniejszym sposobem jest użycie prostej opcji wiersza poleceń lub spróbuj uzyskać dostęp do obiektu konsoli w bloku catch catch (w usłudze the Console nie jest dołączona do procesu i próbująca uzyskać do niego dostęp zgłasza wyjątek).

Jeśli masz problemy z testowaniem/debugowaniem usługi, przenieś kod do oddzielnego zestawu dll i utwórz testową wiązkę testową (winforms/console etc).

(Właśnie zauważyłem, że Jonathan dodała jego rozwiązanie koniec pytanie.)

2

Nie próbowałem tego, ale możliwe, że pomoże Process.GetCurrentProcess - w trybie konsoli nazwa procesu będzie taka sama, jak nazwa pliku wykonywalnego, natomiast spodziewałbym się (i jeszcze raz, proszę sprawdzić!), Że podczas działania jako usługa byłaby inna.

+0

Myślałem, że proces był nadal (zwykle) sam ten sam exe, chyba że robisz wszystko, aby rehost przez svchost.exe lub podobne ... –

+0

Może być - trudne do przetestowania z mojego bieżącego biurka: ( –

+0

Co najmniej pod mono, nazwa procesu zmienia się na jednostkę wykonawczą (tj.mi. jeśli jest uruchamiany w trybie mono-service, proces nazywa się teraz mono-service). Nie próbowałem jako usługa Windows. –

21
+5

Co się stanie, jeśli usługa działa w systemie Windows XP z ustawieniem "Zezwalaj tej usłudze na interakcję z pulpitem"? –

+26

To przestanie robić magię, to co :) – Ishmaeel

+0

To również pęka pod różnymi muszlami Cygwin i tym podobnymi. Aby to zrobić, musisz użyć siły WMI. –

1

Nie wiem, czy to zadziała, ale możesz spróbować użyć PInvoke z kodem this i sprawdzić, czy nadrzędny to "services.exe".

3
[DllImport("kernel32.dll", SetLastError = true)] 
static extern IntPtr GetStdHandle(int nStdHandle); 
const int STD_OUTPUT_HANDLE = -11; 

IntPtr iStdOut = GetStdHandle(STD_OUTPUT_HANDLE); 

if (iStdOut == IntPtr.Zero) 

{  
    app.RunAsWindowsService = true; 

} 

// Run as Service 
if (runAsWindowsService)         
{ 
    // ..... 
    ServiceBase.Run(myService); 
} 
else 
{ 
    // Run as Console 
    // Register Ctrl+C Handler... 
} 
+2

Czy to działa, jeśli usługa działa w trybie interaktywnym? –

2

Korzystanie z struct ParentProcessUtilities od this answer o znalezienie proces macierzysty, można to zrobić:

static bool RunningAsService() { 
    var p = ParentProcessUtilities.GetParentProcess(); 
    return (p != null && p.ProcessName == "services"); 
} 

Należy pamiętać, że nazwa procesu dla procesu macierzystego nie zawiera rozszerzenie „.exe”.

0

Skończyło się na wykryciu, czy jestem w aplikacji konsoli, sprawdzając Console.IsErrorRedirected. Zwrócił "false" dla aplikacji konsolowych i "true" dla testowanych aplikacji bez konsoli. Mogłem też użyć IsOutputRedirected.

Wyobrażam sobie, że są okoliczności, w których nie będą one dokładne, ale to zadziałało dobrze.

+0

IsOutputRedirected będzie prawdą, jeśli konsola zostanie uruchomiona z konsoli, a dane wyjściowe zostaną przekierowane lub wyprowadzone (> lub |). – codeape

3

Może chcieć wypróbować właściwość SessionId obiektu Process. Z mojego doświadczenia wynika, że ​​SessionId ma wartość 0, jeśli proces uruchamia usługę.

Powiązane problemy