将Windows服务作为控制台应用程序运行

pin*_*nki 30 c# windows-services

我想调试一个Windows服务,但它弹出一条错误消息说

无法从命令行或调试器启动服务.必须使用installutil.exe安装Windows服务,然后使用Server explorer,Windows服务管理工具或NET启动命令启动.

我真的不知道这个错误.....

在此输入图像描述

Chr*_*ham 39

在运行Windows服务之前,必须首先使用installutil"安装"它.例如:

C:\installutil -i c:\path\to\project\debug\service.exe
Run Code Online (Sandbox Code Playgroud)

然后,您可以打开服务列表以启动它.例如:

  1. 右击"我的电脑"
  2. 点击"管理"
  3. 打开'服务和应用'
  4. 点击"服务"
  5. 在列表中找到您的服务,然后右键单击它
  6. 点击"开始"

启动后,您可以进入Visual Studio,单击"Debug",然后单击"Attach to Process".

另一种方法是将此行添加到服务中的OnStart()方法:

System.Diagnostics.Debugger.Launch();
Run Code Online (Sandbox Code Playgroud)

当你这样做时,它会提示你选择一个Visual Studio实例来调试服务.

  • 你可能不会在`C:\ InstallUtil.exe`找到`InstallUtil`.你应该看看`C:\ Windows\Microsoft.NET\Framework [ARCH]\v [VERSION]\InstallUtil.exe`. (11认同)
  • 为了运行`installutil`,我发现[运行Developer Command Prompt](https://msdn.microsoft.com/en-us/library/ms229859(v = vs.110).aspx)和`installutil`是最简单的已经在路径中,因此您可以在不指定位置的情况下执行它. (4认同)
  • 我很抱歉,但我无法执行此操作C:\ installutil -ic:\ path\to\project\debug\service.exe (2认同)

Ofe*_*lig 16

您可以根据您是否处于DEBUG模式(通常在Visual Studio内部但不一定是)或RELEASE模式(当它作为生产中的服务运行时)来更改程序集的启动模式:

改变这个:

static class Program
{
    static void Main()
    {
        ServiceBase[] ServicesToRun;
        ServicesToRun = new ServiceBase[] 
        { 
            new MyService() 
        };
        ServiceBase.Run(ServicesToRun);
    }
}
Run Code Online (Sandbox Code Playgroud)

对此:

static class Program
{
    static void Main()
    {
        #if(!DEBUG)
            ServiceBase[] ServicesToRun;
            ServicesToRun = new ServiceBase[] 
            { 
                new MyService() 
            };
            ServiceBase.Run(ServicesToRun);
        #else
            MyService myServ = new MyService();
            myServ.Process();
            // here Process is my Service function
            // that will run when my service onstart is call
            // you need to call your own method or function name here instead of Process();
        #endif
    }
}
Run Code Online (Sandbox Code Playgroud)

该技术取自本文,该文章的作者Tejas Vaishnav负责.我在这里复制了代码片段,因为SO赞成完整的答案而不是可能在某个时间消失的链接.


Ste*_*ner 6

为了防止发生此错误并允许服务在通常的服务控制器之外运行,您可以检查该Environment.UserInteractive标志。如果已设置,您可以运行服务并将输出输出到控制台,而不是让它运行到返回该错误的 ServiceBase 代码。

将其添加到 Program.Main() 的开头,在使用 ServiceBase 运行服务的代码之前:

        if (Environment.UserInteractive)
        {
            var service = new WindowsService();
            service.TestInConsole(args);
            return;
        }
Run Code Online (Sandbox Code Playgroud)

由于 OnStart 和 OnStop 方法protected在您的服务中,您需要向该类添加另一个方法,您可以从 Main() 运行该方法并为您调用这些方法,例如:

    public void TestInConsole(string[] args)
    {
        Console.WriteLine($"Service starting...");
        this.OnStart(args);
        Console.WriteLine($"Service started. Press any key to stop.");
        Console.ReadKey();
        Console.WriteLine($"Service stopping...");
        this.OnStop();
        Console.WriteLine($"Service stopped. Closing in 5 seconds.");
        System.Threading.Thread.Sleep(5000);
    }
Run Code Online (Sandbox Code Playgroud)

最后,确保输出是项目属性中的控制台应用程序。

您现在可以像其他服务一样运行服务可执行文件,它将作为控制台启动。如果从 Visual Studio 启动它,调试器将自动附加。如果您注册它并将其作为服务启动,它将作为服务正常运行,无需任何更改。

我发现的唯一区别是,当作为控制台应用程序运行时,代码不会写入事件日志,您可能还想输出通常记录到控制台的任何内容。

此服务调试技术是learn.microsoft.com上解释的技术之一


use*_*910 5

有一个 nuget 包可以解决这个问题:install-package WindowsService.Gui

运行程序 GUI 的图像

该包有什么作用?

它通过在附加调试器运行时创建播放/停止/暂停 UI 来提供帮助,而且还允许 Windows 服务由 Windows 服务环境安装和运行。这一切只需一行代码!什么是 Service Helper 作为经常编写 Windows 服务的人,处理调试服务中涉及的令人头痛的问题可能会令人沮丧。通常它涉及技巧、黑客和部分解决方法来测试所有代码。Windows 服务开发人员不会有“只需按 F5”的体验。

Service Helper 通过在附加了模拟(尽可能接近)Windows 服务环境的调试器时触发显示 UI 来解决此问题。

github项目在这里:https://github.com/wolfen351/windows-service-gui

如何使用?

在项目中获取 Windows Service Helper 的最简单方法是使用 NuGet 官方源上的 NuGet 包 ServiceProcess.Helpers。

只需对应用程序的“Program.cs”中的典型代码进行一些更改即可:

using System.ServiceProcess;
using ServiceProcess.Helpers; //HERE

namespace DemoService
{
    static class Program
    {
    static void Main()
    {
        ServiceBase[] ServicesToRun;

        ServicesToRun = new ServiceBase[] 
            { 
                new Service1() 
            };

        //ServiceBase.Run(ServicesToRun);
        ServicesToRun.LoadServices(); //AND HERE
    }
    }
}
Run Code Online (Sandbox Code Playgroud)

披露:我是这个项目的维护者

注意:UI 是可选的