/// <summary> /// This method stops a given service and deletes it. The SCM handle passed must have standard rights. /// It handles the case of service not being in started mode. /// </summary> /// <param name="hSCManager">Handle to SCM with standard rights</param> /// <param name="svcName">Name of the service to be deleted</param> public static ServiceDeleteStatus StopAndRemoveService(IntPtr hSCManager, string svcName) { AppAssert.Assert(NativeMethods.NullIntPtr != hSCManager, "Invalid SC Manager handle!"); AppAssert.Assert(null != svcName, "Null service name passed!"); //return success if the service doesn't exist if (ServiceConfigurationHandler.CheckServiceExists(hSCManager, svcName) == false) { return(ServiceDeleteStatus.ServiceDeleteSuccess); } // stop and delete the service try { //stop the service ServiceConfigurationHandler.StopService(svcName); ServiceConfigurationHandler.DeleteService(hSCManager, svcName);//throws ServiceConfigurationException if delete failed } catch { return(ServiceDeleteStatus.ServiceDeleteFailed); } //state: Delete succeeded return(ServiceDeleteStatus.ServiceDeleteSuccess); }
/// <summary> /// Checks if a service exists. /// </summary> /// <param name="hSCManager">Handle to SCM</param> /// <param name="serviceName">Name of the service</param> /// <returns></returns> public static bool CheckServiceExists(IntPtr hSCManager, string serviceName) { AppAssert.Assert(NativeMethods.NullIntPtr != hSCManager, "Invalid SC Manager handle!"); AppAssert.Assert(null != serviceName, "Null service name passed!"); IntPtr hSvc = NativeMethods.NullIntPtr; try { hSvc = NativeMethods.OpenService(hSCManager, serviceName, NativeMethods.SERVICE_QUERY_CONFIG); if (NativeMethods.NullIntPtr.Equals(hSvc)) { int lastWin32Error = System.Runtime.InteropServices.Marshal.GetLastWin32Error(); if (NativeMethods.ERROR_SERVICE_DOES_NOT_EXIST == lastWin32Error) { return(false); } else { throw new Exception(String.Format("Cannot connect to the service {0}", serviceName)); } } else { return(true); } } finally { if (!NativeMethods.NullIntPtr.Equals(hSvc)) { NativeMethods.CloseServiceHandle(hSvc); } } }
/// <summary> /// Attempts to stop a service /// Waits for timeout period for the service to stop /// Logs result and returns. /// </summary> /// <param name="serviceName"></param> private static void StopService(string serviceName) { AppAssert.Assert(null != serviceName, "Null service name passed!"); SetupLogger.LogInfo("ServiceConfigurationHandler.StopService: Stop the service {0}", serviceName); try { //InspectHelper.StopService(serviceName); using (ServiceController serviceController = new ServiceController(serviceName)) { // Check if the service is stopped or paused if (serviceController.Status == ServiceControllerStatus.Stopped) { // Service is stopped, log and return return; } serviceController.Stop(); serviceController.WaitForStatus(ServiceControllerStatus.Stopped, ServiceStopTimeout); } } catch (Exception e) { SetupLogger.LogException(e); throw new Exception(String.Format("Cannot stop the {0} service", serviceName)); } }
private static bool RemoveService(IntPtr hSCManager, string serviceName) { ServiceDeleteStatus status = ServiceConfigurationHandler.StopAndRemoveService(hSCManager, serviceName); bool isRemoved = true; switch (status) { case ServiceDeleteStatus.ServiceDeleteFailed: { isRemoved = false; break; } case ServiceDeleteStatus.ServiceDeleteSuccess: { isRemoved = true; break; } default: { AppAssert.Assert(false, "Unexpected ServiceDeleteStatus returned"); isRemoved = false; break; } } return(isRemoved); }
private static int MapServiceStartModeToNative(ServiceStartMode startMode) { switch (startMode) { case ServiceStartMode.Automatic: { return(NativeMethods.SERVICE_AUTO_START); } case ServiceStartMode.Manual: { return(NativeMethods.SERVICE_DEMAND_START); } case ServiceStartMode.Disabled: { return(NativeMethods.SERVICE_DISABLED); } default: { AppAssert.Assert(false, "Code should not reach here"); return(NativeMethods.SERVICE_DEMAND_START); } } }
/// <summary> /// Sets the failure actions for the specified service /// </summary> /// <param name="serviceName"></param> /// <param name="sfa"></param> internal static void SetFailureActions(string serviceName, ref NativeMethods.SERVICE_FAILURE_ACTIONS sfa) { AppAssert.Assert(null != serviceName, "Null service name passed!"); IntPtr lockHandle = NativeMethods.NullIntPtr; IntPtr scmHandle = NativeMethods.NullIntPtr; IntPtr svcHandle = NativeMethods.NullIntPtr; try { scmHandle = ServiceConfigurationHandler.GetSCMHandle(); //lock the database lockHandle = RepeatLockServiceDatabase(scmHandle); if (NativeMethods.NullIntPtr.Equals(lockHandle)) { SetupLogger.LogError("BackEnd.Configure: Got back NULL service handle!"); int lastWin32Error = System.Runtime.InteropServices.Marshal.GetLastWin32Error(); throw new Exception(String.Format("Setup was unable to configure service {0}", serviceName)); } svcHandle = NativeMethods.OpenService( scmHandle, serviceName, NativeMethods.SERVICE_CHANGE_CONFIG | NativeMethods.SERVICE_START);//since we set restart as a failure option, the handle should have SERVICE_START rights if (NativeMethods.NullIntPtr.Equals(svcHandle)) { //throw exception here SetupLogger.LogInfo("BackEnd.Configure: Got back NULL service handle!"); int lastWin32Error = System.Runtime.InteropServices.Marshal.GetLastWin32Error(); throw new Exception(String.Format("Setup was unable to configure service {0}", serviceName)); } SetupLogger.LogInfo("BackEnd.Configure: Successfully opened {0} service", serviceName); bool success = NativeMethods.ChangeServiceConfig2(svcHandle, NativeMethods.SERVICE_CONFIG_FAILURE_ACTIONS, ref sfa); if (!success) { SetupLogger.LogInfo("BackEnd.Configure: Couldn't modify service description!"); int lastWin32Error = System.Runtime.InteropServices.Marshal.GetLastWin32Error(); throw new Exception(String.Format("Setup was unable to configure service {0}", serviceName)); } } finally { if (!NativeMethods.NullIntPtr.Equals(lockHandle)) { NativeMethods.UnlockServiceDatabase(lockHandle); } if (!NativeMethods.NullIntPtr.Equals(svcHandle)) { NativeMethods.CloseServiceHandle(svcHandle); } if (!NativeMethods.NullIntPtr.Equals(scmHandle)) { NativeMethods.CloseServiceHandle(scmHandle); } } }
public static byte[] GetBinarySid(SecurityIdentifier sid) { // Converts sid to binary form AppAssert.Assert(sid != null); if (sid == null) { throw new ArgumentNullException("sid"); } byte[] sidbuff = new byte[sid.BinaryLength]; sid.GetBinaryForm(sidbuff, 0); return(sidbuff); }
/// <summary> /// Check installed products with Upgrade code /// </summary> /// <param name="upgradeCode"></param> /// <param name="foundAtleastOneVersion"></param> /// <param name="maxInstalledVersion"></param> /// <returns></returns> public static List <string> CheckProductByUpgradeCode(String upgradeCode, ref Version maxInstalledVersion) { //initializations List <string> result = new List <string>(); string productCode = String.Empty; UInt32 error = 0;//for holding return values from native APIs StringBuilder queryVersion = new StringBuilder(SetupConstants.MaximumVersionStringLength); UInt32 bufferLength = (UInt32)queryVersion.Capacity; int index = 0; UInt32 enumRelatedProdResult = 0; StringBuilder productCodeBuffer = new StringBuilder(SetupConstants.MaximumUpgradeCodeLength); enumRelatedProdResult = CMP.Setup.Helpers.NativeMethods.MsiEnumRelatedProducts(upgradeCode, 0, index, productCodeBuffer); while (CMP.Setup.Helpers.NativeMethods.ERROR_SUCCESS == enumRelatedProdResult) { bufferLength = SetupConstants.MaximumVersionStringLength; error = CMP.Setup.Helpers.NativeMethods.MsiGetProductInfo(productCodeBuffer.ToString(), CMP.Setup.Helpers.NativeMethods.INSTALLPROPERTY_VERSIONSTRING, queryVersion, ref bufferLength); if (0 == error) { // success SetupLogger.LogInfo("CheckProductByUpgradeCode : found product with upgrade code {0} with version {1}", upgradeCode, queryVersion.ToString()); Version obtainedVersion = new Version(queryVersion.ToString()); SetupLogger.LogInfo("CheckProductByUpgradeCode: Installed Version {0}", queryVersion.ToString()); int res = obtainedVersion.CompareTo(maxInstalledVersion); AppAssert.Assert(res != 0, "Cannot get two related products with same version! Something must be bad with your code"); if (res > 0) { maxInstalledVersion = obtainedVersion; } productCode = productCodeBuffer.ToString(); if (!result.Contains(productCode)) { result.Add(productCode); } } else { //failed SetupLogger.LogError("CheckProductByUpgradeCode : MsiGetProductInfo failed. Msi Error is {0}", error); } index++; enumRelatedProdResult = CMP.Setup.Helpers.NativeMethods.MsiEnumRelatedProducts(upgradeCode, 0, index, productCodeBuffer); }//end of while return(result); }
public static SecurityIdentifier GetSecurityIdentifier(string accountName) { AppAssert.Assert(!string.IsNullOrEmpty(accountName)); // Check if the string is null or empty - these are not valid account names if (string.IsNullOrEmpty(accountName)) { throw new IdentityNotMappedException(); } // verify that the entered string is a valid account name return(UserAccountHelper.GetSecurityIdentifier(new NTAccount(accountName.Trim()))); }
/// <summary> /// Restarts a particular service /// The method times out if service does not reach "Running" status within the timeout period. /// </summary> /// <param name="serviceName">name of service to start</param> /// <exception cref="ServiceConfigurationException">when service could not be started</exception> public void RestartService(String serviceName) { AppAssert.Assert(null != serviceName, "Null service name passed!"); SetupLogger.LogInfo("ServiceConfigurationHandler.RestartService: Start the service {0}", serviceName); try { this.StartService(serviceName); } catch (Exception serviceNotFoundException) { SetupLogger.LogInfo("ServiceConfigurationHandler.StartService: Start the service, exception {0}", serviceNotFoundException); throw new Exception(String.Format("Cannot start the service. Service name: {0}", serviceName)); } }
/// <summary> /// Attempts to delete the service /// Does nothing if the service doesn't exist /// Throws exception only if the delete actually failed /// </summary> /// <param name="hSCManager"></param> /// <param name="svcName"></param> private static void DeleteService(IntPtr hSCManager, string svcName) { AppAssert.Assert(NativeMethods.NullIntPtr != hSCManager, "Invalid SC Manager handle!"); AppAssert.Assert(null != svcName, "Null service name passed!"); IntPtr hSvc = NativeMethods.NullIntPtr; try { hSvc = NativeMethods.OpenService(hSCManager, svcName, NativeMethods.DELETE); if (NativeMethods.NullIntPtr.Equals(hSvc)) { int lastWin32Error = System.Runtime.InteropServices.Marshal.GetLastWin32Error(); if ( ((NativeMethods.ERROR_SERVICE_DOES_NOT_EXIST != lastWin32Error) && (NativeMethods.ERROR_SERVICE_MARKED_FOR_DELETE != lastWin32Error)) ) { throw new Exception(String.Format("Cannot connect to the service.\nService name: {0}", svcName)); } else { //no exception if the service doesn't exist. return; } } //got a handle to the service... let's try to delete it. bool deleteSvcReturn = NativeMethods.DeleteService(hSvc); if (!deleteSvcReturn) { int lastWin32Error = System.Runtime.InteropServices.Marshal.GetLastWin32Error(); SetupLogger.LogInfo("Couldn't delete service: Doing get last error: {0}.", lastWin32Error); throw new Exception(String.Format("Setup could not delete service {0}", svcName)); } } finally { if (!NativeMethods.NullIntPtr.Equals(hSvc)) { NativeMethods.CloseServiceHandle(hSvc); } SetupLogger.LogInfo("ServiceConfigurationHandler.DeleteService: Doing get last error after closing service handle: {0}", Marshal.GetLastWin32Error()); } }
/// <summary> /// Sets status of the specified service to the specified value /// Ideally this method should throw an exception with the Win32 error value. /// As of now it returns the error code to the caller /// </summary> /// <param name="hSCManager"></param> /// <param name="svcName"></param> /// <param name="serviceStatus"></param> /// <returns></returns> private static int SetServiceStatus(IntPtr hSCManager, string svcName, int serviceStatus) { AppAssert.Assert(NativeMethods.NullIntPtr != hSCManager, "Invalid SC Manager handle!"); AppAssert.Assert(null != svcName, "Null service name passed!"); int returnCode = 0; IntPtr svcHandle = NativeMethods.NullIntPtr; try { svcHandle = NativeMethods.OpenService(hSCManager, svcName, NativeMethods.SERVICE_CHANGE_CONFIG); if (NativeMethods.NullIntPtr.Equals(svcHandle)) { int lastWin32Error = System.Runtime.InteropServices.Marshal.GetLastWin32Error(); throw new Exception(String.Format("Cannot connect to the service.\nService name: {0}", svcName)); } NativeMethods.ChangeServiceConfig( svcHandle, NativeMethods.SERVICE_NO_CHANGE, serviceStatus, NativeMethods.SERVICE_NO_CHANGE, null, null, NativeMethods.NullIntPtr, null, null, null, null ); returnCode = System.Runtime.InteropServices.Marshal.GetLastWin32Error(); return(returnCode); } finally { if (!NativeMethods.NullIntPtr.Equals(svcHandle)) { NativeMethods.CloseServiceHandle(svcHandle); } } }
/// <summary> /// Starts a particular service /// The method times out if service does not reach "Running" status within the timeout period. /// </summary> /// <param name="serviceName">name of service to start</param> /// <param name="machineName">name of computer on which the service resides</param> /// <exception cref="ServiceConfigurationException">when service could not be started</exception> public void StartService(String serviceName, String machineName) { AppAssert.Assert(null != serviceName, "Null service name passed!"); SetupLogger.LogInfo("StartService: Start the service {0}", serviceName); //ConfigurationMessageEvent(this, new ConfigurationMessageEventArgs(String.Format(Resources.StartingService, serviceName))); try { AppAssert.AssertNotNull(serviceName, "serviceName"); ServiceController serviceController = null; try { SetupLogger.LogInfo("Starting service" + serviceName); if (machineName == null) { serviceController = new ServiceController(serviceName); // local host } else { serviceController = new ServiceController(serviceName, machineName); } SetupLogger.LogInfo("StartService: Service {0} status = {1}", serviceName, serviceController.Status); // // Query configurations (credentials and start mode) of service // ServiceConfig serviceConfig = GetServiceConfig(serviceName, machineName); // // Check if the service is disabled or manual and stopped // if (serviceConfig.StartMode == ServiceStartMode.Disabled || (serviceConfig.StartMode == ServiceStartMode.Manual && serviceController.Status == ServiceControllerStatus.Stopped)) { SetupLogger.LogInfo( "StartService : service is disabled or manual and not running"); throw new Exception(String.Format("Cannot start the service. Service name: {0}", serviceName)); } // Check if the service is stopped or paused if (serviceController.Status == ServiceControllerStatus.Running) { // Service is running, log and return SetupLogger.LogInfo("StartService: Service running, check if needs to be restarted"); return; } if (serviceController.Status == ServiceControllerStatus.Stopped) { // Service stopped, Start the service SetupLogger.LogInfo("StartService: Service stopped, Start the service"); serviceController.Start(); } else if (serviceController.Status == ServiceControllerStatus.Paused) { // Service paused, Resume the service SetupLogger.LogInfo("StartService: Service paused, Resume the service"); serviceController.Continue(); } SetupLogger.LogInfo("StartService: Wait for service to start (timeout = {0})", SetupConstants.ServiceStartTimeout); serviceController.WaitForStatus(ServiceControllerStatus.Running, SetupConstants.ServiceStartTimeout); } catch (System.ComponentModel.Win32Exception win32Exception) { // The native service API failed SetupLogger.LogError("StartService: Couldn't start service! Throwing exception: {0}", win32Exception.ToString()); throw new Exception(String.Format("Cannot start the service. Service name: {0}", serviceName)); } catch (InvalidOperationException invalidOperationException) { // The service can not be started SetupLogger.LogError("StartService: Couldn't start service! Throwing exception: {0}", invalidOperationException.ToString()); throw; } catch (System.ServiceProcess.TimeoutException timeoutException) { // There was a timeout SetupLogger.LogError("StartService: Couldn't start service! Throwing exception: {0}", timeoutException.ToString()); throw new Exception(String.Format("Cannot start the service. Service name: {0}", serviceName)); } finally { if (serviceController != null) { serviceController.Close(); } } } catch (Exception serviceNotFoundException) { SetupLogger.LogInfo("ServiceConfigurationHandler.StartService: Start the service, exception {0}", serviceNotFoundException); throw new Exception(String.Format("Cannot start the service. Service name: {0}", serviceName)); } }
/// <summary> /// This method calls into native code for creating a service. /// The service is created with the following standard parameters: /// WIN32_OWN_PROCESS, ERROR_NORMAL, No dependencies /// The handle of the service obtained is closed and not returned /// </summary> /// <param name="hSCManager">Handle to SCM with create service rights</param> /// <param name="svcName">Name of service to create</param> /// <param name="displayName">Localized display name of the service</param> /// <param name="svcDescription">Description of the service</param> /// <param name="binaryPath">Path to the binary</param> /// <param name="dependenciesArray">Array of dependencies</param> /// <param name="serviceStartName">The user account under which the service will run</param> /// <param name="password">Password for the user account</param> /// <param name="autoStart">Should the service be AutoStart on booting the machine</param> /// <param name="interactive">Allow service to interact with desktop or not</param> public static void CreateService(IntPtr hSCManager, string svcName, string displayName, string svcDescription, string binaryPath, string[] dependenciesArray, string serviceStartName, IntPtr password, bool autoStart, bool interactive) { IntPtr hService = NativeMethods.NullIntPtr; try { AppAssert.Assert(null != svcName, "Null service name passed!"); AppAssert.Assert(null != binaryPath, "Null binary path passed!"); string dependenciesString = CreateNativeStringArray(dependenciesArray); int svcType = NativeMethods.SERVICE_WIN32_OWN_PROCESS; if (interactive) { svcType = NativeMethods.SERVICE_WIN32_OWN_PROCESS | NativeMethods.SERVICE_INTERACTIVE_PROCESS; } int svcStartType = NativeMethods.SERVICE_DEMAND_START; if (autoStart) { svcStartType = NativeMethods.SERVICE_AUTO_START; } if (!NativeMethods.NullIntPtr.Equals(password)) //if we are using a password we need to gr ant logon as service permissions to this user. { try { NativeMethods.SetRight(serviceStartName, "SeServiceLogonRight", true); NativeMethods.SetRight(serviceStartName, "SeAssignPrimaryTokenPrivilege", true); } catch (Exception exp) { SetupLogger.LogError("Failed to grant user ( " + serviceStartName + " ) logon as service permissions. Error: " + exp.Message); } } hService = NativeMethods.CreateService( hSCManager, svcName, displayName, NativeMethods.SERVICE_CHANGE_CONFIG, svcType, svcStartType, NativeMethods.SERVICE_ERROR_NORMAL, binaryPath, null, //load order group NativeMethods.NullIntPtr, //[out] tagId dependenciesString, serviceStartName, //Username password ); if (NativeMethods.NullIntPtr.Equals(hService)) { SetupLogger.LogInfo("BackEnd.Configure: Got back NULL service handle!"); int lastWin32Error = System.Runtime.InteropServices.Marshal.GetLastWin32Error(); throw new Exception(String.Format("Cannot create service {0}", svcName)); } NativeMethods.SERVICE_DESCRIPTION svcDesc = new NativeMethods.SERVICE_DESCRIPTION(); svcDesc.lpDescription = svcDescription; bool success = NativeMethods.ChangeServiceConfig2(hService, NativeMethods.SERVICE_CONFIG_DESCRIPTION, ref svcDesc); if (!success) { SetupLogger.LogInfo("BackEnd.Configure: Couldn't modify service description!"); int lastWin32Error = System.Runtime.InteropServices.Marshal.GetLastWin32Error(); throw new Exception(String.Format("Cannot create service {0}", svcName)); } // Set service SID type. This is required for any service that has a firewall rule targeted for that specific service. NativeMethods.SERVICE_SID_INFO svcSidType = new NativeMethods.SERVICE_SID_INFO(); svcSidType.serviceSidType = NativeMethods.SERVICE_SID_TYPE.SERVICE_SID_TYPE_UNRESTRICTED; success = NativeMethods.ChangeServiceConfig2(hService, NativeMethods.SERVICE_CONFIG_SERVICE_SID_INFO, ref svcSidType); if (!success) { SetupLogger.LogInfo("BackEnd.Configure: Couldn't modify service SID type!"); int lastWin32Error = System.Runtime.InteropServices.Marshal.GetLastWin32Error(); throw new Exception(String.Format("Cannot create service {0}", svcName)); } } catch (Exception e) { throw e; } finally { if (NativeMethods.NullIntPtr != hService) { NativeMethods.CloseServiceHandle(hService); } } }