我目前正在为可以在控制台中运行的服务编写一些引导程序代码。从本质上讲,它归结为调用OnStart()方法,而不是使用ServiceBase来启动和停止服务(因为如果未将其作为服务安装,则它不会运行该应用程序,并且会使调试成为噩梦)。
现在,我正在使用Debugger.IsAttached确定是否应该使用ServiceBase.Run或[service] .OnStart,但是我知道这不是最好的主意,因为有时最终用户希望在控制台中运行该服务(以查看输出等)。
关于如何确定Windows服务控制器是否在控制台中启动“我”或用户是否在控制台中启动“我”的任何想法?显然,Environment.IsUserInteractive不是答案。我考虑过使用命令行参数,但这似乎“肮脏”。
我总是可以看到围绕ServiceBase.Run的try-catch语句,但这似乎很脏。编辑:尝试捕获不起作用。
我有一个解决方案:将其放置在这里,供所有其他感兴趣的堆叠器使用:
public void Run() { if (Debugger.IsAttached || Environment.GetCommandLineArgs().Contains<string>("-console")) { RunAllServices(); } else { try { string temp = Console.Title; ServiceBase.Run((ServiceBase[])ComponentsToRun); } catch { RunAllServices(); } } } // void Run private void RunAllServices() { foreach (ConsoleService component in ComponentsToRun) { component.Start(); } WaitForCTRLC(); foreach (ConsoleService component in ComponentsToRun) { component.Stop(); } }
编辑:在StackOverflow上还有另一个问题,那里的人与Environment.CurrentDirectory是“ C:\ Windows \ System32”的问题看起来可能是答案。我今天要测试。
像Ash一样,我将所有实际的处理代码编写在单独的类库程序集中,然后由Windows Service可执行文件以及控制台应用程序引用。
但是,有时候了解类库是否在服务可执行文件或控制台应用程序的上下文中运行很有用。我这样做的方法是反思托管应用程序的基类。(对VB表示抱歉,但是我认为可以很容易地对C#进行以下修饰):
Public Class ExecutionContext ''' <summary> ''' Gets a value indicating whether the application is a windows service. ''' </summary> ''' <value> ''' <c>true</c> if this instance is service; otherwise, <c>false</c>. ''' </value> Public Shared ReadOnly Property IsService() As Boolean Get ' Determining whether or not the host application is a service is ' an expensive operation (it uses reflection), so we cache the ' result of the first call to this method so that we don't have to ' recalculate it every call. ' If we have not already determined whether or not the application ' is running as a service... If IsNothing(_isService) Then ' Get details of the host assembly. Dim entryAssembly As Reflection.Assembly = Reflection.Assembly.GetEntryAssembly ' Get the method that was called to enter the host assembly. Dim entryPoint As System.Reflection.MethodInfo = entryAssembly.EntryPoint ' If the base type of the host assembly inherits from the ' "ServiceBase" class, it must be a windows service. We store ' the result ready for the next caller of this method. _isService = (entryPoint.ReflectedType.BaseType.FullName = "System.ServiceProcess.ServiceBase") End If ' Return the cached result. Return CBool(_isService) End Get End Property Private Shared _isService As Nullable(Of Boolean) = Nothing #End Region End Class