如何调试Windows服务应用程序?

发布于 2024-12-11 14:39:51 字数 526 浏览 0 评论 0原文

我正在 Visual Studio 2010 Ultimate SP1 中创建 Windows 服务应用程序。

我正在关注 MSDN 上的“如何做”: http://msdn.microsoft.com/en-us/library/7a50syb3.aspx

我遇到了两个问题:

  1. 我无法通过服务器资源管理器启动服务 - 我的服务列在那里,但在上下文菜单中我只有两个可用选项:刷新和属性。尽管 MSDN 文档说应该有该选项,但没有“开始”选项。 幸运的是,我可以通过使用服务控制管理器来避免这种麻烦。

  2. 下一步是:“在 Visual Studio 中,从“调试”菜单中选择“进程””。 调试菜单中不存在该选项。我只有“附加到进程”,但其中未列出服务。

有人知道出了什么问题以及我应该如何调试我的应用程序吗?

先感谢您。

I'm creating a Windows Service Application in Visual Studio 2010 Ultimate SP1.

I was following 'How to' from MSDN:
http://msdn.microsoft.com/en-us/library/7a50syb3.aspx

I have encountered two problems:

  1. I cannot start a service via Server Explorer - my service is listed there, but in the context menu I have only two options available: Refresh and Properties. There is no "Start" though MSDN documentation says that there should be that option.
    Fortunately, I can avoid this hassle by using Services Control Manager.

  2. The next step is: "In Visual Studio, choose Processes from the Debug menu".
    That option doesn't exist in Debug menu. I have only "Attach to Process", but services aren't listed there.

Does somebody know what is wrong and how I am supposed to debug my application?

Thank you in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

兔姬 2024-12-18 14:39:51

作为一个想法:我已经构建了很多 Windows 服务,并且出于多种原因之一,我没有在服务本身中创建核心代码。如果您愿意的话,该服务本质上是“操作层”。在 dll 中创建核心代码允许调试和测试该特定代码。您可以创建一个控制台或桌面应用程序来运行可在开发和测试阶段使用的核心代码。

就我个人而言,我创建了一个服务运行程序应用程序,它捕获与启动和停止功能相关的日志记录。我的 OnStart 和 OnStop 代码块实际上与服务的代码块相同。

接下来,当您测试服务时,您应该能够启动服务(例如 myService.exe)并附加到进程。然而,另一个注意事项是,您应该使用调试构建暂停/等待服务线程(例如 30 秒),以便您有时间附加到进程,并且不会错过初始化代码。请记住,您必须安装服务,然后通过 Windows 服务管理器启动。

这是一些代码,可能会为您指明我使用的方向。在 service program.cs 文件中,我使用以下内容;然后在 Service OnStart() 方法中调用 dll 并运行。另外,您可以停止服务,用更新版本替换 dll,然后重新启动。使用 C#,您也可以替换服务 exe,但这些只是 C# 的特性:在 C++ 中则不能。

static class Program
{
    public const string SERVICE_NAME = "myService";
    public const string SERVICE_DISPLAY_NAME = "My Service";

    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    static void Main(string[] args)
    {
        if (args != null && args.Length > 0)
        {
            foreach (string arg in args)
            {
                switch (arg.ToLower())
                {
                    case "-install":
                        ManageService(true);
                        return;

                    case "-remove":
                        ManageService(false);
                        return;
                }
            }


        }

        ServiceBase[] ServicesToRun;
        ServicesToRun = new ServiceBase[] 
                { 
                    new Service() 
                };
        ServiceBase.Run(ServicesToRun);
    }

    private static void ManageService(bool bInstall)
    {
        string parms;

        if (bInstall == true)
        {
            parms = string.Format("Create {0} type= own start= demand binPath= \"{1}\" DisplayName= \"{2}\"", SERVICE_NAME,
                                  System.Reflection.Assembly.GetExecutingAssembly().Location, SERVICE_DISPLAY_NAME);
        }
        else // remove
        {
            parms = string.Format("Delete {0}", SERVICE_NAME);
        }

        try
        {
            string output = string.Empty;
            System.Diagnostics.Process proc = new System.Diagnostics.Process();
            System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo("sc.exe", parms);

            startInfo.UseShellExecute = false;
            startInfo.RedirectStandardOutput = true;
            startInfo.RedirectStandardError = true;
            startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
            startInfo.CreateNoWindow = true;

            proc.StartInfo = startInfo;

            proc.Start();

            output = proc.StandardOutput.ReadToEnd();

            proc.WaitForExit(10000);

            if (proc.HasExited == true)
            {
                // NOTE: The project type has been changed from Windows Service to Console Application
                // so that Console.WriteLine will output to the console
                Console.WriteLine(output);
            }
            else
            {
                proc.Close();
                Console.WriteLine("Timed out waiting to install service");
            }
        }
        catch (System.ComponentModel.Win32Exception)
        {
            Console.WriteLine("Unable to locate sc.exe");
        }
    }
}

