Skip Ribbon Commands
Skip to main content

Cornelius J. van Dyk's SharePoint Brain Dump

:

How-do-I--Create-a-Windows-Service-application-using-Visual-Studio-2010

Thoughts, musings, outbursts and revelations of Cornelius J. van Dyk - 7 x Microsoft SharePoint MVP

We don’t build many Windows Service applications any more these days, but every once in a while, the need for one comes around.  With Visual Studio 2010 now the mainstay of our tool set, let’s look at how you accomplish the mission using this tool.

  1. Launch Visual Studio 2010.
  2. From the Start Page, click "New Project".  If the Start Page isn't visible, you can view it via the View/Start Page menu.
  3. image
  4. If you have the .NET Framework 4.0 installed, Visual Studio will default to that as the target.  Since my specific application is targeting a SharePoint server, I'll set the framework target to .NET Framework 3.5 instead.
  5. From the Installed Templates list, expand "Visual C#" (or VB.NET if you're still using it).
  6. Select the "Windows" section in the left pane.
  7. Available templates are populated in the right pane.  Select "Windows Service" in the right pane.
  8. Provide a Name for your project.  In my case, the names are getting very long with namespaces included so I'm saving my project in a local C:\CODE folder instead of under My Documents.
  9. Once you've picked the folder location, click "OK" to create the project.
  10. image
  11. By default, VS will create a service named "Service1.cs" for us.
  12. In the Solution Explorer, right click the "Service1.cs" file.
  13. On the popup menu, click "Rename".
  14. image
  15. VS will prompt you for reference renames.  Click "Yes".
  16. image
  17. Enter the name of the new service and press Enter to complete the rename.  As you can see, I renamed my service to "RefreshBloggerRatings.cs".
  18. image
  19. Now we need to edit the service class.  In the Solution Explorer, double click the service class name.
  20. The canvas fills the main edit area.  Time to add some components.
  21. Expand the Toolbox.
  22. Expand the Components section.
  23. Since our service runs without a user interface, we need some way to send messages to the system for tracking and/or debugging purposes.  The Event Log is most useful for this.  Let's add the ability to write to the Event Log to our service.
  24. Locate the EventLog control and drag it to your canvas.
  25. image
  26. By default VS will name the new control "eventLog1".  Being the developer type that I am, I don't like default names so... you guessed it... I'm going to rename it.
  27. In our case, I renamed the control to "RBREventLog".
  28. image
  29. Next we need to write some code for our service.
  30. Right click on the canvas and click "View Code" or use the VS shortcut and just press F7.
  31. image
  32. You should now be looking at the C# source code for our service application.  There's not much to it, but this is what you should have right now.
  33. Code Snippet
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Diagnostics;
    using System.Linq;
    using System.ServiceProcess;
    using System.Text;

    namespace cjvandyk.WindowsServices.RefreshBloggerRatings
    {
        public partial class RefreshBloggerRatings : ServiceBase
        {
            public RefreshBloggerRatings()
            {
                InitializeComponent();
            }

            protected override void OnStart(string[] args)
            {
            }

            protected override void OnStop()
            {
            }
        }
    }
  34. In the class constructor, underneath the InitializeComponent() method, we are going to add the code to initialize our Event Log.  You can use the existing event log sources, but I like separating mine off onto it's own source.  Modify the constructor method to look like this:
  35. Code Snippet
    public RefreshBloggerRatings()
    {
        InitializeComponent();
        if (!System.Diagnostics.EventLog.SourceExists("cjvandyk"))
        {
            System.Diagnostics.EventLog.CreateEventSource("cjvandyk", "cjvandyk.Log");
        }
        RBREventLog.Source = "cjvandyk";
        RBREventLog.Log = "cjvandyk.Log";
    }
  36. Now that we have initialized our event log source, we can write to it.
  37. Modify the OnStart() method to write to the log whenever our service starts as follows:
  38. Code Snippet
    protected override void OnStart(string[] args)
    {
        RBREventLog.WriteEntry("RefreshBloggerRatings() starting...");
    }
  39. Also modify the OnStop() method to do the same kind of thing thus:
  40. Code Snippet
    protected override void OnStop()
    {
        RBREventLog.WriteEntry("RefreshBloggerRatings() stopping...");
    }
  41. Now that we have our service startup and shutdown processes in place, we need to define a way for the service to actually do something.  In this case, I want the service application to run daily and do some processing when it does.  For the trigger, we'll be using a Timer.
  42. Switch back to the canvas view of the app.
  43. In the Components section of the Toolbox, locate the "Timer" control and drag it onto the canvas.
  44. image
  45. As before, I'm going to rename it from the default "timer1" to "RBRTimer".
  46. image
  47. Now right click the Timer control and select "Properties".
  48. The property we are interested in is the "Interval".
  49. The Interval value is in milliseconds so that's 1/1000th of a second.  In order to have the timer trigger once daily we need to set it to 24 (hours) X 60 (minutes) X 60 (seconds) X 1000 (milli) or 86,400,000.
  50. Set the value and press Enter.
  51. image
  52. Next we want to start and stop the timer when our service starts/stops.
  53. Switch back to the Code View of our app and add to the OnStart() and OnStop() methods.
  54. We want to enable and then start the timer when the service starts and inversely stop and disable the timer when the service stops.  Modify the methods thus:
  55. Code Snippet
    protected override void OnStart(string[] args)
    {
        RBREventLog.WriteEntry("RefreshBloggerRatings() starting...");
        RBRTimer.Enabled = true;
        RBRTimer.Start();
    }

    protected override void OnStop()
    {
        RBREventLog.WriteEntry("RefreshBloggerRatings() stopping...");
        RBRTimer.Stop();
        RBRTimer.Enabled = false;
    }
  56. Now that our Timer triggers an event every day, we need to add the code to actually do something when the timer triggers.
  57. In the Properties windows of the Timer, click the "Events" button.  It looks like a little lightning bolt.
  58. This switches the Properties window over so we can see the Event Handlers that are defined.
  59. image
  60. As you can see, the Timer control only has a single event available to it.  The event is called "Tick".
  61. You can tell that no method has been defined yet because there's none listed.
  62. To the right of the Tick event, double click the white space.
  63. image
  64. VS will create the new method and bind it to the event.  It will also switch to code view and allow you to edit the method now.
  65. For now, I'm just adding a TODO item to the method, but this is where you would add your working code.
  66. Code Snippet
    private void RBRTimer_Tick(object sender, EventArgs e)
    {
        //TODO: Write the processing code here.
    }
  67. Switching back to the Properties view, you'll see the method bound to the event.
  68. image
  69. Our completed code base should now look like this:
  70. Code Snippet
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Diagnostics;
    using System.Linq;
    using System.ServiceProcess;
    using System.Text;

    namespace cjvandyk.WindowsServices.RefreshBloggerRatings
    {
        public partial class RefreshBloggerRatings : ServiceBase
        {
            public RefreshBloggerRatings()
            {
                InitializeComponent();
                if (!System.Diagnostics.EventLog.SourceExists("cjvandyk"))
                {
                    System.Diagnostics.EventLog.CreateEventSource("cjvandyk", "cjvandyk.Log");
                }
                RBREventLog.Source = "cjvandyk";
                RBREventLog.Log = "cjvandyk.Log";
            }

            protected override void OnStart(string[] args)
            {
                RBREventLog.WriteEntry("RefreshBloggerRatings() starting...");
                RBRTimer.Enabled = true;
                RBRTimer.Start();
            }

            protected override void OnStop()
            {
                RBREventLog.WriteEntry("RefreshBloggerRatings() stopping...");
                RBRTimer.Stop();
                RBRTimer.Enabled = false;
            }

            private void RBRTimer_Tick(object sender, EventArgs e)
            {
                //TODO: Write the processing code here.
                RBREventLog.WriteEntry("RefreshBloggerRatings() processing...");
            }
        }
    }
  71. ADD INSTALLERS
  72. Switch back to the canvas view of the app.
  73. Right click on white space on the canvas.
  74. On the popup menu, click "Add Installer".
  75. image
  76. VS adds the ProjectInstaller components to the project.
  77. From the design view of ProjectInstaller.cs, you'll notice two controls that were added.  They are "serviceProcessInstaller1" and "serviceInstaller1".
  78. image
  79. As before, I'm renaming these.
  80. Right click the "serviceProcessInstaller1" control and click "Properties" on the popup menu.
  81. Change the name in the Properties pane.  I decided to change my control to "RBRserviceProcessInstaller".
  82. image
  83. Right click the "serviceInstaller1" control and click "Properties" on the popup menu.
  84. Change the name in the Properties pane.  I decided to change my control to "RBRserviceInstaller".
  85. image
  86. Now you can modify the properties of the installer controls.  These properties are useful for informing the administrator about what the service is.
  87. Set the Description value to what you'd like it to be displayed in the Windows Services window.
  88. The ServiceName is the name that is actually used in the Windows Services window.
  89. You can also set the StartType.
  90. image
  91. Next we need to set the properties of the "RBRserviceProcessInstaller".  This is where we tell Windows under which account to run the service etc.
  92. We've selected "LocalSystem" which is a highly privileged account, basically a local admin, for our purposes.
  93. image
  94. Time to build our project.
  95. In the Solution Explorer right click the project name and click "Rebuild".
  96. image
  97. ADD SETUP
  98. Now that we know our service compiles, it's time to package and distribute it.
  99. In the Solution Explorer, right click on the solution name.
  100. On the popup, click "Add".
  101. On the flyout menu, click "New Project".
  102. image
  103. In the Installed Templates pane, expand the "Other Project Types" section.
  104. Expand the "Setup and Deployment" sub section.
  105. Select the "Visual Studio Installer" option in the left panel.
  106. In the right panel, select the "Setup Project" option.
  107. Give the setup project a name and click "OK" to add it.
  108. image
  109. Right click the newly added setup project in the Solution Explorer.
  110. On the popup menu, click "Add".
  111. On the flyout menu, click "Project Output".
  112. image
  113. A modal window opens.
  114. Select "Primary output".
  115. Click "OK" to add the output to the setup project.
  116. image
  117. Your setup project should now look something like this:
  118. image
  119. Next we need to add a custom action to the setup project.
  120. Right click the setup project in the Solution Explorer.
  121. On the popup menu, click "View".
  122. On the flyout menu, click "Custom Actions".
  123. image
  124. In the canvas pane, right click the "Custom Actions" section.
  125. On the popup menu, click "Add Custom Action".
  126. image
  127. In the modal window that opens, double click "Application Folder".
  128. image
  129. Select the "Primary output from ..." option.
  130. Click "OK".
  131. image
  132. Your Custom Actions should now look like this:
  133. image
  134. Time to build.  Right click the setup project in Solution Explorer.
  135. On the popup menu, click "Rebuild".
  136. image
  137. Ensure that the "Rebuild All succeeded" message appears telling us that all our project compiled successfully.
  138. image
  139. INSTALL
  140. You can now distribute the setup files to the computer you wish to install on.  installation is pretty easy.
  141. Right click the setup project in Solution Explorer.
  142. In the popup menu, click "Open Folder in Windows Explorer".
  143. image
  144. Navigate Windows Explorer to the Debug folder and you should see the setup files.
  145. Double click "setup.exe" to install.
  146. image
  147. On the Welcome screen, click "Next".
  148. image
  149. On the Installation Folder screen, ensure the "Everyone" radio button is selected.
  150. Click "Next".
  151. image
  152. On the Confirm Installation screen, click "Next".
  153. image
  154. On the Installation Complete screen, click "Close".
  155. image
  156. TEST
  157. Open Event Viewer through Start/Control Panel/Administrative Tools/Event Viewer.
  158. You'll notice the standard Windows event sources.
  159. image
  160. Now open Services through Start/Control Panel/Administrative Tools/Services.
  161. Locate our service in the list and left click it.
  162. You'll notice the service is NOT started.
  163. Click "Start".
  164. image
  165. Notice that the service is now started and running.
  166. image
  167. Switch back to the Event Viewer and refresh the view.
  168. You should now notice our new event source.
  169. image
  170. Opening our event source, there should be a single message noting the service start.
  171. image
  172. REMOVE
  173. Switch back to the Services window.
  174. Stop the service by clicking the "Stop" link after selecting the service.
  175. image
  176. Now open Add or Remove Programs via Start/Control Panel/Add or Remove Programs.
  177. Locate our service application.
  178. Select it and click "Remove".
  179. image

Once the uninstall is complete, removal is done.

And that, dear reader, is how we write a Windows Service application using Visual Studio 2010.

Enjoy
C