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

StackOverflow https://stackoverflow.com/questions/207896

  •  03-07-2019
  •  | 
  •  

Вопрос

На этот вопрос уже есть ответ здесь:

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

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

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

Есть идеи?

Это было полезно?

Решение

Расмус, это предыдущий вопрос.

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

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

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

Другие советы

Environment.UserInteractive сотворит волшебство.

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

[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...
}

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

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

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

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

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

В итоге я определил, находился ли я в консольном приложении, проверив Консоль.IsErrorRedirected.Он вернул «false» для консольных приложений и «true» для протестированных мной неконсольных приложений.Я мог бы также использовать Исаутпутредиректед.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top