С#/. NET: определить, запущена ли программа как служба или консольное приложение
У меня есть программа С#/. NET, которая может запускаться как консольное приложение, так и как служба.
В настоящее время я предоставляю ему параметр командной строки для запуска в качестве консольного приложения, но я бы хотел этого избежать.
Можно ли программно определить, запускается ли моя программа в качестве службы?
Если бы это была чистая Win32, я мог бы попробовать начать с сервиса StartServiceCtrlDispatcher и вернуться к консоли, если он вернет ERROR_FAILED_SERVICE_CONTROLLER_CONNECT, но System.ServiceProcess.ServiceBase.Run() выдает ошибочный аргумент, если он терпит неудачу, а затем просто возвращается без сигнализируя об ошибке программе.
Любые идеи?
Ответы
Ответ 1
Rasmus, это более ранний вопрос.
Из ответов, по-видимому, наиболее популярным способом является использование простой опции командной строки или попытка доступа к объекту Console в блоке try catch (в Сервисе Console не подключен к процессу и пытается получить к нему доступ исключение).
Или, если у вас возникли проблемы с тестированием/отладкой службы, переместите код в отдельную сборку dll и создайте отдельный тестовый жгут (winforms/console и т.д.).
(Только что заметил, что Джонатан добавил свое решение в конец вопроса.)
Ответ 2
Environment.UserInteractive будет делать магию.
Ответ 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.
Я предполагаю, что есть обстоятельства, когда они не будут точными, но это сработало для меня.