开发者

Debug Windows Service

开发者 https://www.devze.com 2022-12-26 10:29 出处:网络
Scenario I\'ve got a windows service written in C#. I\'ve read all the google threads on how to debug it, but I still can\'t get it to work.

Scenario

I've got a windows service written in C#. I've read all the google threads on how to debug it, but I still can't get it to work. I've run "PathTo.NetFramework\InstallUtil.exe C:\MyService.exe". It said the install was successful, however when I run "Services.msc", The service isn't displayed at all, anywhere. If I go into Task Manager, there is a process called "MyService.vshost.exe". Pretty sure that's not it, because it's a service, not a process.

Can Someone Explain To Me?

If I am supposed to see the service when I run Services.msc? (Bearing in mind this is all being done on a local machine, with no servers AT ALL.

Other

I'm running VS2008.

EDIT:

This is all being done on my local machine, I have no servers or access to any. Also, I don't even know what the service does, I want to debug it so I can walkthrough the code and see how it all works (the code inside the service, not the service itself - for any of you smarty pants that might suggest I look at a template).

EDIT 2:

NONE OF THESE ARE WORKING! Everytime I try something I get some message about having to use NET START or install the service.

EDIT 3:

I'm running VS2008.

I typed this: C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\InstallUtil.exe C:\dev\Restarter\bin\Release\Restarter.exe

I got this: Microsoft (R) .NET Framework Installation utility Version 2.0.50727.3053 Copyright (c) Microsoft Corporation. All rights reserved.

Running a transacted installation.

Beginning the Install phase of the installation. See the contents of the log file for the C:\dev\Restarter\bin\ Release\Restarter.exe assembly's progress. The file is located at C:开发者_如何学C\dev\Restarter\bin\Release\EDT.Restar ter.InstallLog. Installing assembly 'C:\dev\Restarter\bin\Release\Restarter.exe'. Affected parameters are: logtoconsole = assemblypath = C:\dev\Restarter\bin\Release\Restarter.exe logfile = C:\dev\Restarter\bin\Release\Restarter.InstallLog

The Install phase completed successfully, and the Commit phase is beginning. See the contents of the log file for the C:\dev\Restarter\bin\ Release\Restarter.exe assembly's progress. The file is located at C:\dev\Restarter\bin\Release\Restar ter.InstallLog. Committing assembly 'C:\dev\Restarter\bin\Release\Restarter.exe'. Affected parameters are: logtoconsole = assemblypath = C:\dev\Restarter\bin\Release\Restarter.exe logfile = C:\dev\Restarter\bin\Release\Restarter.InstallLog

The Commit phase completed successfully.

The transacted install has completed.

C:\Program Files\Microsoft Visual Studio 9.0\VC>

I then went to RUN -> Services.msc I can see nothing in there.

There is a process in Task Manager called "Restarter.vshost.exe".

That's it.

I only wanted to install and debug it. I know it works (as it it runs and doesn't crash). But the code was written by a friend and I want to understand the underlying code by walking through it in debug mode.


I recommend following pattern for debug:

 var ServiceToRun = new SomeService(); 
 if (Environment.UserInteractive)
 {
    // This used to run the service as a console (development phase only)

    ServiceToRun.Start();

    Console.WriteLine("Press Enter to terminate ...");
    Console.ReadLine();

    ServiceToRun.DoStop();
 }
 else
 {
    ServiceBase.Run(ServiceToRun);
 }

Edit: make sure that your target is Console Application, not Windows Application, otherwise it will not work.


you can debug it by attaching the debugger to the process. You can do this by either adding a line to the startup of your program:

Debugger.Launch ();

after adding the using statement:

using System.Diagnostics; 

you will either need to put that in a conditional block or remove it when you are done debugging

or by running the service and then attaching to the process manually from the IDE: Debug->Attach to process..


We can make the windows service project debuggable by just adding a parameter and making it behave like a console app.

1) Go to your windows service project properties -> Debug -> Start Options 2) Give an argument -Console 3) Go to Application tab -> output type, change it to Console Application 4) Type the below code in Program.cs

static class Program
    {
        private static EventWaitHandle _waitHandle;
        private static Service1 _service;
                static void Main(string[] args)
        {
            bool runConsole = false;**

            foreach (string arg in args)
            {
                if (arg.ToLowerInvariant().Equals("-console"))
                {
                    runConsole = true;
                }
            }   

            _service = new Service1();
            if (runConsole)
            {
                _waitHandle = new EventWaitHandle(false, EventResetMode.ManualReset);
                Console.WriteLine("Starting Workflow Service in Console Mode");
                Console.WriteLine("Press Ctrl+C to exit Console Mode");
               Console.CancelKeyPress += new ConsoleCancelEventHandler(OnCancelKeyPress);
                _service.InternalStart();
                WaitHandle.WaitAll(new WaitHandle[] { _waitHandle });
            }

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

        static void OnCancelKeyPress(object sender, ConsoleCancelEventArgs e)
        {
            _service.InternalStop();
            _waitHandle.Set();
        }


    }


This has helped me a lot when developing/debugging windows services:

http://windowsservicehelper.codeplex.com/

Just press F5 to debug. Very easy.

Andrey's approach is also very good.


In order to be able to debug my service without deploying it, I always write it in the following way:

In your program.cs file:

#if DEBUG
    MyService myService = new MyService();
    myService.OnDebug();
    System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);
