<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://msmvps.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Joacim's view on stuff : debugging</title><link>http://msmvps.com/blogs/joacim/archive/tags/debugging/default.aspx</link><description>Tags: debugging</description><dc:language>en</dc:language><generator>CommunityServer 2008.5 SP2 (Build: 40407.4157)</generator><item><title>Debugging a Windows Service</title><link>http://msmvps.com/blogs/joacim/archive/2009/09/13/debugging-a-windows-service.aspx</link><pubDate>Sun, 13 Sep 2009 19:17:31 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1723066</guid><dc:creator>Joacim Andersson</dc:creator><slash:comments>9</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/joacim/rsscomments.aspx?PostID=1723066</wfw:commentRss><comments>http://msmvps.com/blogs/joacim/archive/2009/09/13/debugging-a-windows-service.aspx#comments</comments><description>&lt;p&gt;&lt;strong&gt;Introduction&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;In my &lt;a href="http://msmvps.com/blogs/joacim/archive/2009/09/13/creating-a-windows-service-using-vb-net.aspx"&gt;last article&lt;/a&gt; I showed a simple example of how to create a Windows Service using VB. This time we’re going to have a look at how to debug the service from Visual Studio.&lt;/p&gt;  &lt;p&gt;Since a service must run from the context of the &lt;em&gt;Service Control Manager&lt;/em&gt; you can’t normally debug it in the same manner as you would any other project type. Normally you would need to build the project, install it using the &lt;em&gt;InstallUtil.exe&lt;/em&gt; command line tool, and attach a debugger to the process while it’s running. Another approach is to create a separate project (console application) and call your main code from there.&lt;/p&gt;  &lt;p&gt;Neither of these are an ideal way of doing the debugging so I’m going to show an alternative method, which you also can use to run your service from the command line, just like any other application.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Converting the service into a command line tool&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;When you create a Windows Service project in Visual Studio 2008, you get a &lt;em&gt;ServiceBase&lt;/em&gt; designer to which you add controls and your code to. Normally you would, at the very least, override the &lt;em&gt;OnLoad()&lt;/em&gt; and the &lt;em&gt;OnStop() &lt;/em&gt;methods. But the designer also creates a shared (static) &lt;em&gt;Main()&lt;/em&gt; method for you, which is the real starting point of the service. To be able to see that you need to open the designer generated code file. In VB this file is normally hidden, so you need to press the &lt;em&gt;Show all files &lt;/em&gt;button in the Solution Explorer.&lt;/p&gt;  &lt;p&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" title="image" border="0" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/joacim.metablogapi/4812.image_5F00_0E6D228A.png" width="339" height="313" /&gt; &lt;/p&gt;  &lt;p&gt;The &lt;em&gt;Main()&lt;/em&gt; method looks like this (with some comments removed).&lt;/p&gt;  &lt;pre class="code"&gt;&amp;lt;MTAThread()&amp;gt; _
&amp;lt;System.Diagnostics.DebuggerNonUserCode()&amp;gt; _
&lt;span style="color:blue;"&gt;Public Shared Sub &lt;/span&gt;Main()
&lt;span style="color:blue;"&gt;  Dim &lt;/span&gt;ServicesToRun() &lt;span style="color:blue;"&gt;As &lt;/span&gt;System.ServiceProcess.ServiceBase
  ServicesToRun = _&lt;br /&gt;      &lt;span style="color:blue;"&gt;New &lt;/span&gt;System.ServiceProcess.ServiceBase() {&lt;span style="color:blue;"&gt;New &lt;/span&gt;FileWatcherService}
  System.ServiceProcess.ServiceBase.Run(ServicesToRun)
&lt;span style="color:blue;"&gt;End Sub&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;A &lt;em&gt;Main()&lt;/em&gt; method can receive arguments from the command line, you just have to add a string array as a parameter of the method. The whole idea is that if a specific command line switch is passed to the executable it should not act as a Windows Service but instead run as any other EXE file. So I rewrote the above method to this:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color:green;"&gt;&amp;#39; The main entry point for the process
&lt;/span&gt;&amp;lt;MTAThread()&amp;gt; _
&amp;lt;System.Diagnostics.DebuggerNonUserCode()&amp;gt; _
&lt;span style="color:blue;"&gt;Public Shared Sub &lt;/span&gt;Main(&lt;span style="color:blue;"&gt;ByVal &lt;/span&gt;args() &lt;span style="color:blue;"&gt;As String&lt;/span&gt;)
  &lt;span style="color:blue;"&gt;Dim &lt;/span&gt;runAsService &lt;span style="color:blue;"&gt;As Boolean &lt;/span&gt;= &lt;span style="color:blue;"&gt;True
  For Each &lt;/span&gt;arg &lt;span style="color:blue;"&gt;As String In &lt;/span&gt;args
    &lt;span style="color:blue;"&gt;Select Case &lt;/span&gt;arg.ToLower
      &lt;span style="color:blue;"&gt;Case &lt;/span&gt;&lt;span style="color:#a31515;"&gt;&amp;quot;/c&amp;quot;&lt;/span&gt;, &lt;span style="color:#a31515;"&gt;&amp;quot;-c&amp;quot;
        &lt;/span&gt;runAsService = &lt;span style="color:blue;"&gt;False
    End Select
  Next
  If &lt;/span&gt;runAsService &lt;span style="color:blue;"&gt;Then
    Dim &lt;/span&gt;ServicesToRun() &lt;span style="color:blue;"&gt;As &lt;/span&gt;System.ServiceProcess.ServiceBase
