private ServiceHandle GivenAServiceExists(string serviceName, bool canBeUpdated) { GivenTheServiceControlManagerCanBeOpened(); var serviceHandle = A.Fake <ServiceHandle>(o => o.Wrapping(new ServiceHandle { NativeInterop = nativeInterop })); A.CallTo(() => serviceHandle.IsInvalid).Returns(value: false); ServiceHandle dummyServiceHandle; Win32Exception dummyWin32Exception; A.CallTo(() => serviceControlManager.TryOpenService(serviceName, A <ServiceControlAccessRights> ._, out dummyServiceHandle, out dummyWin32Exception)) .Returns(value: true) .AssignsOutAndRefParameters(serviceHandle, null); if (canBeUpdated) { A.CallTo( () => nativeInterop.ChangeServiceConfigW(serviceHandle, A <ServiceType> ._, A <ServiceStartType> ._, A <ErrorSeverity> ._, A <string> ._, A <string> ._, A <IntPtr> ._, A <string> ._, A <string> ._, A <string> ._, A <string> ._)) .Returns(value: true); A.CallTo(() => nativeInterop.ChangeServiceConfig2W(serviceHandle, ServiceConfigInfoTypeLevel.ServiceDescription, A <IntPtr> ._)) .Returns(value: true); A.CallTo(() => nativeInterop.ChangeServiceConfig2W(serviceHandle, ServiceConfigInfoTypeLevel.FailureActions, A <IntPtr> ._)) .Returns(value: true); A.CallTo(() => nativeInterop.ChangeServiceConfig2W(serviceHandle, ServiceConfigInfoTypeLevel.FailureActionsFlag, A <IntPtr> ._)) .Returns(value: true); A.CallTo(() => nativeInterop.ChangeServiceConfig2W(serviceHandle, ServiceConfigInfoTypeLevel.DelayedAutoStartInfo, A <IntPtr> ._)) .ReturnsLazily((ServiceHandle handle, ServiceConfigInfoTypeLevel infoLevel, IntPtr info) => { if (info != IntPtr.Zero) { delayedAutoStartInfoSetOnNativeInterop = Marshal.ReadInt32(info) > 0; } else { delayedAutoStartInfoSetOnNativeInterop = null; } return(true); }); A.CallTo(() => nativeInterop.StartServiceW(serviceHandle, A <uint> ._, A <IntPtr> ._)) .Returns(value: true); } return(serviceHandle); }
/// <summary> /// Installs the service. /// </summary> /// <param name="DisplayName">Service display name.</param> /// <param name="Description">Service description.</param> /// <param name="StartType">How the service should be started.</param> /// <param name="StartImmediately">If the service should be started immediately.</param> /// <param name="FailureActions">Service failure actions.</param> /// <param name="Credentials">Credentials to use when running service.</param> /// <returns> /// Return code: /// /// 0: Installed, not started. /// 1: Installed, started. /// 2: Updated, not started. /// 3: Updated, started. /// </returns> /// <exception cref="Exception">If service could not be installed.</exception> public int Install(string DisplayName, string Description, ServiceStartType StartType, bool StartImmediately, ServiceFailureActions FailureActions, Win32ServiceCredentials Credentials) { string Path = Assembly.GetExecutingAssembly().Location.Replace(".dll", ".exe"); try { using (ServiceControlManager mgr = ServiceControlManager.Connect(null, null, ServiceControlManagerAccessRights.All)) { if (mgr.TryOpenService(this.serviceName, ServiceControlAccessRights.All, out ServiceHandle existingService, out Win32Exception errorException)) { using (existingService) { existingService.ChangeConfig(DisplayName, Path, ServiceType.Win32OwnProcess, StartType, ErrorSeverity.Normal, Credentials); if (!string.IsNullOrEmpty(Description)) { existingService.SetDescription(Description); } if (!(FailureActions is null)) { existingService.SetFailureActions(FailureActions); existingService.SetFailureActionFlag(true); } else { existingService.SetFailureActionFlag(false); } if (StartImmediately) { existingService.Start(throwIfAlreadyRunning: false); return(3); } else { return(2); } }
/// <summary> /// Creates the or update a windows service. /// Note that the service is not restarted due to changes in its configuration /// </summary> /// <param name="serviceDefinition">The service definition.</param> /// <param name="startImmediately">if set to <c>true</c> the service will be started immediatly after updating. Has no effect if the service is already running.</param> /// <exception cref="ArgumentException"> /// Thrown when: /// BinaryPath of <paramref name="serviceDefinition"/> is null or empty /// or /// ServiceName of <paramref name="serviceDefinition"/> is null or empty /// </exception> /// <exception cref="PlatformNotSupportedException">Thrown when run on a non-windows platform.</exception> public void CreateOrUpdateService(ServiceDefinition serviceDefinition, bool startImmediately = false) { if (string.IsNullOrEmpty(serviceDefinition.BinaryPath)) { throw new System.ArgumentException($"Invalid service definition. {nameof(ServiceDefinition.BinaryPath)} must not be null or empty.", nameof(serviceDefinition)); } if (string.IsNullOrEmpty(serviceDefinition.ServiceName)) { throw new System.ArgumentException($"Invalid service definition. {nameof(ServiceDefinition.ServiceName)} must not be null or empty.", nameof(serviceDefinition)); } try { using (ServiceControlManager mgr = ServiceControlManager.Connect(nativeInterop, machineName , databaseName, ServiceControlManagerAccessRights.All)) { if (mgr.TryOpenService(serviceDefinition.ServiceName , ServiceControlAccessRights.All , out ServiceHandle existingService , out System.ComponentModel.Win32Exception errorException) ) { using (existingService) { DoUpdateService(existingService, serviceDefinition, startImmediately); } } else { if (errorException.NativeErrorCode == KnownWin32ErrorCoes.ERROR_SERVICE_DOES_NOT_EXIST) { DoCreateService(mgr, serviceDefinition, startImmediately); } else { throw errorException; } } }
/// <summary> /// Installs the service. /// </summary> /// <param name="DisplayName">Service display name.</param> /// <param name="Description">Service description.</param> /// <param name="StartType">How the service should be started.</param> /// <param name="StartImmediately">If the service should be started immediately.</param> /// <param name="Credentials">Credentials to use when running service.</param> /// <returns> /// Return code: /// /// 0: Installed, not started. /// 1: Installed, started. /// 2: Updated, not started. /// 3: Updated, started. /// </returns> /// <exception cref="Exception">If service could not be installed.</exception> public int Install(string DisplayName, string Description, ServiceStartType StartType, bool StartImmediately, Win32ServiceCredentials Credentials) { string Path = Assembly.GetExecutingAssembly().Location.Replace(".dll", ".exe"); try { using (ServiceControlManager mgr = ServiceControlManager.Connect(null, null, ServiceControlManagerAccessRights.All)) { if (mgr.TryOpenService(this.serviceName, ServiceControlAccessRights.All, out ServiceHandle existingService, out Win32Exception errorException)) { using (existingService) { existingService.ChangeConfig(DisplayName, Path, ServiceType.Win32OwnProcess, StartType, ErrorSeverity.Normal, Credentials); if (!string.IsNullOrEmpty(Description)) { existingService.SetDescription(Description); } /*if (serviceFailureActions != null) * { * existingService.SetFailureActions(serviceFailureActions); * existingService.SetFailureActionFlag(failureActionsOnNonCrashFailures); * }*/ if (StartImmediately) { existingService.Start(throwIfAlreadyRunning: false); return(3); } else { return(2); } } } else { if (errorException.NativeErrorCode == Win32.ERROR_SERVICE_DOES_NOT_EXIST) { using (ServiceHandle svc = mgr.CreateService(this.serviceName, DisplayName, Path, ServiceType.Win32OwnProcess, StartType, ErrorSeverity.Normal, Credentials)) { if (!string.IsNullOrEmpty(Description)) { svc.SetDescription(Description); } /*if (serviceFailureActions != null) * { * svc.SetFailureActions(serviceFailureActions); * svc.SetFailureActionFlag(failureActionsOnNonCrashFailures); * }*/ if (StartImmediately) { svc.Start(); return(1); } else { return(0); } } } else { throw errorException; } } }