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

46

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

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

对于这个错误,我并不是很清楚......

输入图像描述


4
我刚刚好像看到了一个类似这样的帖子。链接在此:https://dev59.com/RW435IYBdhLWcg3w4UWs - Brad Christie
6个回答

46

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

C:\installutil -i c:\path\to\project\debug\service.exe

你可以打开服务列表来启动它。例如:

  1. 右键单击“我的电脑”
  2. 点击“管理”
  3. 打开“服务和应用程序”
  4. 点击“服务”
  5. 在列表中找到你的服务并右键单击它
  6. 点击“启动”

一旦它已经启动,你可以进入Visual Studio,点击“调试”,然后点击“附加到进程”。

另一种技术是在服务的OnStart()方法中添加这行代码:

System.Diagnostics.Debugger.Launch();

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


1
顺便提一下,我发现在 OnCommitted 方法中使用以下代码创建安装程序非常好用:using (ServiceController sc = new ServiceController(__SERVICENAME__)){sc.Start();}(或者您可以按照描述手动启动)。 - Brad Christie
2
抱歉,我无法执行此操作 C:\installutil -i c:\path\to\project\debug\service.exe。 - pinki
14
你可能找不到C:\InstallUtil.exe。你应该查看C:\Windows\Microsoft.NET\Framework[ARCH]\v[VERSION]\InstallUtil.exe。这里会有更多的可能性找到它。请注意替换[ARCH][VERSION]为适当的架构和版本号。 - AlicanC
6
对于运行 installutil,我发现最简单的方法是运行开发人员命令提示符,而且 installutil 已经在路径中了,因此您可以直接执行它而无需指定位置。 - Frank Bryce
1
如果我的服务没有列出来怎么办?我是用管理员身份运行的cmd提示符安装的。 - picheto

23

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

更改如下内容:

static class Program
{
    static void Main()
    {
        ServiceBase[] ServicesToRun;
        ServicesToRun = new ServiceBase[] 
        { 
            new MyService() 
        };
        ServiceBase.Run(ServicesToRun);
    }
}
对此:
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
    }
}

这项技术来源于该文章,文章作者是Tejas Vaishnav。我在此处复制代码片段,因为SO更喜欢完整的答案,而不是可能会消失的链接。


所以这只会运行myServ.Process()并退出? - Paul McCarthy
基本上,让它保持繁忙是你的责任。 - Ofer Zelig
即使是服务也必须保持运行。 - Ofer Zelig
Application.Run;我不需要调用其他任何东西来“保持它运行”。 - Paul McCarthy
1
在项目属性中,您还需要将输出类型设置为控制台应用程序。 - Arthur
要将输出类型设置为控制台应用程序,请按照此Stack Overflow答案中描述的说明进行操作:https://dev59.com/H0UFtIcB2Jgan1znUd2u#60382135 - Vitalis

6
为了避免出现这个错误并允许服务在通常的服务控制器之外运行,您可以检查Environment.UserInteractive标记。如果设置了该标记,则可以将服务运行时输出到控制台,而不是让它运行到返回该错误的ServiceBase代码。
在Program.Main()的开始处添加以下内容,在使用ServiceBase运行服务的代码之前:
        if (Environment.UserInteractive)
        {
            var service = new WindowsService();
            service.TestInConsole(args);
            return;
        }

由于您的服务中的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);
    }

最后,请确保在项目属性中将输出设置为控制台应用程序。
现在,您可以像运行其他应用程序一样运行服务可执行文件,并且它将作为控制台启动。如果您从Visual Studio启动它,则调试器会自动附加。如果您将其注册并作为服务启动,则它将作为服务正确运行,而无需进行任何更改。
我发现唯一的区别是当作为控制台应用程序运行时,代码不会写入事件日志,因此您可能希望将日志记录到控制台上。
这种服务调试技术是在 learn.microsoft.com 上解释的其中之一。

微软的文档越来越好了,感谢添加链接。 - dare2k
要将输出类型设置为控制台应用程序,请按照此Stack Overflow答案中描述的说明进行操作:https://dev59.com/H0UFtIcB2Jgan1znUd2u#60382135 - Vitalis

5
有一个NuGet包可解决此问题:install-package WindowsService.Gui Image of the runner GUI 该包有什么作用? 它能够创建一个Play/Stop/Pause UI,当使用调试器运行时,但也允许Windows服务在Windows Services环境中安装和运行。只需要一行代码! Service Helper是什么呢?作为经常编写Windows服务的人,处理调试服务的麻烦可能会让人沮丧。通常涉及技巧、黑客和部分解决方法来测试所有的代码。对于Windows服务开发人员来说,没有“只需按F5”体验。
Service Helper通过触发UI显示来解决这个问题,如果调试器附加,则模拟(尽可能地)Windows Services环境。
该GitHub项目在此处:https://github.com/wolfen351/windows-service-gui 如何使用? 将Windows Service Helper添加到项目中最简单的方法是使用NuGet官方源上的ServiceProcess.Helpers NuGet包。
只需对应用程序的“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
    }
    }
}

声明:我是该项目的维护者

注意:UI为可选项


2
另一个原因可能是解决方案配置处于 Release 模式而不是 Debug 模式 在此输入图片描述

enter image description here


1
请检查您是处于“DEBUG”还是“RELEASE”模式。当我尝试在“RELEASE”模式下调试服务时,出现了这个错误。当我将其更改为“DEBUG”时,一切都正常工作。
这是在按照其他人的建议正确安装服务之后。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接