How to programmatically install a Windows service in C #?

I have 3 projects in my VS solution. One of them is a web application, the second is a Windows service, and the last is an installation project for my web application.

What I want is towards the end of the web application installation in my installation project, as part of my user action, to try to install my Windows service, given that I have the build location by then.

+71
c # windows-services setup-project visual-studio-setup-proje
Dec 11 '08 at 8:38
source share
8 answers

Well, that’s what REALLY worked for me, it was tested on several computers with different OS (Vista, XP, Win2k, Win2003 server)

The code was taken from here, so the full credit belongs to the person who wrote this piece of code.

After you add the DLL or source file to your project, be sure to add the ServiceTools namespace, and then you will have access to some very convenient functions, such as ...

//Installs and starts the service ServiceInstaller.InstallAndStart("MyServiceName", "MyServiceDisplayName", "C:\\PathToServiceFile.exe"); //Removes the service ServiceInstaller.Uninstall("MyServiceName"); //Checks the status of the service ServiceInstaller.GetServiceStatus("MyServiceName"); //Starts the service ServiceInstaller.StartService("MyServiceName"); //Stops the service ServiceInstaller.StopService("MyServiceName"); //Check if service is installed ServiceInstaller.ServiceIsInstalled("MyServiceName"); 

Hope this helps.

+70
Mar 12 '09 at 8:26
source share

