示例#1
0
        public bool ConfigureRestartActions(string serviceName)
        {
            /* Note: For now, this function is hard-coded to set recovery actions
             *       that will restart the service, waiting 60s between restart
             *       attempts. It could be enhanced in the future, to take these
             *       actions as parameters, and configure accordingly.
             */

            IntPtr scManagerHandle     = IntPtr.Zero;
            IntPtr actionsBuffer       = IntPtr.Zero;
            IntPtr scManagerLockHandle = IntPtr.Zero;
            IntPtr serviceHandle       = IntPtr.Zero;

            try
            {
                if (ServiceExists(serviceName) == false)
                {
                    _logger.Log($"ERROR: Service does not exist [{serviceName}].");
                    return(false);
                }

                scManagerHandle = NativeMethods.OpenSCManagerA(
                    null, null,
                    NativeMethods.ServiceControlManagerType.SC_MANAGER_ALL_ACCESS);

                if (scManagerHandle == IntPtr.Zero)
                {
                    _logger.Log("ERROR: Unable to open service control manager.");
                    return(false);
                }

                scManagerLockHandle = NativeMethods.LockServiceDatabase(scManagerHandle);

                if (scManagerLockHandle == IntPtr.Zero)
                {
                    _logger.Log("ERROR: Unable to lock service control manager database.");
                    return(false);
                }

                serviceHandle = NativeMethods.OpenServiceA(
                    scManagerHandle,
                    serviceName,
                    NativeMethods.ACCESS_TYPE.SERVICE_ALL_ACCESS);

                if (serviceHandle == IntPtr.Zero)
                {
                    _logger.Log("ERROR: Unable to open specified service [" + serviceName + "].");
                    return(false);
                }

                NativeMethods.SC_ACTION[]             scActions = new NativeMethods.SC_ACTION[3];
                NativeMethods.SERVICE_FAILURE_ACTIONS serviceFailureActions; // Reference: https://docs.microsoft.com/en-us/windows/win32/api/winsvc/ns-winsvc-service_failure_actionsa
                serviceFailureActions.dwResetPeriod = 24 * 3600;             // The time after which to reset the failure count to zero if there are no failures, in seconds.
                serviceFailureActions.lpRebootMsg   = "";                    // No broadcast message.
                serviceFailureActions.lpCommand     = null;                  // If this value is NULL, the command is unchanged.
                serviceFailureActions.cActions      = scActions.Length;      // (3) failure actions.
                scActions[0].Delay        = 60000;
                scActions[0].SCActionType = NativeMethods.SC_ACTION_TYPE.SC_ACTION_RESTART;
                scActions[1].Delay        = 60000;
                scActions[1].SCActionType = NativeMethods.SC_ACTION_TYPE.SC_ACTION_RESTART;
                scActions[2].Delay        = 60000;
                scActions[2].SCActionType = NativeMethods.SC_ACTION_TYPE.SC_ACTION_RESTART;

                actionsBuffer = Marshal.AllocHGlobal(Marshal.SizeOf(new NativeMethods.SC_ACTION()) * 3);
                NativeMethods.CopyMemory(actionsBuffer, scActions, Marshal.SizeOf(new NativeMethods.SC_ACTION()) * 3);
                serviceFailureActions.lpsaActions = actionsBuffer;

                bool configSuccess = NativeMethods.ChangeServiceConfig2A(
                    serviceHandle,
                    NativeMethods.InfoLevel.SERVICE_CONFIG_FAILURE_ACTIONS,
                    ref serviceFailureActions);

                if (!configSuccess)
                {
                    _logger.Log("ERROR: Unable to configure service failure actions [ChangeServiceConfig2A=" +
                                Marshal.GetLastWin32Error().ToString() + "].");
                    return(false);
                }
            }
            catch (Exception e)
            {
                _logger.Log(e, "Failed to configure service failure actions.");
            }
            finally
            {
                if (actionsBuffer != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(actionsBuffer);
                }

                if (serviceHandle != IntPtr.Zero)
                {
                    NativeMethods.CloseServiceHandle(serviceHandle);
                }

                if (scManagerLockHandle != IntPtr.Zero)
                {
                    NativeMethods.UnlockServiceDatabase(scManagerLockHandle);
                }

                if (scManagerHandle != IntPtr.Zero)
                {
                    NativeMethods.CloseServiceHandle(scManagerHandle);
                }
            }

            return(true);
        }
