Подтвердить что ты не робот

С#/. NET: определить, запущена ли программа как служба или консольное приложение

У меня есть программа С#/. NET, которая может запускаться как консольное приложение, так и как служба. В настоящее время я предоставляю ему параметр командной строки для запуска в качестве консольного приложения, но я бы хотел этого избежать.

Можно ли программно определить, запускается ли моя программа в качестве службы?

Если бы это была чистая Win32, я мог бы попробовать начать с сервиса StartServiceCtrlDispatcher и вернуться к консоли, если он вернет ERROR_FAILED_SERVICE_CONTROLLER_CONNECT, но System.ServiceProcess.ServiceBase.Run() выдает ошибочный аргумент, если он терпит неудачу, а затем просто возвращается без сигнализируя об ошибке программе.

Любые идеи?

4b9b3361

Ответ 1

Rasmus, это более ранний вопрос.

Из ответов, по-видимому, наиболее популярным способом является использование простой опции командной строки или попытка доступа к объекту Console в блоке try catch (в Сервисе Console не подключен к процессу и пытается получить к нему доступ исключение).

Или, если у вас возникли проблемы с тестированием/отладкой службы, переместите код в отдельную сборку dll и создайте отдельный тестовый жгут (winforms/console и т.д.).

(Только что заметил, что Джонатан добавил свое решение в конец вопроса.)

Ответ 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...
}

Ответ 4

Возможно, вы захотите попробовать свойство SessionId объекта Process. По моему опыту SessionId установлен в 0, если процесс запускает службу.

Ответ 5

Я не пробовал, но возможно, что Process.GetCurrentProcess поможет - в режиме консоли имя процесса будет одинаковым в качестве исполняемого файла, в то время как я ожидал бы (и снова, пожалуйста, проверьте!), что при работе в качестве службы это будет другим.

Ответ 6

Используя конструкцию ParentProcessUtilities из этого вопроса о поиске родительского процесса, вы можете сделать это:

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

Обратите внимание, что имя процесса для родительского процесса не включает расширение ".exe".

Ответ 7

Я не знаю, будет ли это работать, но вы можете попробовать использовать PInvoke с этот код и проверить, является ли родительский "services.exe".

Ответ 8

В итоге я обнаружил, был ли я в консольном приложении, проверив Console.IsErrorRedirected. Он вернул "ложный" для консольных приложений и "истинный" для неконсервированных приложений, которые я тестировал. Я мог бы также использовать IsOutputRedirected.

Я предполагаю, что есть обстоятельства, когда они не будут точными, но это сработало для меня.