public static extern bool ChangeServiceConfig2(IntPtr hService, int dwInfoLevel, [MarshalAs(UnmanagedType.Struct)] ref SERVICE_DESCRIPTION lpInfo);
//////////////////////////////////////////////////////////////////////////////////// // The worker method to set all the extension properties for the service private void UpdateServiceConfig(object sender, InstallEventArgs e) { // Determine if we need to set fail actions this.setFailActions = false; int numActions = FailureActions.Count; if (numActions > 0) { setFailActions = true; } // Do we need to do any work that the base installer did not do already? if (!(this.setDescription || this.setFailActions)) return; // We've got work to do IntPtr scmHndl = IntPtr.Zero; IntPtr svcHndl = IntPtr.Zero; IntPtr tmpBuf = IntPtr.Zero; IntPtr svcLock = IntPtr.Zero; // Err check var bool rslt = false; // Place all our code in a try block try { // Open the service control manager scmHndl = OpenSCManager(null, null, SC_MANAGER_ALL_ACCESS); if (scmHndl.ToInt32() <= 0) { LogInstallMessage(EventLogEntryType.Error, logMsgBase + "Failed to Open Service Control Manager"); return; } // Lock the Service Database svcLock = LockServiceDatabase(scmHndl); if (svcLock.ToInt32() <= 0) { LogInstallMessage(EventLogEntryType.Error, logMsgBase + "Failed to Lock Service Database for Write"); return; } // Open the service svcHndl = OpenService(scmHndl, base.ServiceName, SERVICE_ALL_ACCESS); if (svcHndl.ToInt32() <= 0) { LogInstallMessage(EventLogEntryType.Information, logMsgBase + "Failed to Open Service "); return; } // Need to set service failure actions. Note that the API lets us set as many as // we want, yet the Service Control Manager GUI only lets us see the first 3. // Bill is aware of this and has promised no fixes. Also note that the API allows // granularity of seconds whereas GUI only shows days and minutes. if (this.setFailActions) { // We're gonna serialize the SA_ACTION structs into an array of ints // for simplicity in marshalling this variable length ptr to win32 int[] actions = new int[numActions * 2]; int currInd = 0; bool needShutdownPrivilege = false; foreach (FailureAction fa in FailureActions) { actions[currInd] = (int)fa.Type; actions[++currInd] = fa.Delay; currInd++; if (fa.Type == RecoverAction.Reboot) { needShutdownPrivilege = true; } } // If we need shutdown privilege, then grant it to this process if (needShutdownPrivilege) { rslt = this.GrandShutdownPrivilege(); if (!rslt) return; } // Need to pack 8 bytes per struct tmpBuf = Marshal.AllocHGlobal(numActions * 8); // Move array into marshallable pointer Marshal.Copy(actions, 0, tmpBuf, numActions * 2); // Set the SERVICE_FAILURE_ACTIONS struct SERVICE_FAILURE_ACTIONS sfa = new SERVICE_FAILURE_ACTIONS(); sfa.cActions = numActions; sfa.dwResetPeriod = this.failResetTime; sfa.lpCommand = this.failRunCommand; sfa.lpRebootMsg = this.failRebootMsg; sfa.lpsaActions = tmpBuf.ToInt32(); // Call the ChangeServiceFailureActions() abstraction of ChangeServiceConfig2() rslt = ChangeServiceFailureActions(svcHndl, SERVICE_CONFIG_FAILURE_ACTIONS, ref sfa); //Check the return if (!rslt) { int err = Marshal.GetLastWin32Error(); if (err == ERROR_ACCESS_DENIED) { throw new Exception(logMsgBase + "Access Denied while setting Failure Actions"); } } // Free the memory Marshal.FreeHGlobal(tmpBuf); tmpBuf = IntPtr.Zero; LogInstallMessage(EventLogEntryType.Information, logMsgBase + "Successfully configured Failure Actions"); } // Need to set the description field? if (this.setDescription) { SERVICE_DESCRIPTION sd = new SERVICE_DESCRIPTION(); sd.lpDescription = this.description; // Call the ChangeServiceDescription() abstraction of ChangeServiceConfig2() rslt = ChangeServiceDescription(svcHndl, SERVICE_CONFIG_DESCRIPTION, ref sd); // Error setting description? if (!rslt) { throw new Exception(logMsgBase + "Failed to set description"); } LogInstallMessage(EventLogEntryType.Information, logMsgBase + "Successfully set description"); } } // Catch all exceptions catch (Exception ex) { ex.Trace(); } finally { if (scmHndl != IntPtr.Zero) { // Unlock the service database if (svcLock != IntPtr.Zero) { UnlockServiceDatabase(svcLock); svcLock = IntPtr.Zero; } // Close the service control manager handle CloseServiceHandle(scmHndl); scmHndl = IntPtr.Zero; } // Close the service handle if (svcHndl != IntPtr.Zero) { CloseServiceHandle(svcHndl); svcHndl = IntPtr.Zero; } // Free the memory if (tmpBuf != IntPtr.Zero) { Marshal.FreeHGlobal(tmpBuf); tmpBuf = IntPtr.Zero; } } // End try-catch-finally }
/// <summary> /// Installs and optionally starts the service. /// </summary> /// <param name="path">The full path of the service exe.</param> /// <param name="name">The name of the service.</param> /// <param name="displayName">The display name of the service.</param> /// <param name="description">The description for the service.</param> /// <param name="startMode">The service start mode.</param> /// <param name="userName">The account name. Null to use the default account (LocalSystem).</param> /// <param name="password">The account password.</param> /// <param name="start">True to start the service after the installation; otherwise, false. /// Once the method returns you can use this parameter to check whether the service is running or not.</param> /// <param name="dependencies">The list of dependencies services. Null if there are no dependencies.</param> /// <returns>True for success. Otherwise, false.</returns> public static bool InstallService( string path, string name, string displayName, string description, StartMode startMode, string userName, string password, ref bool start, string[] dependencies) { uint SC_MANAGER_CREATE_SERVICE = 0x0002; if (string.IsNullOrEmpty(userName)) { userName = null; password = null; } // check if an existing service needs to uninstalled. try { Service existingService = ServiceManager.GetService(name); if (existingService != null) { if (existingService.StartMode != StartMode.Disabled && existingService.Path == path) { if (existingService.Status == ServiceStatus.Stopped) { ServiceManager.StartService(name); } return(true); } UnInstallService(name); } } catch (Exception e) { Utils.Trace(e, "CreateService Exception"); } IntPtr svHandle = IntPtr.Zero; try { IntPtr scHandle = OpenSCManagerW(null, null, SC_MANAGER_CREATE_SERVICE); if (scHandle.ToInt64() != 0) { string dependencyServices = string.Empty; if (dependencies != null && dependencies.Length > 0) { for (int i = 0; i < dependencies.Length; i++) { if (!string.IsNullOrEmpty(dependencies[i])) { dependencyServices += dependencies[i].Trim(); if (i < dependencies.Length - 1) { dependencyServices += "\0";//add a null char separator } } } } if (dependencyServices == string.Empty) { dependencyServices = null; } // lpDependencies, if not null, must be a series of strings concatenated with the null character as a delimiter, including a trailing one. svHandle = CreateServiceW( scHandle, name, displayName, (uint)ServiceAccess.AllAccess, (uint)ServiceType.OwnProcess, (uint)startMode, (uint)ServiceError.ErrorNormal, path, null, 0, dependencyServices, userName, password); if (svHandle.ToInt64() == 0) { int error = GetLastError(); Utils.Trace("CreateService Error: {0}", error); return(false); } // set the description. if (!String.IsNullOrEmpty(description)) { SERVICE_DESCRIPTION info = new SERVICE_DESCRIPTION(); info.lpDescription = description; IntPtr pInfo = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(SERVICE_DESCRIPTION))); Marshal.StructureToPtr(info, pInfo, false); try { int result = ChangeServiceConfig2W(svHandle, SERVICE_CONFIG_DESCRIPTION, pInfo); if (result == 0) { Utils.Trace("Could not set description for service: {0}", displayName); } } finally { Marshal.DestroyStructure(pInfo, typeof(SERVICE_DESCRIPTION)); Marshal.FreeCoTaskMem(pInfo); } } // start the service. if (start) { start = ServiceManager.StartService(name, new TimeSpan(0, 0, 0, 60)); } return(true); } } catch (Exception e) { Utils.Trace(e, "CreateService Exception"); } finally { SafeCloseServiceHandle(svHandle); } return(false); }
public static extern bool ChangeServiceConfig2A(IntPtr hService, InfoLevel dwInfoLevel, ref SERVICE_DESCRIPTION lpInfo);
public static partial bool ChangeServiceConfig2(SafeServiceHandle serviceHandle, uint infoLevel, ref SERVICE_DESCRIPTION serviceDesc);
private static extern bool ChangeServiceConfig2( IntPtr hService, ServiceConfig dwInfoLevel, ref SERVICE_DESCRIPTION lpInfo);
public static extern bool ChangeServiceConfig2(IntPtr serviceHandle, uint infoLevel, ref SERVICE_DESCRIPTION serviceDesc);
ChangeServiceDescription(IntPtr hService, int dwInfoLevel, [MarshalAs(UnmanagedType.Struct)] ref SERVICE_DESCRIPTION lpInfo);
/// <summary> /// Installs the specified service name. /// </summary> /// <param name="serviceName">Name of the service.</param> /// <param name="displayName">The display name.</param> /// <param name="description">The description.</param> /// <param name="fileName">Name of the file.</param> /// <param name="userName">Name of the user.</param> /// <param name="password">The password.</param> /// <exception cref="System.ComponentModel.Win32Exception"> /// </exception> public static void Install( [NotNull] string serviceName, [NotNull] string displayName, [NotNull] string description, [NotNull] string fileName, [CanBeNull] string userName = null, [CanBeNull] string password = null) { if (serviceName == null) { throw new ArgumentNullException("serviceName"); } if (displayName == null) { throw new ArgumentNullException("displayName"); } if (description == null) { throw new ArgumentNullException("description"); } if (fileName == null) { throw new ArgumentNullException("fileName"); } if (ServiceIsInstalled(serviceName)) { return; } IntPtr scm = OpenSCManager(ScmAccessRights.AllAccess); try { if (fileName.Contains(' ')) { fileName = string.Format("\"{0}\"", fileName); } IntPtr 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 CommonServiceException( new Win32Exception(), () => CommonResources.Err_ServiceUtils_Install_CouldNotInstallService, serviceName); } try { // Set description SERVICE_DESCRIPTION sd = new SERVICE_DESCRIPTION { description = Marshal.StringToHGlobalUni(description) }; try { bool flag = ChangeServiceConfig2(service, ServiceConfig.Description, ref sd); if (!flag) { throw new CommonServiceException( new Win32Exception(), () => CommonResources.Err_ServiceUtils_Install_CouldNotSetDescription, serviceName); } } finally { Marshal.FreeHGlobal(sd.description); } } finally { CloseServiceHandle(service); } } finally { CloseServiceHandle(scm); } }
private static extern int ChangeServiceConfig2(IntPtr hService, int dwServiceConfigDescription, ref SERVICE_DESCRIPTION lpInfo);
public static extern bool ChangeServiceConfigDescription( IntPtr hService, uint dwInfoLevel, ref SERVICE_DESCRIPTION lpInfo);
private static extern bool ChangeServiceConfig2(IntPtr hService, int dwInfoLevel, ref SERVICE_DESCRIPTION lpDescription);
/// <summary> /// Installs and optionally starts the service. /// </summary> /// <param name="path">The full path of the service exe.</param> /// <param name="name">The name of the service.</param> /// <param name="displayName">The display name of the service.</param> /// <param name="description">The description for the service.</param> /// <param name="startMode">The service start mode.</param> /// <param name="userName">The account name. Null to use the default account (LocalSystem).</param> /// <param name="password">The account password.</param> /// <param name="start">True to start the service after the installation; otherwise, false. /// Once the method returns you can use this parameter to check whether the service is running or not.</param> /// <param name="dependencies">The list of dependencies services. Null if there are no dependencies.</param> /// <returns>True for success. Otherwise, false.</returns> public static bool InstallService( string path, string name, string displayName, string description, StartMode startMode, string userName, string password, ref bool start, string[] dependencies) { uint SC_MANAGER_CREATE_SERVICE = 0x0002; if (string.IsNullOrEmpty(userName)) { userName = null; password = null; } // check if an existing service needs to uninstalled. try { Service existingService = ServiceManager.GetService(name); if (existingService != null) { if (existingService.StartMode != StartMode.Disabled && existingService.Path == path) { if (existingService.Status == ServiceStatus.Stopped) { ServiceManager.StartService(name); } return true; } UnInstallService(name); } } catch (Exception e) { Utils.Trace(e, "CreateService Exception"); } IntPtr svHandle = IntPtr.Zero; try { IntPtr scHandle = OpenSCManagerW(null, null, SC_MANAGER_CREATE_SERVICE); if (scHandle.ToInt64() != 0) { string dependencyServices = string.Empty; if(dependencies!=null && dependencies.Length > 0) { for (int i = 0; i < dependencies.Length; i++) { if (!string.IsNullOrEmpty(dependencies[i])) { dependencyServices += dependencies[i].Trim(); if (i < dependencies.Length - 1) dependencyServices += "\0";//add a null char separator } } } if (dependencyServices == string.Empty) dependencyServices = null; // lpDependencies, if not null, must be a series of strings concatenated with the null character as a delimiter, including a trailing one. svHandle = CreateServiceW( scHandle, name, displayName, (uint)ServiceAccess.AllAccess, (uint)ServiceType.OwnProcess, (uint)startMode, (uint)ServiceError.ErrorNormal, path, null, 0, dependencyServices, userName, password); if (svHandle.ToInt64() == 0) { int error = GetLastError(); Utils.Trace("CreateService Error: {0}", error); return false; } // set the description. if (!String.IsNullOrEmpty(description)) { SERVICE_DESCRIPTION info = new SERVICE_DESCRIPTION(); info.lpDescription = description; IntPtr pInfo = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(SERVICE_DESCRIPTION))); Marshal.StructureToPtr(info, pInfo, false); try { int result = ChangeServiceConfig2W(svHandle, SERVICE_CONFIG_DESCRIPTION, pInfo); if (result == 0) { Utils.Trace("Could not set description for service: {0}", displayName); } } finally { Marshal.DestroyStructure(pInfo, typeof(SERVICE_DESCRIPTION)); Marshal.FreeCoTaskMem(pInfo); } } // start the service. if (start) { start = ServiceManager.StartService(name, new TimeSpan(0, 0, 0, 60)); } return true; } } catch (Exception e) { Utils.Trace(e, "CreateService Exception"); } finally { SafeCloseServiceHandle(svHandle); } return false; }
/// <summary> /// This method installs and runs the service in the service control 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> /// <param name="svcDescription">The English description of the service.</param> /// <param name="svcStartType">The start type of the service (automatic, manual, etc)</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, string svcDescription, SERVICE_START_TYPE svcStartType, string dependencies) { var bSuccess = false; #region Constants declaration. int SERVICE_WIN32_OWN_PROCESS = 0x00000010; int SERVICE_INTERACTIVE_PROCESS = 0x00000100; 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); #endregion Constants declaration. try { var hServiceCtrlMgr = OpenSCManager(null, null, SCM_ACCESS.SC_MANAGER_CREATE_SERVICE); var servDesc = new SERVICE_DESCRIPTION() { lpDescription = svcDescription }; if (hServiceCtrlMgr.ToInt32() != 0) { IntPtr hService = CreateService(hServiceCtrlMgr, svcName, svcDispName, SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS, svcStartType, SERVICE_ERROR_NORMAL, svcPath, null, 0, dependencies, null, null); if (hService.ToInt32() == 0) { CloseServiceHandle(hServiceCtrlMgr); throw new Exception("Unable to start the service due to some error. Is the service already running?"); } else { // Add the description to the service bSuccess = ChangeServiceConfig2A(hService, InfoLevel.SERVICE_CONFIG_DESCRIPTION, ref servDesc); // Now trying to start the service int nStartSuccess = StartService(hService, 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 (nStartSuccess != 0) { CloseServiceHandle(hServiceCtrlMgr); bSuccess = true; } else throw new Exception("Unable to start the service due to some error. Is the service already running?"); } } } catch (Exception ex) { Trace.WriteLine(ex); } return bSuccess; }
/// <summary> /// Installs the specified service name. /// </summary> /// <param name="serviceName">Name of the service.</param> /// <param name="displayName">The display name.</param> /// <param name="description">The description.</param> /// <param name="fileName">Name of the file.</param> /// <param name="userName">Name of the user.</param> /// <param name="password">The password.</param> /// <exception cref="System.ComponentModel.Win32Exception"> /// </exception> public static void Install( [NotNull] string serviceName, [NotNull] string displayName, [NotNull] string description, [NotNull] string fileName, [CanBeNull] string userName = null, [CanBeNull] string password = null) { if (serviceName == null) throw new ArgumentNullException("serviceName"); if (displayName == null) throw new ArgumentNullException("displayName"); if (description == null) throw new ArgumentNullException("description"); if (fileName == null) throw new ArgumentNullException("fileName"); if (ServiceIsInstalled(serviceName)) return; IntPtr scm = OpenSCManager(ScmAccessRights.AllAccess); try { if (fileName.Contains(' ')) fileName = string.Format("\"{0}\"", fileName); IntPtr 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 CommonServiceException( new Win32Exception(), () => CommonResources.Err_ServiceUtils_Install_CouldNotInstallService, serviceName); try { // Set description SERVICE_DESCRIPTION sd = new SERVICE_DESCRIPTION { description = Marshal.StringToHGlobalUni(description) }; try { bool flag = ChangeServiceConfig2(service, ServiceConfig.Description, ref sd); if (!flag) throw new CommonServiceException( new Win32Exception(), () => CommonResources.Err_ServiceUtils_Install_CouldNotSetDescription, serviceName); } finally { Marshal.FreeHGlobal(sd.description); } } finally { CloseServiceHandle(service); } } finally { CloseServiceHandle(scm); } }
public static void Install(string serviceName, string displayName, string fileName, ServiceBootFlag startFlag = ServiceBootFlag.AutoStart, string description = null) { var scm = OpenSCManager(ScmAccessRights.AllAccess); try { var service = OpenService(scm, serviceName, ServiceAccessRights.AllAccess); if (service == IntPtr.Zero) service = CreateService(scm, serviceName, displayName, ServiceAccessRights.AllAccess, SERVICE_WIN32_OWN_PROCESS, startFlag, ServiceError.Normal, fileName, null, IntPtr.Zero, null, null, null); if (service == IntPtr.Zero) throw new ApplicationException("Failed to install service."); if (!string.IsNullOrEmpty(description)) { var serviceDescription = new SERVICE_DESCRIPTION { lpDescription = Marshal.StringToHGlobalAnsi(description) }; ChangeServiceConfig2(service, SERVICE_CONFIG_DESCRIPTION, ref serviceDescription); Marshal.FreeHGlobal(serviceDescription.lpDescription); } CloseServiceHandle(service); } finally { CloseServiceHandle(scm); } }
/// <summary> /// Update installed service's config accordinly. /// </summary> /// <param name="sender">sender</param> /// <param name="e">event args</param> private void UpdateServiceConfig(object sender, InstallEventArgs e) { IntPtr scmHndl = IntPtr.Zero; IntPtr svcHndl = IntPtr.Zero; IntPtr tmpBuf = IntPtr.Zero; IntPtr svcLock = IntPtr.Zero; try { // Open the service control manager scmHndl = OpenSCManager(null, null, SC_MANAGER_ALL_ACCESS); if (scmHndl.ToInt32() <= 0) { LogInstallMessage(EventLogEntryType.Error, "Failed to Open Service Control Manager"); return; } // Lock the Service Database svcLock = LockServiceDatabase(scmHndl); if (svcLock.ToInt32() <= 0) { LogInstallMessage(EventLogEntryType.Error, "Failed to Lock Service Database for Write"); return; } // Open the service svcHndl = OpenService(scmHndl, ServiceName, SERVICE_ALL_ACCESS); if (svcHndl.ToInt32() <= 0) { LogInstallMessage(EventLogEntryType.Information, "Failed to Open Service "); return; } // Need to set service failure actions. Note that the API lets us set as many as // we want, yet the Service Control Manager GUI only lets us see the first 3. // Also note that the API allows granularity of seconds whereas GUI only shows days and minutes. if (FailureActions.Count > 0) { int[] actions = new int[FailureActions.Count * 2]; int i = 0; bool needShutdownPrivilege = false; foreach (FailureAction fa in FailureActions) { actions[i] = (int)fa.Type; actions[++i] = fa.DelaySeconds * 1000; i++; if (fa.Type == FailureActionType.Reboot) { needShutdownPrivilege = true; } } // If we need shutdown privilege, then grant it to this process if (needShutdownPrivilege) { GrantShutdownPrivilege(); } tmpBuf = Marshal.AllocHGlobal(FailureActions.Count * 8); Marshal.Copy(actions, 0, tmpBuf, FailureActions.Count * 2); SERVICE_FAILURE_ACTIONS sfa = new SERVICE_FAILURE_ACTIONS(); sfa.cActions = FailureActions.Count; sfa.dwResetPeriod = FailCountResetTime; if (FailureCommandAction != null) { sfa.lpCommand = FailureCommandAction.ToString(); } sfa.lpRebootMsg = FailureRebootMessage; sfa.lpsaActions = tmpBuf.ToInt32(); SERVICE_FAILURE_ACTIONS_FLAG sfaf = new SERVICE_FAILURE_ACTIONS_FLAG(); sfaf.bFailureAction = true; if (!ChangeServiceFailureActionFlag(svcHndl, SERVICE_CONFIG_FAILURE_ACTIONS_FLAG, ref sfaf)) { throw new Win32Exception(GetLastError()); } if (!ChangeServiceFailureActions(svcHndl, SERVICE_CONFIG_FAILURE_ACTIONS, ref sfa)) { if (GetLastError() == ERROR_ACCESS_DENIED) { throw new Exception( "Access Denied while setting Failure Actions"); } } Marshal.FreeHGlobal(tmpBuf); tmpBuf = IntPtr.Zero; LogInstallMessage(EventLogEntryType.Information, "Successfully configured Failure Actions"); } if (Description != null && Description.Length > 0) { SERVICE_DESCRIPTION sd = new SERVICE_DESCRIPTION(); sd.lpDescription = Description; if (!ChangeServiceDescription(svcHndl, SERVICE_CONFIG_DESCRIPTION, ref sd)) { throw new Exception("Failed to set description"); } LogInstallMessage(EventLogEntryType.Information, "Successfully set description"); } } catch (Exception ex) { LogInstallMessage(EventLogEntryType.Error, Format(ex)); } finally { if (scmHndl != IntPtr.Zero) { // Unlock the service database if (svcLock != IntPtr.Zero) { UnlockServiceDatabase(svcLock); svcLock = IntPtr.Zero; } CloseServiceHandle(scmHndl); scmHndl = IntPtr.Zero; } // Close the service handle if (svcHndl != IntPtr.Zero) { CloseServiceHandle(svcHndl); svcHndl = IntPtr.Zero; } // Free the memory if (tmpBuf != IntPtr.Zero) { Marshal.FreeHGlobal(tmpBuf); tmpBuf = IntPtr.Zero; } } }
private static extern int ChangeServiceConfig2(IntPtr hService, uint dwInfoLevel, ref SERVICE_DESCRIPTION info);
//////////////////////////////////////////////////////////////////////////////////// // The worker method to set all the extension properties for the service public void UpdateServiceConfig(object sender, InstallEventArgs e) { // Determine if we need to set fail actions this.setFailActions = false; int numActions = FailureActions.Count; if (numActions > 0) { setFailActions = true; } // Do we need to do any work that the base installer did not do already? if (!(this.setDescription || this.setFailActions)) { return; } // We've got work to do IntPtr scmHndl = IntPtr.Zero; IntPtr svcHndl = IntPtr.Zero; IntPtr tmpBuf = IntPtr.Zero; IntPtr svcLock = IntPtr.Zero; // Err check var bool rslt = false; // Place all our code in a try block try { // Open the service control manager scmHndl = OpenSCManager(null, null, SC_MANAGER_ALL_ACCESS); if (scmHndl.ToInt32() <= 0) { LogInstallMessage(EventLogEntryType.Error, logMsgBase + "Failed to Open Service Control Manager"); return; } // Lock the Service Database svcLock = LockServiceDatabase(scmHndl); if (svcLock.ToInt32() <= 0) { LogInstallMessage(EventLogEntryType.Error, logMsgBase + "Failed to Lock Service Database for Write"); return; } // Open the service svcHndl = OpenService(scmHndl, base.ServiceName, SERVICE_ALL_ACCESS); if (svcHndl.ToInt32() <= 0) { LogInstallMessage(EventLogEntryType.Information, logMsgBase + "Failed to Open Service "); return; } // Need to set service failure actions. Note that the API lets us set as many as // we want, yet the Service Control Manager GUI only lets us see the first 3. // Bill is aware of this and has promised no fixes. Also note that the API allows // granularity of seconds whereas GUI only shows days and minutes. if (this.setFailActions) { // We're gonna serialize the SA_ACTION structs into an array of ints // for simplicity in marshalling this variable length ptr to win32 int[] actions = new int[numActions * 2]; int currInd = 0; bool needShutdownPrivilege = false; foreach (FailureAction fa in FailureActions) { actions[currInd] = (int)fa.Type; actions[++currInd] = fa.Delay; currInd++; if (fa.Type == RecoverAction.Reboot) { needShutdownPrivilege = true; } } // If we need shutdown privilege, then grant it to this process if (needShutdownPrivilege) { rslt = this.GrandShutdownPrivilege(); if (!rslt) { return; } } // Need to pack 8 bytes per struct tmpBuf = Marshal.AllocHGlobal(numActions * 8); // Move array into marshallable pointer Marshal.Copy(actions, 0, tmpBuf, numActions * 2); // Set the SERVICE_FAILURE_ACTIONS struct SERVICE_FAILURE_ACTIONS sfa = new SERVICE_FAILURE_ACTIONS(); sfa.cActions = numActions; sfa.dwResetPeriod = this.failResetTime; sfa.lpCommand = this.failRunCommand; sfa.lpRebootMsg = this.failRebootMsg; sfa.lpsaActions = tmpBuf.ToInt32(); // Call the ChangeServiceFailureActions() abstraction of ChangeServiceConfig2() rslt = ChangeServiceFailureActions(svcHndl, SERVICE_CONFIG_FAILURE_ACTIONS, ref sfa); //Check the return if (!rslt) { int err = GetLastError(); if (err == ERROR_ACCESS_DENIED) { throw new Exception(logMsgBase + "Access Denied while setting Failure Actions"); } } // Free the memory Marshal.FreeHGlobal(tmpBuf); tmpBuf = IntPtr.Zero; LogInstallMessage(EventLogEntryType.Information, logMsgBase + "Successfully configured Failure Actions"); } // Need to set the description field? if (this.setDescription) { SERVICE_DESCRIPTION sd = new SERVICE_DESCRIPTION(); sd.lpDescription = this.description; // Call the ChangeServiceDescription() abstraction of ChangeServiceConfig2() rslt = ChangeServiceDescription(svcHndl, SERVICE_CONFIG_DESCRIPTION, ref sd); // Error setting description? if (!rslt) { throw new Exception(logMsgBase + "Failed to set description"); } LogInstallMessage(EventLogEntryType.Information, logMsgBase + "Successfully set description"); } } // Catch all exceptions catch (Exception ex) { LogInstallMessage(EventLogEntryType.Error, ex.Message); } finally{ if (scmHndl != IntPtr.Zero) { // Unlock the service database if (svcLock != IntPtr.Zero) { UnlockServiceDatabase(svcLock); svcLock = IntPtr.Zero; } // Close the service control manager handle CloseServiceHandle(scmHndl); scmHndl = IntPtr.Zero; } // Close the service handle if (svcHndl != IntPtr.Zero) { CloseServiceHandle(svcHndl); svcHndl = IntPtr.Zero; } // Free the memory if (tmpBuf != IntPtr.Zero) { Marshal.FreeHGlobal(tmpBuf); tmpBuf = IntPtr.Zero; } } // End try-catch-finally }
public static unsafe void SetServiceDescription( String name, String description) { // prepare byte *_name = stackalloc byte[ name.Length]; byte *_desc = stackalloc byte[ description.Length]; char[] cname = name.ToCharArray(); char[] cdesc = description.ToCharArray(); // copy the name for( int i = 0; i < name.Length; i++) _name[i] = (byte)cname[i]; _name[ name.Length] = 0; for( int i = 0; i < description.Length; i++) _desc[i] = (byte)cdesc[i]; _desc[ description.Length] = 0; IntPtr srvName = new IntPtr( _name); SERVICE_DESCRIPTION info = new SERVICE_DESCRIPTION(); info.description = new IntPtr( _desc); // open the SC manager db IntPtr scHandle = Win32_OpenSCManager( new IntPtr(null), new IntPtr(null), STANDARD_RIGHTS_REQUIRED | SC_MANAGER_CONNECT | SC_MANAGER_CREATE_SERVICE | SC_MANAGER_ENUMERATE_SERVICE | SC_MANAGER_LOCK | SC_MANAGER_QUERY_LOCK_STATUS | SC_MANAGER_MODIFY_BOOT_CONFIG ); // open the service IntPtr srvHandle = Win32_OpenService( scHandle, srvName, SERVICE_CHANGE_CONFIG); // set service description Win32_ChangeServiceConfig2( srvHandle, SERVICE_CONFIG_DESCRIPTION, new IntPtr( &info)); // close service Win32_CloseService( srvHandle); // close SC manager db }