Click here to Skip to main content
6,290,315 members and growing! (15,573 online)
Email Password   helpLost your password?
Development Lifecycle » Installation » General     Beginner License: The Code Project Open License (CPOL)

Install Windows Service using Custom Action

By lata07mahi

This article explains how to a custom action EXE to install a service using WinNT utilities, instsrv.exe and srvany.exe
C# (C# 2.0), Windows (WinXP)
Posted:15 May 2008
Views:17,954
Bookmarked:14 times
Unedited contribution
Announcements
Loading...
 
Search    
Advanced Search
printPrint   Broken Article?Report       add Share
  Discuss Discuss   Recommend Article Email
5 votes for this article.
Popularity: 1.26 Rating: 1.80 out of 5

1

2

3

4
1 vote, 100.0%
5

Introduction

Services can be installed using MSI (Microsoft Installer) by adding custom actions. This tutorial gives step-by-step details how custom action can be added which would install user service silently. It then modifies the registry entries for the service installed and logon user account based on user input.

Windows NT resource kit provides two utilities, srvany.exe and instsrv.exe which can be
used to allow any windows application to run as Windows Service, install and remove
any windows service.

Creating Custom Action Exe

Using following steps create a custom action executable:

  • Create a project of type Windows Application say ServiceInstaller.
  • Add component class to it. Derive the class from System.Configuration.Install.Installer which provided foundation for custom installation.
  • Set its [RunInstaller] attribute to true.
  • Add references to the project using solution explorer and in code.
  • Override Install, Uninstall, Rollback methods of base class.
  • Add a main function.
  • Compile the project.
using System.Text;
using System.Configuration.Install;
using System.Windows.Forms;
using System.IO;
using System.Reflection;
using System.ServiceProcess;
using System.Resources;
using System.Threading;
using System.Management;
using System.DirectoryServices;
using System.Collections;
using Microsoft.Win32;
using System.Runtime.InteropServices;
 
namespace ServiceInstaller
{
    [RunInstaller(true)]
    public partial class ServiceInstall : System.Configuration.Install.Installer
    { 
        public override void Install(IDictionary savedState)
        {
            base.Install(savedState);
            //Add custom code here
        }
        
        public override void Uninstall(IDictionary savedState)
        {
            base.Uninstall(savedState);
            //Add custom code here
        }
 
        public override void Rollback(IDictionary savedState)
        {
            base.Rollback(savedState);
            //Add custom code here
        }
 
        public override void Commit(IDictionary savedState)
        {
            base.Commit(savedState);
           //Add custom code here
        }
 
        static void Main()
        {
 
        }
    }
}         

Adding Custom Action to MSI project

Add a Setup and deployment project named SetupService in the same solution.

  • In the File System Editor, select the application folder. On the Action menu, point to Add, and choose Project Output.
  • In the Add Project Output Group dialog box, select the primary output for the ServiceInstaller project. Click OK to close the dialog box.
  • In the Custom Actions Editor, select the Install node. On the Action menu, choose Add Custom Action. In the Select Item in Project dialog box, double-click the Application Folder to the primary output from ServiceInstaller project. Do the same for Uninstall and Rollback nodes. This signifies that Install, Rollback and Uninstall methods of base class have been overridden in custom action.
  • In the Properties window, set the RemovePreviousVersion property to true.
  • Build the project and click Install on the Project menu.
InstallService.png

LaunchService Method

This method explains how service is installed using Windows NT utilities instsrv.exe and srvany.exe.

private bool LaunchService(string serviceEXE)
{
    bool blnServiceInstalled = true;
 
    //Stop Service if running
    System.ServiceProcess.ServiceController[] services;
    services = System.ServiceProcess.ServiceController.GetServices();
    if (services != null)
    {
        for(int intServiceCount=0; intServiceCount<services.Length;intServiceCount++)
        {
            if(services[intServiceCount].ServiceName == serviceEXE)
            {
                if(services[intServiceCount].Status == ServiceControllerStatus.Running)
                {
                    using(StreamWriter sw = File.CreateText(strPath + batchFileName))
                    {
                        sw.WriteLine("net stop {0}", serviceEXE);
                    }
                    ExecuteBatchFile();
                    File.Delete(strPath + batchFileName);
                }
                break;
            }
        }
    }
 
   //Register as Windows Service using instsrv.exe and srvany.exe
   using (StreamWriter sw = File.CreateText(strPath + batchFileName))
   {
        sw.WriteLine("cd {0}", strPath);
        sw.WriteLine("instsrv " + serviceEXE + " " + strPath + "\\" + "srvany.exe");
        sw.Flush();
        sw.Close();
   }
   ExecuteBatchFile();
   File.Delete(strPath + batchFileName);
 
 
   //Modify Registry entries for service added
   RegistryKey SystemServicesKey =  
       Registry.LocalMachine.OpenSubKey("System\\CurrentControlSet\\Services");
   if (SystemServicesKey != null)
   {
        //Open service key with write access
        RegistryKey userServiceKey = SystemServicesKey.OpenSubKey(serviceEXE, true);
        if (userServiceKey != null)
        {
            userServiceKey.SetValue("Description", "Test Service Application");
            if (userName != "")
            {
                userServiceKey.SetValue("ObjectName", ".\\" + userName);
            }
            else
            {
                userServiceKey.SetValue("ObjectName", ServiceAccount.LocalSystem);
            }
            //Set path where service is copied on the system 
            userServiceKey.SetValue("ImagePath", strPath + "\\" +serviceEXE+serviceExtn);
 
            //Start automatically
            userServiceKey.SetValue("Start", 0x02);
 
            userServiceKey.Close();
            SystemServicesKey.Close();
        }
        else
        {
            SystemServicesKey.Close();
            MessageBox.Show("Windows Service registration failed.Installation aborted!");
            blnServiceInstalled = false;
        }
    }
    return blnServiceInstalled;
}

Key Points

  • User can enter the logon account under whose security context this service will run. The sample code checks whether the logon account entered by user is one of the Domain users on the system. If invalid user is entered, then LocalSystem is set as the logon account for this service.
  • Custom actions always run at the end of the default installation.

Conclusion

Hope this code give an insight into writing custom actions and installing Windows service using Windows NT utilities. This is one of the possible methods for installing services. Since custom action is compiled as an executable, more customized code can be added in it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

lata07mahi


Member

Occupation: Software Developer
Location: India India

Other popular Installation articles:

Article Top
You must Sign In to use this message board.
FAQ FAQ 
 
Noise Tolerance  Layout  Per page   
 Msgs 1 to 5 of 5 (Total in Forum: 5) (Refresh)FirstPrevNext
GeneralHow to set password for the configured Account Pinmembertank_rakesh1:50 28 Jul '08  
GeneralRe: How to set password for the configured Account Pinmemberlata07mahi22:49 3 Aug '08  
GeneralWhy not just use what the .NET framework already provide? Pinmember leppie 2:54 15 May '08  
GeneralRe: Why not just use what the .NET framework already provide? PinmemberMartin Bohring5:55 15 May '08  
GeneralRe: Why not just use what the .NET framework already provide? PinmvpJohn Simmons / outlaw programmer7:24 15 May '08  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 15 May 2008
Editor:
Copyright 2008 by lata07mahi
Everything else Copyright © CodeProject, 1999-2009
Web12 | Advertise on the Code Project