玄铁剑

成功的途径:抄,创造,研究,发明...
posts - 128, comments - 42, trackbacks - 0, articles - 174

Installing a Service Programmatically

Posted on 2007-01-03 11:16 玄铁剑 阅读(341) 评论(0)  编辑 收藏 引用 所属分类: Service
With the arrival of .Net, creation of a windows service has become a piece of cake by just selecting Windows Service as project type in the New Project Dialog Box. For installing a service, .Net provides a utility called installutil.exe which installs the service and registers it with Service Control Manager(SCM) but at times there is a need to install the service programmatically for example as a part of your custom installer program where you don't want your user to manually install the service using installutil.

The following piece of code shows how to install/uninstall a given service and register it with SCM calling appropriate APIs using P/Invoke in C#

 
SERVICEINSTALLER.CS
 
using System;
using System.Runtime.InteropServices;
 
namespace SvcInstaller
{
 /// <summary>
 /// Summary description for ServiceInstaller.
 /// </summary>
 class ServiceInstaller
 {
  #region Private Variables
  
  private string _servicePath;
  private string _serviceName;
  private string _serviceDisplayName;
 
  #endregion Private Variables
 
  #region DLLImport
  
  [DllImport("advapi32.dll")]
  public static extern IntPtr OpenSCManager(string lpMachineName,string lpSCDB, int scParameter);
  [DllImport("Advapi32.dll")]
  public static extern IntPtr CreateService(IntPtr SC_HANDLE,string lpSvcName,string lpDisplayName,
 int dwDesiredAccess,int dwServiceType,int dwStartType,int dwErrorControl,string lpPathName,
string lpLoadOrderGroup,int lpdwTagId,string lpDependencies,string lpServiceStartName,string lpPassword);
  [DllImport("advapi32.dll")]
  public static extern void CloseServiceHandle(IntPtr SCHANDLE);
  [DllImport("advapi32.dll")]
  public static extern int StartService(IntPtr SVHANDLE,int dwNumServiceArgs,string lpServiceArgVectors);
  
  [DllImport("advapi32.dll",SetLastError=true)]
  public static extern IntPtr OpenService(IntPtr SCHANDLE,string lpSvcName,int dwNumServiceArgs);
  [DllImport("advapi32.dll")]
  public static extern int DeleteService(IntPtr SVHANDLE);
 
  [DllImport("kernel32.dll")]
  public static extern int GetLastError();
  
  #endregion DLLImport
 
  
  /// <summary>
  /// The main entry point for the application.
  /// </summary>
  #region Main method + testing code
   [STAThread]
   static void Main(string[] args)
   {
    
     // TODO: Add code to start application here
    
    
    #region Testing
    //  Testing --------------
     string svcPath;
     string svcName;
     string svcDispName;
     
     //path to the service that you want to install
     svcPath = @"C:\build\service\Debug\Service.exe";
     svcDispName="Service Display Name";
     svcName= "Service Name";
 
     ServiceInstaller c = new ServiceInstaller();
     c.InstallService(svcPath, svcName, svcDispName);
 
     Console.Read();
       Testing --------------
    #endregion Testing
   }
  #endregion Main method + testing code - Commented
 

  
  /// <summary>
  /// This method installs and runs the service in the service conrol manager.
  /// </summary>
  /// <param name="svcPath">The complete path of the service.</param>
  /// <param name="svcName">Name of the service.</param>
  /// <param name="svcDispName">Display name of the service.</param>
  /// <returns>True if the process went thro successfully. False if there was any error.</returns>
  public bool InstallService(string svcPath, string svcName, string svcDispName)
  {
   #region Constants declaration.
   int SC_MANAGER_CREATE_SERVICE = 0x0002;
   int SERVICE_WIN32_OWN_PROCESS = 0x00000010;
   //int SERVICE_DEMAND_START = 0x00000003;
   int SERVICE_ERROR_NORMAL = 0x00000001;
 
   int STANDARD_RIGHTS_REQUIRED = 0xF0000;
   int SERVICE_QUERY_CONFIG       =    0x0001;
   int SERVICE_CHANGE_CONFIG       =   0x0002;
   int SERVICE_QUERY_STATUS           =  0x0004;
   int SERVICE_ENUMERATE_DEPENDENTS   = 0x0008;
   int SERVICE_START                  =0x0010;
   int SERVICE_STOP                   =0x0020;
   int SERVICE_PAUSE_CONTINUE         =0x0040;
   int SERVICE_INTERROGATE            =0x0080;
   int SERVICE_USER_DEFINED_CONTROL   =0x0100;
 
   int SERVICE_ALL_ACCESS             =  (STANDARD_RIGHTS_REQUIRED     |
        SERVICE_QUERY_CONFIG         |
        SERVICE_CHANGE_CONFIG        |
        SERVICE_QUERY_STATUS         |
        SERVICE_ENUMERATE_DEPENDENTS |
        SERVICE_START                |
        SERVICE_STOP                 |
        SERVICE_PAUSE_CONTINUE       |
        SERVICE_INTERROGATE          |
        SERVICE_USER_DEFINED_CONTROL);
   int SERVICE_AUTO_START = 0x00000002;
   #endregion Constants declaration.
 
   try
   {
    IntPtr  sc_handle = OpenSCManager(null,null,SC_MANAGER_CREATE_SERVICE);
 
    if (sc_handle.ToInt32() != 0)
    {
     IntPtr sv_handle = CreateService(sc_handle,svcName,svcDispName,SERVICE_ALL_ACCESS,SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START,SERVICE_ERROR_NORMAL,svcPath,null,0,null,null,null);
 
     if(sv_handle.ToInt32() ==0)
     {
 
      CloseServiceHandle(sc_handle);
      return false;
     }
     else
     {
      //now trying to start the service
      int i = StartService(sv_handle,0,null);
      // If the value i is zero, then there was an error starting the service.
      // note: error may arise if the service is already running or some other problem.
      if(i==0)
      {
       //Console.WriteLine("Couldnt start service");
       return false;
      }
      //Console.WriteLine("Success");
      CloseServiceHandle(sc_handle);
      return true;
     }
    }
    else
     //Console.WriteLine("SCM not opened successfully");
     return false;
 
   }
   catch(Exception e)
   {
    throw e;
   }
  }
 
  
  /// <summary>
  /// This method uninstalls the service from the service conrol manager.
  /// </summary>
  /// <param name="svcName">Name of the service to uninstall.</param>
  public bool UnInstallService(string svcName)
  {
   int GENERIC_WRITE = 0x40000000;
   IntPtr sc_hndl = OpenSCManager(null,null,GENERIC_WRITE);
 
   if(sc_hndl.ToInt32() !=0)
   {
    int DELETE = 0x10000;
    IntPtr svc_hndl = OpenService(sc_hndl,svcName,DELETE);
    //Console.WriteLine(svc_hndl.ToInt32());
    if(svc_hndl.ToInt32() !=0)
    { 
     int i = DeleteService(svc_hndl);
     if (i != 0)
     {
      CloseServiceHandle(sc_hndl);
      return true;
     }
     else
     {
      CloseServiceHandle(sc_hndl);
      return false;
     }
    }
    else
     return false;
   }
   else
    return false;
  }
 }
}
 

The above code shows that installing a service programmatically is as simple if not simpler than using installutil and gives you far more flexibility.
只有注册用户登录后才能发表评论。