public static ServiceRecoveryOptions FromConfiguration(RecoveryOptionsElement recoveryOptionsElement)
 {
     var recoveryOptions = new ServiceRecoveryOptions
                               {
                                   FirstFailureAction = recoveryOptionsElement.FirstFailureAction,
                                   SecondFailureAction = recoveryOptionsElement.SecondFailureAction,
                                   SubsequentFailureActions = recoveryOptionsElement.SubsequentFailureActions,
                                   DaysToResetFailAcount = recoveryOptionsElement.DaysToResetFailAcount,
                                   CommandToLaunchOnFailure = recoveryOptionsElement.CommandToLaunchOnFailure,
                                   MinutesToRestartService = recoveryOptionsElement.MinutesToRestartService,
                                   RebootMessage = recoveryOptionsElement.RebootMessage
                               };
     recoveryOptions.Validate();
     return recoveryOptions;
 }
 public bool Equals(ServiceRecoveryOptions other)
 {
     if (ReferenceEquals(null, other)) return false;
     if (ReferenceEquals(this, other)) return true;
     return Equals(other.FirstFailureAction, FirstFailureAction) && Equals(other.SecondFailureAction, SecondFailureAction) && Equals(other.SubsequentFailureActions, SubsequentFailureActions) && other.DaysToResetFailAcount == DaysToResetFailAcount && other.MinutesToRestartService == MinutesToRestartService && Equals(other.RebootMessage, RebootMessage) && Equals(other.CommandToLaunchOnFailure, CommandToLaunchOnFailure);
 }
        public static void SetServiceRecoveryOptions(
            string serviceName,
            ServiceRecoveryOptions recoveryOptions)
        {
            Exceptions.ThrowHelper.ThrowArgumentNullIfNull(serviceName, "serviceName");
            Exceptions.ThrowHelper.ThrowArgumentOutOfRangeIfEmpty(serviceName, "serviceName");

            Log.Debug("Setting service recovery options...");

            bool requiresShutdownPriveleges =
                recoveryOptions.FirstFailureAction == ServiceRecoveryAction.RestartTheComputer ||
                recoveryOptions.SecondFailureAction == ServiceRecoveryAction.RestartTheComputer ||
                recoveryOptions.SubsequentFailureActions == ServiceRecoveryAction.RestartTheComputer;
            if (requiresShutdownPriveleges)
            {
                GrantShutdownPrivileges();
            }

            const int actionCount = 3;
            var restartServiceAfter = (uint)TimeSpan.FromMinutes(
                recoveryOptions.MinutesToRestartService).TotalMilliseconds;

            IntPtr failureActionsPointer = IntPtr.Zero;
            IntPtr actionPointer = IntPtr.Zero;

            ServiceController controller = null;
            try
            {
                // Open the service
                controller = new ServiceController(serviceName);

                // Set up the failure actions
                var failureActions = new SERVICE_FAILURE_ACTIONS
                                         {
                                             dwResetPeriod = (int)TimeSpan.FromDays(recoveryOptions.DaysToResetFailAcount).TotalSeconds,
                                             cActions = actionCount,
                                             lpRebootMsg = recoveryOptions.RebootMessage
                                         };

                // allocate memory for the individual actions
                actionPointer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SC_ACTION)) * actionCount);
                ServiceRecoveryAction[] actions = { recoveryOptions.FirstFailureAction,
                                                    recoveryOptions.SecondFailureAction,
                                                    recoveryOptions.SubsequentFailureActions };
                for (int i = 0; i < actions.Length; i++)
                {
                    ServiceRecoveryAction action = actions[i];
                    var scAction = GetScAction(action, restartServiceAfter);
                    Marshal.StructureToPtr(scAction, (IntPtr)((Int64)actionPointer + (Marshal.SizeOf(typeof(SC_ACTION))) * i), false);
                }
                failureActions.lpsaActions = actionPointer;

                string command = recoveryOptions.CommandToLaunchOnFailure;
                if (command != null)
                {
                    failureActions.lpCommand = command;
                }

                failureActionsPointer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SERVICE_FAILURE_ACTIONS)));
                Marshal.StructureToPtr(failureActions, failureActionsPointer, false);

                // Make the change
                bool success = ChangeServiceConfig2(
                    controller.ServiceHandle.DangerousGetHandle(),
                    SERVICE_CONFIG_FAILURE_ACTIONS,
                    failureActionsPointer);

                // Check that the change occurred
                if (!success)
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error(), "Unable to change the Service configuration.");
                }
            }
            finally
            {
                if (failureActionsPointer != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(failureActionsPointer);
                }

                if (actionPointer != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(actionPointer);
                }

                if (controller != null)
                {
                    controller.Close();
                }

                Log.Debug("Done setting service recovery options.");
            }
        }
        public static ServiceRecoveryOptions GetServiceRecoveryOptions(string serviceName)
        {
            Exceptions.ThrowHelper.ThrowArgumentNullIfNull(serviceName, "serviceName");
            Exceptions.ThrowHelper.ThrowArgumentOutOfRangeIfEmpty(serviceName, "serviceName");

            Log.Debug("Getting service recovery options...");

            // 8KB is the largest buffer supported by QueryServiceConfig2
            const int bufferSize = 1024 * 8;

            IntPtr bufferPtr = IntPtr.Zero;

            ServiceRecoveryOptions recoveryOptions;
            ServiceController controller = null;
            try
            {
                // Open the service
                controller = new ServiceController(serviceName);

                uint dwBytesNeeded;

                // Allocate memory for struct
                bufferPtr = Marshal.AllocHGlobal(bufferSize);
                int queryResult = QueryServiceConfig2(
                    controller.ServiceHandle.DangerousGetHandle(),
                    SERVICE_CONFIG_FAILURE_ACTIONS,
                    bufferPtr,
                    bufferSize,
                    out dwBytesNeeded);

                if (queryResult == 0)
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error(), "Unable to query the Service configuration.");
                }

                // Cast the buffer to a QUERY_SERVICE_CONFIG struct
                SERVICE_FAILURE_ACTIONS config =
                    (SERVICE_FAILURE_ACTIONS)Marshal.PtrToStructure(bufferPtr, typeof(SERVICE_FAILURE_ACTIONS));

                recoveryOptions = new ServiceRecoveryOptions
                                      {
                                          DaysToResetFailAcount = (int) TimeSpan.FromSeconds(config.dwResetPeriod).TotalDays,
                                          RebootMessage = config.lpRebootMsg,
                                          CommandToLaunchOnFailure = config.lpCommand
                                      };

                int actionCount = config.cActions;
                if (actionCount != 0)
                {
                    uint millisecondsToRestartService = 0;
                    SC_ACTION[] actions = new SC_ACTION[actionCount];
                    for (int i = 0; i < config.cActions; i++)
                    {
                        SC_ACTION action = (SC_ACTION)Marshal.PtrToStructure(
                            (IntPtr)(config.lpsaActions.ToInt32() + (Marshal.SizeOf(typeof(SC_ACTION)) * i)),
                            typeof(SC_ACTION));
                        actions[i] = action;
                        millisecondsToRestartService = action.Delay;
                    }

                    recoveryOptions.FirstFailureAction = GetServiceRecoveryAction(actions[0]);
                    recoveryOptions.SecondFailureAction = GetServiceRecoveryAction(actions[1]);
                    recoveryOptions.SubsequentFailureActions = GetServiceRecoveryAction(actions[2]);
                    recoveryOptions.MinutesToRestartService =
                        (int)TimeSpan.FromMilliseconds(millisecondsToRestartService).TotalMinutes;
                }
            }
            finally
            {
                // Clean up
                if (bufferPtr != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(bufferPtr);
                }

                if (controller != null)
                {
                    controller.Close();
                }

                Log.Debug("Done getting service recovery options.");
            }

            return recoveryOptions;
        }
 public CandidateWindowsServiceInfo()
 {
     StartMode = StartMode.Manual;
     _servicesDependedOn = new List<string>();
     RecoveryOptions = new ServiceRecoveryOptions();
 }