public void SetRecoveryOptions()
        {
            uint      delay         = 60000;
            SC_ACTION pFirstFailure = new SC_ACTION();

            pFirstFailure.Type  = SC_ACTION_TYPE.SC_ACTION_RESTART;
            pFirstFailure.Delay = delay;
            SC_ACTION pSecondFailure = new SC_ACTION();

            pSecondFailure.Type  = SC_ACTION_TYPE.SC_ACTION_RESTART;
            pSecondFailure.Delay = delay;
            SC_ACTION pSubsequentFailures = new SC_ACTION();

            pSubsequentFailures.Type  = SC_ACTION_TYPE.SC_ACTION_RESTART;
            pSubsequentFailures.Delay = delay;
            int pDaysToResetFailureCount = 0;
            int NUM_ACTIONS = 3;

            int[] arrActions = new int[NUM_ACTIONS * 2];
            int   index      = 0;

            arrActions[index++] = (int)pFirstFailure.Type;
            arrActions[index++] = (int)pFirstFailure.Delay;
            arrActions[index++] = (int)pSecondFailure.Type;
            arrActions[index++] = (int)pSecondFailure.Delay;
            arrActions[index++] = (int)pSubsequentFailures.Type;
            arrActions[index++] = (int)pSubsequentFailures.Delay;

            IntPtr tmpBuff = Marshal.AllocHGlobal(NUM_ACTIONS * 8);

            try
            {
                Marshal.Copy(arrActions, 0, tmpBuff, NUM_ACTIONS * 2);
                SERVICE_FAILURE_ACTIONS sfa = new SERVICE_FAILURE_ACTIONS();
                sfa.cActions      = 3;
                sfa.dwResetPeriod = pDaysToResetFailureCount;
                sfa.lpCommand     = null;
                sfa.lpRebootMsg   = null;
                sfa.lpsaActions   = new IntPtr(tmpBuff.ToInt32());

                bool success = ChangeServiceFailureActions(_ServiceHandle, SERVICE_CONFIG_FAILURE_ACTIONS, ref sfa);
                if (!success)
                {
                    if (GetLastError() == ERROR_ACCESS_DENIED)
                    {
                        throw new Exception("Access denied while setting failure actions.");
                    }
                    else
                    {
                        throw new Exception("Unknown error while setting failure actions.");
                    }
                }
            }
            finally
            {
                Marshal.FreeHGlobal(tmpBuff);
                tmpBuff = IntPtr.Zero;
            }
        }
        public bool HasRestartOnFailure(string serviceName)
        {
            const int bufferSize = 1024 * 8;

            IntPtr service   = IntPtr.Zero;
            IntPtr bufferPtr = IntPtr.Zero;
            bool   result    = false;

            try
            {
                // Open the service
                service = OpenService(serviceName, ServiceAccessRights.SERVICE_QUERY_CONFIG);

                int dwBytesNeeded = 0;

                // Allocate memory for struct
                bufferPtr = Marshal.AllocHGlobal(bufferSize);
                int queryResult = NativeMethods.QueryServiceConfig2(
                    service,
                    ServiceConfig2InfoLevel.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));

                // Determine whether the service is set to auto restart
                if (config.cActions != 0)
                {
                    SC_ACTION action = (SC_ACTION)Marshal.PtrToStructure(config.lpsaActions, typeof(SC_ACTION));
                    result = (action.Type == SC_ACTION_TYPE.SC_ACTION_RESTART);
                }

                return(result);
            }
            finally
            {
                // Clean up
                if (bufferPtr != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(bufferPtr);
                }

                if (service != IntPtr.Zero)
                {
                    NativeMethods.CloseServiceHandle(service);
                }
            }
        }
 private static extern bool ChangeServiceFailureActions(IntPtr hService, int dwInfoLevel, [MarshalAs(UnmanagedType.Struct)] ref SERVICE_FAILURE_ACTIONS lpInfo);
        public void SetRestartOnFailure(string serviceName)
        {
            const int  actionCount = 2;
            const uint delay       = 60000;

            IntPtr service           = IntPtr.Zero;
            IntPtr failureActionsPtr = IntPtr.Zero;
            IntPtr actionPtr         = IntPtr.Zero;

            try
            {
                // Open the service
                service = OpenService(serviceName,
                                      ServiceAccessRights.SERVICE_CHANGE_CONFIG |
                                      ServiceAccessRights.SERVICE_START);

                // Allocate memory for the individual actions
                actionPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SC_ACTION)) * actionCount);

                // Set up the restart action
                SC_ACTION action1 = new SC_ACTION();
                action1.Type  = SC_ACTION_TYPE.SC_ACTION_RESTART;
                action1.Delay = delay;
                Marshal.StructureToPtr(action1, actionPtr, false);

                // Set up the restart action
                SC_ACTION action2 = new SC_ACTION();
                action2.Type  = SC_ACTION_TYPE.SC_ACTION_RESTART;
                action2.Delay = delay;
                Marshal.StructureToPtr(action2, (IntPtr)((Int64)actionPtr + Marshal.SizeOf(typeof(SC_ACTION))), false);

                //// Set up the restart action
                //SC_ACTION action3 = new SC_ACTION();
                //action3.Type = SC_ACTION_TYPE.SC_ACTION_RESTART;
                //action3.Delay = delay;
                //Marshal.StructureToPtr(action3, (IntPtr)((Int64)actionPtr + Marshal.SizeOf(typeof(SC_ACTION)) * 2), false);

                // Set up the failure actions
                SERVICE_FAILURE_ACTIONS failureActions = new SERVICE_FAILURE_ACTIONS();
                failureActions.dwResetPeriod = 0;
                failureActions.cActions      = actionCount;
                failureActions.lpsaActions   = actionPtr;

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

                // Make the change
                int changeResult = NativeMethods.ChangeServiceConfig2(
                    service,
                    ServiceConfig2InfoLevel.SERVICE_CONFIG_FAILURE_ACTIONS,
                    failureActionsPtr);

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

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

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