C#/.NET:检测程序是作为服务还是作为控制台应用程序运行
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/207896/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C#/.NET: Detect whether program is being run as a service or a console application
提问by Rasmus Faber
I have a C#/.NET program that can run both as a console application and as a service. Currently I give it a command-line option to start as a console application, but I would like to avoid that.
我有一个 C#/.NET 程序,它可以作为控制台应用程序和服务运行。目前我给它一个命令行选项以作为控制台应用程序启动,但我想避免这种情况。
Is it possible to programmatically detect whether my program is being started as a service?
是否可以以编程方式检测我的程序是否作为服务启动?
If it was pure Win32, I could try starting as a service with StartServiceCtrlDispatcher and fall back to console if it returned ERROR_FAILED_SERVICE_CONTROLLER_CONNECT, but System.ServiceProcess.ServiceBase.Run() pops up an errordialog if it fails and then just returns without signaling an error to the program.
如果它是纯 Win32,我可以尝试使用 StartServiceCtrlDispatcher 作为服务启动,如果它返回 ERROR_FAILED_SERVICE_CONTROLLER_CONNECT,则返回到控制台,但 System.ServiceProcess.ServiceBase.Run() 如果失败则弹出一个错误对话框,然后直接返回而不发出错误信号到程序。
Any ideas?
有任何想法吗?
采纳答案by Ash
Rasmus, this is the earlier question.
拉斯姆斯, 这是之前的问题。
From the answers it seems the most popular way is to use a simple command line option, or try accessing the Console object in a try catch block (in a Service the Console is not attached to the process and trying to access it throws an exception).
从答案看来,最流行的方法是使用简单的命令行选项,或者尝试在 try catch 块中访问 Console 对象(在服务中,控制台未附加到进程并尝试访问它会引发异常) .
Or if you're having trouble testing/debugging the service, move code into a separate dll assembly and create a seprate test harness (winforms/console etc).
或者,如果您在测试/调试服务时遇到问题,请将代码移动到单独的 dll 程序集中并创建单独的测试工具(winforms/控制台等)。
(Just noticed that Jonathan has added his solution to the end of the question.)
(刚刚注意到乔纳森在问题的末尾添加了他的解决方案。)
回答by Jon Skeet
I haven't tried it, but it's possible that Process.GetCurrentProcesswill help - under console mode the process name would be the same as the executable, whereas I'd expect (and again, please check!) that when running as a service it would be different.
我还没有尝试过,但Process.GetCurrentProcess可能会有所帮助 - 在控制台模式下,进程名称将与可执行文件相同,而我希望(再次,请检查!)作为服务运行时它会有所不同。
回答by Vlad Nagorny
Environment.UserInteractivewill do the magic.
回答by ta.speot.is
回答by Chin Siang
[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...
}
回答by Dylan Nissley
Using the ParentProcessUtilities struct from this answerabout finding a parent process, you can do this:
使用这个关于查找父进程的答案中的 ParentProcessUtilities 结构,您可以执行以下操作:
static bool RunningAsService() {
var p = ParentProcessUtilities.GetParentProcess();
return ( p != null && p.ProcessName == "services" );
}
Note that the process name for the parent process does not include the extension ".exe".
请注意,父进程的进程名称不包括扩展名“.exe”。
回答by NightShovel
I ended up detecting whether or not I was in a console application by checking Console.IsErrorRedirected. It returned "false" for console apps, and "true" for the non-console apps I tested. I could have also used IsOutputRedirected.
我最终通过检查Console.IsErrorRedirected来检测我是否在控制台应用程序中。它为控制台应用程序返回“false”,为我测试的非控制台应用程序返回“true”。我也可以使用IsOutputRedirected。
I imagine there are circumstances where these will not be accurate, but this worked well for me.
我想在某些情况下这些不会准确,但这对我来说效果很好。
回答by Curt Williams
Might want to try SessionId property of the Process object. In my experience SessionId is set to 0 if the process is running a service.
可能想尝试 Process 对象的 SessionId 属性。根据我的经验,如果进程正在运行服务,则 SessionId 设置为 0。