如何确定是否在Windows服务内启动?

目前我正在通过以下方式检查它:

if (Environment.UserInteractive) Application.Run(new ServiceControllerForm(service)); else ServiceBase.Run(windowsService); 

它有助于调试一点,服务也可以使用可执行文件运行。 但现在假设该服务需要与用户桌面进行交互,因此我必须在属性中启用“允许服务与桌面交互”。 这当然打破了这种检查方式。 还有另一种方式吗?

它并不完美,但你可以这样做:

 public static bool IsService() { ServiceController sc = new ServiceController("MyApplication"); return sc.Status == ServiceControllerStatus.StartPending; } 

我们的想法是,如果您在服务仍在启动时运行此服务,那么它将始终处于暂挂状态。 如果根本没有安装该服务,则该方法将始终返回false。 它只会在服务正在启动的极不可能的极端情况下失败, 并且有人试图同时将其作为应用程序启动。

我不喜欢这个答案,但我认为这可能是你能做的最好的。 实际上,允许相同的应用程序在服务或应用程序模式下运行并不是一个好主意 – 从长远来看,如果将所有常用function抽象到类库中并且只创建一个单独的服务应用程序,则会更容易。 但是如果由于某种原因你真的需要你的蛋糕并且也吃它,你可能会将上面的IsService方法与Environment.UserInteractive结合起来, 几乎在所有时间都能得到正确的答案。

接受的答案的问题是检查未安装的服务的状态将抛出。 我正在使用的IsService方法如下所示:

  private bool IsService(string name) { if (!Environment.UserInteractive) return true; System.ServiceProcess.ServiceController sc = new System.ServiceProcess.ServiceController(name); try { return sc.Status == System.ServiceProcess.ServiceControllerStatus.StartPending; } catch(InvalidOperationException) { return false; } } 

哪个应该比检查Environment.UserInteractive更可靠

为什么不使用命令行开关?

 // Note that you have to add the params argument, // which isn't usually present in windows services private static void Main(params string[] parameters) { .... if (parameters.Length > 0) { if (parameters[0].ToLower() == "/console") { Application.Run(new ServiceControllerForm(service)); { else { ServiceBase.Run(windowsService); } } } 

而不是使用Environment.UserInteractive属性,修改服务的启动方法以检查“-console”命令行参数。 如果参数存在,则作为普通应用程序运行。 如果没有,请作为服务运行。 它不像属性检查那样自动化,但是可以很容易地为桌面添加一个快捷方式,为您添加“-console”命令行参数。

另外,您需要注意在Windows Vista及更高版本中已禁用与桌面的交互。 如果您正在运行需要与用户交互的Windows服务,那么现在批准的方法是将您的前端应用程序与Windows服务分开,并让它们使用WCF等进行通信。

如果需要调试Windows服务(无论是作为服务还是作为应用程序运行),请在启动方法中调用System.Diagnostics.Debugging.Break() 。 这将强制提示您进入调试会话。 我使用这种技术一直调试我的Windows服务。