I found several errors in the code that you reused, and fixed them, and also cleared it a bit. And again, the source code is taken from here .

 public static class ServiceInstaller { private const int STANDARD_RIGHTS_REQUIRED = 0xF0000; private const int SERVICE_WIN32_OWN_PROCESS = 0x00000010; [StructLayout(LayoutKind.Sequential)] private class SERVICE_STATUS { public int dwServiceType = 0; public ServiceState dwCurrentState = 0; public int dwControlsAccepted = 0; public int dwWin32ExitCode = 0; public int dwServiceSpecificExitCode = 0; public int dwCheckPoint = 0; public int dwWaitHint = 0; } #region OpenSCManager [DllImport("advapi32.dll", EntryPoint = "OpenSCManagerW", ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)] static extern IntPtr OpenSCManager(string machineName, string databaseName, ScmAccessRights dwDesiredAccess); #endregion #region OpenService [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)] static extern IntPtr OpenService(IntPtr hSCManager, string lpServiceName, ServiceAccessRights dwDesiredAccess); #endregion #region CreateService [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)] private static extern IntPtr CreateService(IntPtr hSCManager, string lpServiceName, string lpDisplayName, ServiceAccessRights dwDesiredAccess, int dwServiceType, ServiceBootFlag dwStartType, ServiceError dwErrorControl, string lpBinaryPathName, string lpLoadOrderGroup, IntPtr lpdwTagId, string lpDependencies, string lp, string lpPassword); #endregion #region CloseServiceHandle [DllImport("advapi32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] static extern bool CloseServiceHandle(IntPtr hSCObject); #endregion #region QueryServiceStatus [DllImport("advapi32.dll")] private static extern int QueryServiceStatus(IntPtr hService, SERVICE_STATUS lpServiceStatus); #endregion #region DeleteService [DllImport("advapi32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool DeleteService(IntPtr hService); #endregion #region ControlService [DllImport("advapi32.dll")] private static extern int ControlService(IntPtr hService, ServiceControl dwControl, SERVICE_STATUS lpServiceStatus); #endregion #region StartService [DllImport("advapi32.dll", SetLastError = true)] private static extern int StartService(IntPtr hService, int dwNumServiceArgs, int lpServiceArgVectors); #endregion public static void Uninstall(string serviceName) { IntPtr scm = OpenSCManager(ScmAccessRights.AllAccess); try { IntPtr service = OpenService(scm, serviceName, ServiceAccessRights.AllAccess); if (service == IntPtr.Zero) throw new ApplicationException("Service not installed."); try { StopService(service); if (!DeleteService(service)) throw new ApplicationException("Could not delete service " + Marshal.GetLastWin32Error()); } finally { CloseServiceHandle(service); } } finally { CloseServiceHandle(scm); } } public static bool ServiceIsInstalled(string serviceName) { IntPtr scm = OpenSCManager(ScmAccessRights.Connect); try { IntPtr service = OpenService(scm, serviceName, ServiceAccessRights.QueryStatus); if (service == IntPtr.Zero) return false; CloseServiceHandle(service); return true; } finally { CloseServiceHandle(scm); } } public static void InstallAndStart(string serviceName, string displayName, string fileName) { IntPtr scm = OpenSCManager(ScmAccessRights.AllAccess); try { IntPtr service = OpenService(scm, serviceName, ServiceAccessRights.AllAccess); if (service == IntPtr.Zero) service = CreateService(scm, serviceName, displayName, ServiceAccessRights.AllAccess, SERVICE_WIN32_OWN_PROCESS, ServiceBootFlag.AutoStart, ServiceError.Normal, fileName, null, IntPtr.Zero, null, null, null); if (service == IntPtr.Zero) throw new ApplicationException("Failed to install service."); try { StartService(service); } finally { CloseServiceHandle(service); } } finally { CloseServiceHandle(scm); } } public static void StartService(string serviceName) { IntPtr scm = OpenSCManager(ScmAccessRights.Connect); try { IntPtr service = OpenService(scm, serviceName, ServiceAccessRights.QueryStatus | ServiceAccessRights.Start); if (service == IntPtr.Zero) throw new ApplicationException("Could not open service."); try { StartService(service); } finally { CloseServiceHandle(service); } } finally { CloseServiceHandle(scm); } } public static void StopService(string serviceName) { IntPtr scm = OpenSCManager(ScmAccessRights.Connect); try { IntPtr service = OpenService(scm, serviceName, ServiceAccessRights.QueryStatus | ServiceAccessRights.Stop); if (service == IntPtr.Zero) throw new ApplicationException("Could not open service."); try { StopService(service); } finally { CloseServiceHandle(service); } } finally { CloseServiceHandle(scm); } } private static void StartService(IntPtr service) { SERVICE_STATUS status = new SERVICE_STATUS(); StartService(service, 0, 0); var changedStatus = WaitForServiceStatus(service, ServiceState.StartPending, ServiceState.Running); if (!changedStatus) throw new ApplicationException("Unable to start service"); } private static void StopService(IntPtr service) { SERVICE_STATUS status = new SERVICE_STATUS(); ControlService(service, ServiceControl.Stop, status); var changedStatus = WaitForServiceStatus(service, ServiceState.StopPending, ServiceState.Stopped); if (!changedStatus) throw new ApplicationException("Unable to stop service"); } public static ServiceState GetServiceStatus(string serviceName) { IntPtr scm = OpenSCManager(ScmAccessRights.Connect); try { IntPtr service = OpenService(scm, serviceName, ServiceAccessRights.QueryStatus); if (service == IntPtr.Zero) return ServiceState.NotFound; try { return GetServiceStatus(service); } finally { CloseServiceHandle(service); } } finally { CloseServiceHandle(scm); } } private static ServiceState GetServiceStatus(IntPtr service) { SERVICE_STATUS status = new SERVICE_STATUS(); if (QueryServiceStatus(service, status) == 0) throw new ApplicationException("Failed to query service status."); return status.dwCurrentState; } private static bool WaitForServiceStatus(IntPtr service, ServiceState waitStatus, ServiceState desiredStatus) { SERVICE_STATUS status = new SERVICE_STATUS(); QueryServiceStatus(service, status); if (status.dwCurrentState == desiredStatus) return true; int dwStartTickCount = Environment.TickCount; int dwOldCheckPoint = status.dwCheckPoint; while (status.dwCurrentState == waitStatus) { // Do not wait longer than the wait hint. A good interval is // one tenth the wait hint, but no less than 1 second and no // more than 10 seconds. int dwWaitTime = status.dwWaitHint / 10; if (dwWaitTime < 1000) dwWaitTime = 1000; else if (dwWaitTime > 10000) dwWaitTime = 10000; Thread.Sleep(dwWaitTime); // Check the status again. if (QueryServiceStatus(service, status) == 0) break; if (status.dwCheckPoint > dwOldCheckPoint) { // The service is making progress. dwStartTickCount = Environment.TickCount; dwOldCheckPoint = status.dwCheckPoint; } else { if (Environment.TickCount - dwStartTickCount > status.dwWaitHint) { // No progress made within the wait hint break; } } } return (status.dwCurrentState == desiredStatus); } private static IntPtr OpenSCManager(ScmAccessRights rights) { IntPtr scm = OpenSCManager(null, null, rights); if (scm == IntPtr.Zero) throw new ApplicationException("Could not connect to service control manager."); return scm; } } public enum ServiceState { Unknown = -1, // The state cannot be (has not been) retrieved. NotFound = 0, // The service is not known on the host server. Stopped = 1, StartPending = 2, StopPending = 3, Running = 4, ContinuePending = 5, PausePending = 6, Paused = 7 } [Flags] public enum ScmAccessRights { Connect = 0x0001, CreateService = 0x0002, EnumerateService = 0x0004, Lock = 0x0008, QueryLockStatus = 0x0010, ModifyBootConfig = 0x0020, StandardRightsRequired = 0xF0000, AllAccess = (StandardRightsRequired | Connect | CreateService | EnumerateService | Lock | QueryLockStatus | ModifyBootConfig) } [Flags] public enum ServiceAccessRights { QueryConfig = 0x1, ChangeConfig = 0x2, QueryStatus = 0x4, EnumerateDependants = 0x8, Start = 0x10, Stop = 0x20, PauseContinue = 0x40, Interrogate = 0x80, UserDefinedControl = 0x100, Delete = 0x00010000, StandardRightsRequired = 0xF0000, AllAccess = (StandardRightsRequired | QueryConfig | ChangeConfig | QueryStatus | EnumerateDependants | Start | Stop | PauseContinue | Interrogate | UserDefinedControl) } public enum ServiceBootFlag { Start = 0x00000000, SystemStart = 0x00000001, AutoStart = 0x00000002, DemandStart = 0x00000003, Disabled = 0x00000004 } public enum ServiceControl { Stop = 0x00000001, Pause = 0x00000002, Continue = 0x00000003, Interrogate = 0x00000004, Shutdown = 0x00000005, ParamChange = 0x00000006, NetBindAdd = 0x00000007, NetBindRemove = 0x00000008, NetBindEnable = 0x00000009, NetBindDisable = 0x0000000A } public enum ServiceError { Ignore = 0x00000000, Normal = 0x00000001, Severe = 0x00000002, Critical = 0x00000003 } 

Please let me know if anyone finds something wrong with this code!

+70
Jul 23 '09 at 14:22
source share

Please see this article .




Sometimes you may need to programmatically install a Windows service, but there is no InstallUtil.exe on the target computer.

Add a link to System.Configuration.Install

Use the code below.

Note that exeFileName is InstallerClass.exe, not ServiceClass.exe.

 public static void InstallService(string exeFilename) { string[] commandLineOptions = new string[1] { "/LogFile=install.log" }; System.Configuration.Install.AssemblyInstaller installer = new System.Configuration.Install.AssemblyInstaller(exeFilename, commandLineOptions); installer.UseNewContext = true; installer.Install(null); installer.Commit(null); } 

To delete:

 public static void UninstallService(string exeFilename) { string[] commandLineOptions = new string[1] { "/LogFile=uninstall.log" }; System.Configuration.Install.AssemblyInstaller installer = new System.Configuration.Install.AssemblyInstaller(exeFilename, commandLineOptions); installer.UseNewContext = true; installer.Uninstall(null); } 
+30
Dec 11 '08 at 8:43
source share

After instantiating the installer class for my service (very simple) all I had to do was call:

 ManagedInstallerClass.InstallHelper(new string[] { Assembly.GetExecutingAssembly().Location }); 

to install it and

 ManagedInstallerClass.InstallHelper(new string[] { "/u", Assembly.GetExecutingAssembly().Location }); 

to remove the service. The calling code is here, in the same assembly as the service executable.

in order to get the service for installation via the command line, all I had to do was connect it with the command line executable arguments and test for System.Environment.UserInteractive to see if this service is being executed or someone is trying to System.Environment.UserInteractive remove it and voila ... no funky roll call ... no pointers flowing ...

Just about 20 lines of code, distributed across two classes, did the trick.

to replace InstallUtil just take a look at ManagedInstallerClass.InstallHelper

+11
Jul 23 '12 at 19:48
source share

Using the Topshelf project, you can install by calling your executable file:

 MyService.exe install 

Topshelf also takes care of other Windows plumbing services.

+4
Dec 10 '10 at 3:51
source share

Since I was faced with the problem of installing programs programmatically executed under a specific user. I extended the InstallAndStart method to use lp and lpPassword ...

Not much, but it can help.

 public static void InstallAndStart( string serviceName, string displayName, string fileName, string username, string password) { IntPtr scm = OpenSCManager(ScmAccessRights.AllAccess); try { IntPtr service = OpenService( scm, serviceName, ServiceAccessRights.AllAccess); if (service == IntPtr.Zero) service = CreateService( scm, serviceName, displayName, ServiceAccessRights.AllAccess, SERVICE_WIN32_OWN_PROCESS, ServiceBootFlag.AutoStart, ServiceError.Normal, fileName, null, IntPtr.Zero, null, username, password); if (service == IntPtr.Zero) throw new ApplicationException("Failed to install service."); try { StartService(service); } finally { CloseServiceHandle(service); } } finally { CloseServiceHandle(scm); } } 
+3
Nov 27 '14 at 19:31
source share

In this article, I read all posts and comments. Boo still don't know. How to set account type and StartType method when I am going to add a windows service. This sample code works fine on my side, just add your own local service system). But I am preparing a setup program. I have to think that the StartMode method and the type of user account are due to the client system. < b > Every view ServiceBootFlag lists provides StartType, but the Account Type is still a problem.

  [DllImport("advapi32.dll", EntryPoint = "CreateServiceA")] private static extern IntPtr CreateService(IntPtr hSCManager, string lpServiceName, string lpDisplayName, ServiceRights dwDesiredAccess, int dwServiceType, ServiceBootFlag dwStartType, ServiceError dwErrorControl, string lpBinaryPathName, string lpLoadOrderGroup, IntPtr lpdwTagId, string lpDependencies, string lp, string lpPassword); 
+1
Aug 26 '13 at 15:01
source share

Use the code below to install a Windows service using C #:

 public void InstallWinService(string winServicePath) { try { ManagedInstallerClass.InstallHelper(new string[] { winServicePath}); } catch (Exception) { throw; } } 
0
Mar 15 '16 at 12:30
source share



All Articles