27

我有一个可以作为控制台应用程序和服务运行的 C#/.NET 程序。目前我给它一个命令行选项来作为控制台应用程序启动,但我想避免这种情况。

是否可以以编程方式检测我的程序是否作为服务启动?

如果它是纯 Win32,我可以尝试使用 StartServiceCtrlDispatcher 作为服务启动,如果它返回 ERROR_FAILED_SERVICE_CONTROLLER_CONNECT,则返回到控制台,但 System.ServiceProcess.ServiceBase.Run() 如果失败,则会弹出一个错误对话框,然后返回而不会发出错误信号到程序。

有任何想法吗?

4

8 回答 8

33

Environment.UserInteractive will do the magic.

于 2010-02-18T10:39:31.080 回答
7

拉斯穆斯, 这是前面的问题

从答案看来,最流行的方法是使用简单的命令行选项,或尝试在 try catch 块中访问控制台对象(在服务中,控制台未附加到进程并尝试访问它会引发异常) .

或者,如果您在测试/调试服务时遇到问题,请将代码移动到单独的 dll 程序集中并创建单独的测试工具(winforms/console 等)。

(刚刚注意到乔纳森在问题的末尾添加了他的解决方案。)

于 2008-10-16T09:47:19.340 回答
6

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.

于 2014-10-14T19:04:26.197 回答
3

我没有尝试过,但Process.GetCurrentProcess可能会有所帮助 - 在控制台模式下,进程名称将与可执行文件相同,而我希望(再次,请检查!)作为服务运行时情况会有所不同。

于 2008-10-16T09:26:37.697 回答
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...
}
于 2011-06-01T14:40:27.537 回答
3

Using the ParentProcessUtilities struct from this answer about finding a parent process, you can do this:

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".

于 2013-04-26T13:19:37.907 回答
1

I don't know if this will work, but you may want to try using PInvoke with this code and checking if the parent is "services.exe".

于 2010-02-18T11:09:31.130 回答
0

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.

I imagine there are circumstances where these will not be accurate, but this worked well for me.

于 2013-07-31T23:48:23.500 回答