As a thought: I have built a lot of Windows services and for one of many reasons, I do not create the core code in the service itself. The service is essentially the "operational layer", if you will. Creating the core code in a dll permits debugging and testing of that particular code. You can create a console or desktop app that will run the core code which can be used during development and testing phases.

Personally, I created a service runner application which captures logging in conjunction with the start and stop functionality. My OnStart and OnStop code blocks are literally identical to that of the service.

Next, when you test the service, you should be able to start the service (e.g. myService.exe) and attach to process. However, another note is that you should pause/wait the service thread (for say 30 seconds) with a debug build so you have time to attach to the process and you don't miss your initialization code. Just remember, you have to install your service then start via the Windows service manager.

Here is some code you that might point you in the direction that I use. In the service program.cs file I use the below; then in the Service OnStart() method you call your dll and run. Also, you can stop your service, replace the dll with an updated version then restart. With C# you can replace the service exe as well, but these are only C# characteristics: in C++ you cannot.

static class Program
{
    public const string SERVICE_NAME = "myService";
    public const string SERVICE_DISPLAY_NAME = "My Service";

    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    static void Main(string[] args)
    {
        if (args != null && args.Length > 0)
        {
            foreach (string arg in args)
            {
                switch (arg.ToLower())
                {
                    case "-install":
                        ManageService(true);
                        return;

                    case "-remove":
                        ManageService(false);
                        return;
                }
            }


        }

        ServiceBase[] ServicesToRun;
        ServicesToRun = new ServiceBase[] 
                { 
                    new Service() 
                };
        ServiceBase.Run(ServicesToRun);
    }

    private static void ManageService(bool bInstall)
    {
        string parms;

        if (bInstall == true)
        {
            parms = string.Format("Create {0} type= own start= demand binPath= \"{1}\" DisplayName= \"{2}\"", SERVICE_NAME,
                                  System.Reflection.Assembly.GetExecutingAssembly().Location, SERVICE_DISPLAY_NAME);
        }
        else // remove
        {
            parms = string.Format("Delete {0}", SERVICE_NAME);
        }

        try
        {
            string output = string.Empty;
            System.Diagnostics.Process proc = new System.Diagnostics.Process();
            System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo("sc.exe", parms);

            startInfo.UseShellExecute = false;
            startInfo.RedirectStandardOutput = true;
            startInfo.RedirectStandardError = true;
            startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
            startInfo.CreateNoWindow = true;

            proc.StartInfo = startInfo;

            proc.Start();

            output = proc.StandardOutput.ReadToEnd();

            proc.WaitForExit(10000);

            if (proc.HasExited == true)
            {
                // NOTE: The project type has been changed from Windows Service to Console Application
                // so that Console.WriteLine will output to the console
                Console.WriteLine(output);
            }
            else
            {
                proc.Close();
                Console.WriteLine("Timed out waiting to install service");
            }
        }
        catch (System.ComponentModel.Win32Exception)
        {
            Console.WriteLine("Unable to locate sc.exe");
        }
    }
}
没有你我更好 2024-12-18 14:39:51
//From the main function a method from service class can be called like below code


//DebugApp method can be called from main and so the service can be debug:
//Service class    
public partial class CServices : ServiceBase
{
    public CServices()
    {
        InitializeComponent();
    }

    **public void DebugApp()
    {
        OnStart(new string[]{});
    }**
    protected override void OnStart(string[] args)
    {
        System.Console.WriteLine("Testing");
        System.Console.Read();
    }

    protected override void OnStop()
    {
    }
}


//Calling from main: 

   static void Main()
    {
        Services1.CServices uc = new CServices();
        uc.DebugApp();
    }
//From the main function a method from service class can be called like below code


//DebugApp method can be called from main and so the service can be debug:
//Service class    
public partial class CServices : ServiceBase
{
    public CServices()
    {
        InitializeComponent();
    }

    **public void DebugApp()
    {
        OnStart(new string[]{});
    }**
    protected override void OnStart(string[] args)
    {
        System.Console.WriteLine("Testing");
        System.Console.Read();
    }

    protected override void OnStop()
    {
    }
}


//Calling from main: 

   static void Main()
    {
        Services1.CServices uc = new CServices();
        uc.DebugApp();
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文