示例#2
0
        /// <summary>
        /// Create the engine service and start it
        /// </summary>
        public static void ConfigureCMPWorkerService(ServiceConfigurationHandler serviceConfigurationHandler)
        {
            AppAssert.AssertNotNull(serviceConfigurationHandler, "serviceConfigurationHandler");

            string installPath = SetupConstants.GetServerInstallPath();

            //attempt to remove services first.
            //this will ignore errors of service does not exist and service marked for deletion
            //If service is marked for deletion, then exception will be thrown at create time as
            //we will be unable to create the service.
            //reason:
            //1. Keeps the code path of Install and Repair same
            //2. Handles corner case of service already existing in Install mode
            //3. Repairs the configuration of the service if broken

            IntPtr hSCManager = NativeMethods.NullIntPtr;
            IntPtr password   = NativeMethods.NullIntPtr;

            try
            {
                hSCManager = ServiceConfigurationHandler.GetSCMHandle();

                //TODO: Handle rollback if exception is thrown
                ServiceConfigurationHandler.StopAndRemoveService(hSCManager, SetupConstants.EngineServiceName);

                //construct paths to service binaries
                string servicePathEngine = PathHelper.QuoteString(installPath + @"MSIT\CmpWorkerService\" + SetupConstants.EngineServiceBinary);
                SetupLogger.LogInfo("BackEnd.Configure: Engine Service path is : {0}", servicePathEngine);

                //Get account
                string userAccountName   = null;
                bool   runasLocalAccount = SetupInputs.Instance.FindItem(SetupInputTags.CmpServiceLocalAccountTag);
                if (!runasLocalAccount)
                {
                    userAccountName = UserAccountHelper.GetVmmServiceDomainAccount();
                    password        = Marshal.SecureStringToGlobalAllocUnicode(SetupInputs.Instance.FindItem(SetupInputTags.CmpServiceUserPasswordTag));
                }

                //create engine service
                ServiceConfigurationHandler.CreateService(
                    hSCManager,
                    SetupConstants.EngineServiceName,
                    Resources.EngineServiceDisplayName,
                    Resources.EngineServiceDescription,
                    servicePathEngine,
                    null,   // dependent services
                    userAccountName,
                    password: password,
                    autoStart: true,
                    interactive: false);

                //set failure actions for VMMService
                NativeMethods.SERVICE_FAILURE_ACTIONS sfa = new NativeMethods.SERVICE_FAILURE_ACTIONS();
                NativeMethods.SC_ACTION[]             sca = new NativeMethods.SC_ACTION[SetupConstants.ServiceActionsCount + 1];
                for (int i = 0; i < SetupConstants.ServiceActionsCount; i++)
                {
                    sca[i].Delay = SetupConstants.ServiceRestartDelay;
                    sca[i].Type  = NativeMethods.SC_ACTION_TYPE.SC_ACTION_RESTART;
                }
                sca[SetupConstants.ServiceActionsCount].Delay = 0;
                sca[SetupConstants.ServiceActionsCount].Type  = NativeMethods.SC_ACTION_TYPE.SC_ACTION_NONE;

                IntPtr unmanagedStructArray = NativeMethods.NullIntPtr;
                try
                {
                    unmanagedStructArray = GetUnmanagedStructArray(sca);

                    sfa.sc_Action     = unmanagedStructArray;
                    sfa.cActions      = SetupConstants.ServiceActionsCount + 1;
                    sfa.dwResetPeriod = SetupConstants.ServiceResetPeriod;
                    sfa.lpCommand     = null;
                    sfa.lpRebootMsg   = null;

                    //set service failure actions for engine service
                    ServiceConfigurationHandler.SetFailureActions(SetupConstants.EngineServiceName, ref sfa);

                    //ConfigurationProgressEvent(this, new EventArgs());
                }
                finally
                {
                    if (NativeMethods.NullIntPtr != unmanagedStructArray)
                    {
                        Marshal.FreeHGlobal(unmanagedStructArray);
                    }
                }
            }
            finally
            {
                if (!NativeMethods.NullIntPtr.Equals(hSCManager))
                {
                    NativeMethods.CloseServiceHandle(hSCManager);
                }
                if (!NativeMethods.NullIntPtr.Equals(password))
                {
                    Marshal.ZeroFreeGlobalAllocUnicode(password);
                }
            }
        }