#else
    ServiceBase[] ServicesToRun;
    ServicesToRun = new ServiceBase[]
    {
        new MyService()
    };
    ServiceBase.Run(ServicesToRun);
#endif

and in your MyService.cs file:

    public void OnDebug()
    {
        OnStart(null);
    }

* NOTE *: You must build under 'Release' mode when you are finally done with debugging and you are ready to deploy the service otherwise the service will not be considered as a service.

Hope this helps.


Assumptions:

1) You have the source code available in a Solution in the VS2008 IDE

How I Debug C# Services:

  1. Install the Service using InstallUtil. (You seem like you've already done that)
  2. (If Needed) Change the Service path to the MyService.exe that is produced in your Solution's bin folder
  3. Put something like the following at the beginning of your Service's OnStart() method:

    while(true)
    {
       System.Threading.Thread.Sleep(500);
    }
    
  4. Put a breakpoint on System.Threading.Thread.Sleep(500)

  5. Build the Solution

  6. Start your Service using the Windows Service Utility

  7. While your Service is starting, in VS2008 goto Debug -> Attach To Processes...

  8. Make sure Show Processes From All Users and Show Processes In All Sessions are checked

  9. Find your MyService.exe in the list, and click Attach

  10. You should now be at the breakpoint you inserted in the infinite loop

  11. Drag the Control (Yellow Arrow) just outside the infinite loop

  12. Debug away!

Disclaimer:

Remember to remove the infinite loop when you want to release a build, or when you simply want to run the service normally.


It can be that service name is not what you expect and that's why you can't find it. Service name is defined in ServiceInstaller properties in .NET project and does not have to correspond with executable name in any way. But if you're sure the service is not listed after installation, here is what you can do.

First, service installation. There are 2 methods, InstallUtil.exe and SC.exe. First one is tailored specifically for .NET services as it will run all ProjectInstaller and ServiceInstaller code. Second one will not do that but it will give you more options and is usually more effective i.e. likely to succeed where InstallUtil fails. This can be when there is an exception in any installer code.

You've already tried installing with InstallUtil so here is SC version:

sc create MyService binPath= "C:\Service.exe"

Note that MyService is the name you give to the service at this point and it can be anything you like (within reason :-). This name will be shown in services console list.

Once you have your service installed you would need to debug it right when OnStart is called. This can be achieved by running and attaching to a debugger (Visual Studio) from within the service:

protected override void OnStart(string[] args)
{
    #if DEBUG
    Debugger.Launch();
    #endif
    ...
}

Do not forget to build and replace service executable after this code change. Service must be stopped but no need to uninstall and reinstall it.

To delete service using SC:

sc delete MyService


If your business layer is seperate from the windows service you can test all of your business functions outside of running the windows service.

To test the windows service I like to create a test project that is a console app and I start a new thread that runs my service.

System.Threading.Thread sftpThread = new System.Threading.Thread((ThreadStart)service1);
service1.Start();


I recently added this to a project and it works great for me. You can debug it just like any other EXE. After it is added go to your project properties and add a command line parameter (/EXE) in the Debug tab for the Debug build configuration.

<MTAThread()> _
Shared Sub Main()

    '' 
    '' let's add a command line parameter so we can run this as a regular exe or as a service
    ''
    If Command().ToUpper() = "/EXE" Then
        Dim app As MyService = New MyService()

        app.OnStart(Nothing)
        Application.Run()
    Else
        Dim ServicesToRun() As System.ServiceProcess.ServiceBase

        ' More than one NT Service may run within the same process. To add
        ' another service to this process, change the following line to
        ' create a second service object. For example,
        '
        '   ServicesToRun = New System.ServiceProcess.ServiceBase () {New Service1, New MySecondUserService}
        '
        ServicesToRun = New System.ServiceProcess.ServiceBase() {New MyService}

        System.ServiceProcess.ServiceBase.Run(ServicesToRun)
    End If
End Sub


I recommend to add /test on project properties debug tab as a start option. Then you can run your service without having to install it.


If you create your service with TopShelf you should be able to easily debug it from Visual Studio

0

精彩评论

暂无评论...
验证码 换一张
取 消