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

时间:2011-10-23 18:12:58

标签: visual-studio-2010 debugging windows-services

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

我正在关注来自MSDN的'如何': http://msdn.microsoft.com/en-us/library/7a50syb3.aspx

我遇到了两个问题:

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

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

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

    提前谢谢。

2 个答案:

答案 0 :(得分:2)

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

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

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

以下是您可能会指出我使用方向的一些代码。在服务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");
        }
    }
}

答案 1 :(得分:0)

//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();
    }