&lt;span style="color:green;"&gt;    &lt;/span&gt;ServicesToRun = _&lt;br /&gt;        &lt;span style="color:blue;"&gt;New &lt;/span&gt;System.ServiceProcess.ServiceBase() {&lt;span style="color:blue;"&gt;New &lt;/span&gt;FileWatcherService}
    System.ServiceProcess.ServiceBase.Run(ServicesToRun)
  &lt;span style="color:blue;"&gt;Else
    Dim &lt;/span&gt;service &lt;span style="color:blue;"&gt;As New &lt;/span&gt;FileWatcherService
    service.CommandLineExecution = &lt;span style="color:blue;"&gt;True
    &lt;/span&gt;service.OnStart(&lt;span style="color:blue;"&gt;New String&lt;/span&gt;() {&lt;span style="color:#a31515;"&gt;&amp;quot;&amp;quot;&lt;/span&gt;})
  &lt;span style="color:blue;"&gt;End If
End Sub&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;If the /c or –c switch is found among the command line parameters then it will start as a regular program. As you can see, if the switch is found, instead of creating an instance of the &lt;em&gt;ServiceBase&lt;/em&gt; class I create an instance of my service class directly and call its &lt;em&gt;OnStart()&lt;/em&gt; method. I also added a &lt;em&gt;CommandLineExecution&lt;/em&gt; property to the class so I can keep track of how it is supposed to be executed. If you need to set a breakpoint or step through the &lt;em&gt;Main()&lt;/em&gt; method you need to remove the &lt;em&gt;DebuggerNonUserCode&lt;/em&gt; attribute, otherwise Visual Studio will just run through this method without stopping (this is what you normally would want to do with designer created code).&lt;/p&gt;

&lt;p&gt;Now I also needed to make some changes to the &lt;em&gt;OnStart()&lt;/em&gt; method.&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color:blue;"&gt;Protected Overrides Sub &lt;/span&gt;OnStart(&lt;span style="color:blue;"&gt;ByVal &lt;/span&gt;args() &lt;span style="color:blue;"&gt;As String&lt;/span&gt;)
  &lt;span style="color:blue;"&gt;Dim &lt;/span&gt;handle &lt;span style="color:blue;"&gt;As &lt;/span&gt;IntPtr = &lt;span style="color:blue;"&gt;Me&lt;/span&gt;.ServiceHandle
  &lt;span style="color:blue;"&gt;If Not Me&lt;/span&gt;.CommandLineExecution &lt;span style="color:blue;"&gt;Then
    &lt;/span&gt;_serviceStatus.currentState = Fix(State.SERVICE_START_PENDING)
    SetServiceStatus(handle, _serviceStatus)
  &lt;span style="color:blue;"&gt;End If
  Dim &lt;/span&gt;logMessage &lt;span style="color:blue;"&gt;As String &lt;/span&gt;= &lt;span style="color:blue;"&gt;String&lt;/span&gt;.Empty
  &lt;span style="color:blue;"&gt;If Not &lt;/span&gt;ReadSettings(logMessage) &lt;span style="color:blue;"&gt;Then
    &lt;/span&gt;WriteLogMessage(logMessage, EventLogEntryType.Error)
    _serviceStatus.currentState = Fix(State.SERVICE_STOPPED)
    &lt;span style="color:blue;"&gt;If Not Me&lt;/span&gt;.CommandLineExecution &lt;span style="color:blue;"&gt;Then
      &lt;/span&gt;SetServiceStatus(handle, _serviceStatus)
    &lt;span style="color:blue;"&gt;End If
  Else
    If Not String&lt;/span&gt;.IsNullOrEmpty(logMessage) &lt;span style="color:blue;"&gt;Then
      &lt;/span&gt;WriteLogMessage(logMessage, EventLogEntryType.Information)
    &lt;span style="color:blue;"&gt;End If
    &lt;/span&gt;&lt;span style="color:green;"&gt;&amp;#39;Start the file watching...
    &lt;/span&gt;&lt;span style="color:blue;"&gt;With &lt;/span&gt;FileSystemWatcher1
      .BeginInit()
      .Filter = _fileMask
      .IncludeSubdirectories = _includeSubFolders
      .Path = _folderName
      .EnableRaisingEvents = &lt;span style="color:blue;"&gt;True
      &lt;/span&gt;.EndInit()
      &lt;span style="color:blue;"&gt;If Not Me&lt;/span&gt;.CommandLineExecution &lt;span style="color:blue;"&gt;Then
        &lt;/span&gt;_serviceStatus.currentState = Fix(State.SERVICE_RUNNING)
        SetServiceStatus(handle, _serviceStatus)
      &lt;span style="color:blue;"&gt;Else
        &lt;/span&gt;Threading.Thread.Sleep(Threading.Timeout.Infinite)
      &lt;span style="color:blue;"&gt;End If
    End With
  End If
End Sub&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;If the &lt;em&gt;CommandLineExecution &lt;/em&gt;property is set to True I skip all the calls to the &lt;em&gt;SetServiceStatus() &lt;/em&gt;Win32 API function. I also end the method by letting the current thread sleep for infinity, if I didn’t do that the program would just exit when it reached the end of the method.&lt;/p&gt;

&lt;p&gt;I also made a slight change to the &lt;em&gt;WriteLogMessage()&lt;/em&gt; method, if the application isn’t running as a service there is no reason to do the logging to the Event Viewer. Instead it simply shows a message box.&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color:blue;"&gt;Private Sub &lt;/span&gt;WriteLogMessage(&lt;span style="color:blue;"&gt;ByVal &lt;/span&gt;message &lt;span style="color:blue;"&gt;As String&lt;/span&gt;, _&lt;br /&gt;                            &lt;span style="color:blue;"&gt;ByVal &lt;/span&gt;type &lt;span style="color:blue;"&gt;As &lt;/span&gt;EventLogEntryType)
  &lt;span style="color:blue;"&gt;If Not Me&lt;/span&gt;.CommandLineExecution &lt;span style="color:blue;"&gt;Then
    If Not &lt;/span&gt;EventLog.SourceExists(&lt;span style="color:#a31515;"&gt;&amp;quot;File Observer&amp;quot;&lt;/span&gt;) &lt;span style="color:blue;"&gt;Then
      &lt;/span&gt;EventLog.CreateEventSource(&lt;span style="color:#a31515;"&gt;&amp;quot;File Observer&amp;quot;&lt;/span&gt;, &lt;span style="color:#a31515;"&gt;&amp;quot;File Observer Log&amp;quot;&lt;/span&gt;)
    &lt;span style="color:blue;"&gt;End If
    Dim &lt;/span&gt;log &lt;span style="color:blue;"&gt;As New &lt;/span&gt;EventLog()
    log.Source = &lt;span style="color:#a31515;"&gt;&amp;quot;File Observer&amp;quot;
    &lt;/span&gt;log.WriteEntry(message, type)
  &lt;span style="color:blue;"&gt;Else
    &lt;/span&gt;MsgBox(&lt;span style="color:blue;"&gt;String&lt;/span&gt;.Format(&lt;span style="color:#a31515;"&gt;&amp;quot;{0}: {1}&amp;quot;&lt;/span&gt;, type.ToString, message))
  &lt;span style="color:blue;"&gt;End If
End Sub&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;&lt;strong&gt;Debug the service&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To be able to run this service as a regular application from Visual Studio you must pass the command line switch /c. You can specify command line arguments on the Debug tab of the project properties dialog.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/joacim.metablogapi/5008.image_5F00_4C1A0A46.png"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" title="image" border="0" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/joacim.metablogapi/6253.image_5F00_thumb_5F00_0A3324F8.png" width="599" height="280" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In this post I showed you how to turn a Windows Service into a regular executable using a command line switch to allow you to debug it from Visual Studio. Of course, instead of a command line switch you could instead just check if the application is in debug or release mode. But I wanted to be able to run the service as a regular application even after it was compiled and deployed in release mode.&lt;/p&gt;

&lt;p&gt;Have fun!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1723066" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/joacim/archive/tags/vb/default.aspx">vb</category><category domain="http://msmvps.com/blogs/joacim/archive/tags/visual+basic/default.aspx">visual basic</category><category domain="http://msmvps.com/blogs/joacim/archive/tags/windows+service/default.aspx">windows service</category><category domain="http://msmvps.com/blogs/joacim/archive/tags/debugging/default.aspx">debugging</category></item></channel></rss>