Пример #1
0
    public unsafe void ChangeServiceConfig2_ErrorsProperly()
    {
        Assert.False(ChangeServiceConfig2(SafeServiceHandle.Null, ServiceInfoLevel.SERVICE_CONFIG_DESCRIPTION, null));

        string rebootMessage = "Rebooting now.";

        fixed(char *pRebootMessage = rebootMessage.ToCharArrayWithNullTerminator())
        {
            var actions = new SC_ACTION[]
            {
                new SC_ACTION {
                    Type = SC_ACTION_TYPE.SC_ACTION_REBOOT, Delay = 2000
                },
                new SC_ACTION {
                    Type = SC_ACTION_TYPE.SC_ACTION_REBOOT, Delay = 2000
                },
            };

            fixed(SC_ACTION *pActions = &actions[0])
            {
                var failureActions = new SERVICE_FAILURE_ACTIONS
                {
                    lpRebootMsg = pRebootMessage,
                    cActions    = 2,
                    lpsaActions = pActions,
                };

                Assert.False(ChangeServiceConfig2(SafeServiceHandle.Null, ServiceInfoLevel.SERVICE_CONFIG_FAILURE_ACTIONS_FLAG, &failureActions));
            }
        }
    }
Пример #2
0
        private void SetFailureActions(IntPtr serviceHandle)
        {
            UInt32 dwBytesNeeded;

            // Determine the buffer size needed
            QueryServiceConfig2(serviceHandle, SERVICE_CONFIG_FAILURE_ACTIONS, IntPtr.Zero, 0, out dwBytesNeeded);

            var ptr = Marshal.AllocHGlobal((int)dwBytesNeeded);

            QueryServiceConfig2(serviceHandle, SERVICE_CONFIG_FAILURE_ACTIONS, ptr, dwBytesNeeded, out dwBytesNeeded);
            var failureActions = new SERVICE_FAILURE_ACTIONS();

            Marshal.PtrToStructure(ptr, failureActions);

            // Report it.
            ResetPeriod    = (UInt32)failureActions.dwResetPeriod;
            FailureProgram = failureActions.lpCommand;

            var offset = 0;

            for (var i = 0; i < failureActions.cActions; i++)
            {
                var type = (FailureAction)Marshal.ReadInt32(failureActions.lpsaActions, offset);
                offset += sizeof(Int32);
                var delay = (UInt32)Marshal.ReadInt32(failureActions.lpsaActions, offset);
                offset += sizeof(Int32);

                if (i == 0)
                {
                    FirstFailure = type;
                }
                else if (i == 1)
                {
                    SecondFailure = type;
                }
                else if (i == 2)
                {
                    ThirdFailure = type;
                }

                switch (type)
                {
                case (FailureAction.RunCommand):
                    RunCommandDelay = delay;
                    break;

                case (FailureAction.Reboot):
                    RebootDelay = delay;
                    break;

                case (FailureAction.Restart):
                    RestartDelay = delay;
                    break;
                }
            }

            Marshal.FreeHGlobal(ptr);
        }
Пример #3
0
        /// <summary>
        /// Changes the service failure action information
        /// </summary>
        /// <param name="serviceName">The service to look for</param>
        /// <param name="resetPeriodInDays">The reset period (in days)</param>
        /// <param name="rebootMessage">The message displayed on reboot</param>
        /// <param name="commandLine">Program command line</param>
        /// <param name="actions">Ordered list of actions to add to the service configuration</param>
        public static void SetServiceInformation(string serviceName, int resetPeriodInDays, string rebootMessage, string commandLine, ServiceFailureActionType[] actions)
        {
            // Get a valid service handle
            IntPtr serviceHandle = LookupServiceHandle(serviceName, scope.Modify);

            // marshal the actions
            ServiceFailureAction action = new ServiceFailureAction();
            IntPtr lpsaActions          = Marshal.AllocHGlobal(Marshal.SizeOf(action) * actions.Length);
            // Marshal.StructureToPtr(action, lpsaActions, false);
            IntPtr nextAction = lpsaActions;

            for (int i = 0; i < actions.Length; i++)
            {
                action       = new ServiceFailureAction();
                action.Type  = actions[i];
                action.Delay = (UInt32)TimeSpan.FromMinutes(1).TotalMilliseconds;

                Marshal.StructureToPtr(action, nextAction, false);
                nextAction = (IntPtr)(nextAction.ToInt64() + Marshal.SizeOf(action));
            }


            // now put it all in one struct
            SERVICE_FAILURE_ACTIONS failureActions = new SERVICE_FAILURE_ACTIONS();

            failureActions.dwResetPeriod = (int)TimeSpan.FromDays(resetPeriodInDays).TotalSeconds;
            failureActions.lpRebootMsg   = rebootMessage;
            failureActions.lpCommand     = commandLine;
            failureActions.cActions      = actions.Length;
            failureActions.lpsaActions   = lpsaActions;

            IntPtr lpInfo = Marshal.AllocHGlobal(Marshal.SizeOf(failureActions));

            Marshal.StructureToPtr(failureActions, lpInfo, true);

            // do the change
            bool success = ChangeServiceConfig2(serviceHandle, SERVICE_CONFIG_FAILURE_ACTIONS, lpInfo);

            //int errorcode = GetLatError();
            // clean up
            Marshal.FreeHGlobal(lpInfo);
            Marshal.FreeHGlobal(lpsaActions);
            if (serviceHandle != IntPtr.Zero)
            {
                CloseServiceHandle(serviceHandle);
            }

            if (false == success)
            {
                throw new System.Runtime.InteropServices.ExternalException(string.Format("Cannot set ServiceConfig. Last Error: {0}.", Marshal.GetLastWin32Error()));
            }
        }
    public static void SetRecoveryOptions(String serviceName, int action = SC_ACTION_RESTART, int pDaysToResetFailureCount = 0)
    {
        ServiceController svcController  = new ServiceController(serviceName);
        IntPtr            _ServiceHandle = svcController.ServiceHandle.DangerousGetHandle();

        int NUM_ACTIONS = 3;

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

        arrActions[index++] = action;
        arrActions[index++] = DELAY_IN_MILLISECONDS;
        arrActions[index++] = action;
        arrActions[index++] = DELAY_IN_MILLISECONDS;
        arrActions[index++] = action;
        arrActions[index++] = DELAY_IN_MILLISECONDS;

        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;
        }
    }
Пример #5
0
        /// <summary>
        /// Configures the service to auto-restart on failure
        /// </summary>
        public void SetRestartOnFailure(int restartAttempts, int restartDelay, int resetFailuresDelay)
        {
            SC_ACTION[] actions =
                new SC_ACTION[3]
            {
                new SC_ACTION
                {
                    Delay = Math.Max(0, Math.Min(int.MaxValue, restartDelay)),
                    Type  = SC_ACTION_TYPE.SC_ACTION_RESTART
                },
                new SC_ACTION
                {
                    Delay = Math.Max(0, Math.Min(int.MaxValue, restartDelay)),
                    Type  = SC_ACTION_TYPE.SC_ACTION_RESTART
                },
                new SC_ACTION
                {
                    Delay = Math.Max(0, Math.Min(int.MaxValue, restartDelay)),
                    Type  = SC_ACTION_TYPE.SC_ACTION_RESTART
                },
            };

            for (int i = Math.Max(0, restartAttempts); i < actions.Length; i++)
            {
                actions[i] = new SC_ACTION {
                    Delay = 0, Type = SC_ACTION_TYPE.SC_ACTION_NONE
                }
            }
            ;

            GCHandle hdata = GCHandle.Alloc(actions, GCHandleType.Pinned);

            try
            {
                SERVICE_FAILURE_ACTIONS cfg = new SERVICE_FAILURE_ACTIONS();
                cfg.dwResetPeriod = Math.Max(-1, Math.Min(int.MaxValue, resetFailuresDelay));
                cfg.lpRebootMsg   = cfg.lpCommand = IntPtr.Zero;
                cfg.cActions      = actions.Length;
                cfg.lpsaActions   = hdata.AddrOfPinnedObject();

                SetServiceConfig(SERVICE_CONFIG_INFO.FAILURE_ACTIONS, cfg);
            }
            finally
            {
                hdata.Free();
            }
        }
Пример #6
0
        /// <summary>
        /// Look up the Failure action information for a service
        /// </summary>
        /// <param name="serviceName">The service to look up</param>
        /// <returns>Service Failure Action information</returns>
        public static ServiceInformation GetSericeInformation(string serviceName)
        {
            UInt32 dwBytesNeeded;

            // Get a valid service handle
            IntPtr serviceHandle = LookupServiceHandle(serviceName, scope.Query);

            // Determine the buffer size needed
            bool sucess = QueryServiceConfig2(serviceHandle, SERVICE_CONFIG_FAILURE_ACTIONS, IntPtr.Zero, 0, out dwBytesNeeded);

            IntPtr ptr = Marshal.AllocHGlobal((int)dwBytesNeeded);

            sucess = QueryServiceConfig2(serviceHandle, SERVICE_CONFIG_FAILURE_ACTIONS, ptr, dwBytesNeeded, out dwBytesNeeded);

            if (false == sucess)
            {
                throw new System.Runtime.InteropServices.ExternalException(string.Format("Cannot find  SERVICE_FAILURE_ACTIONS struct. Last Error: {0}.", Marshal.GetLastWin32Error()));
            }

            SERVICE_FAILURE_ACTIONS failureActions = new SERVICE_FAILURE_ACTIONS();

            Marshal.PtrToStructure(ptr, failureActions);

            ServiceInformation serviceConfigInformation = new ServiceInformation((UInt32)failureActions.dwResetPeriod, failureActions.lpRebootMsg, failureActions.lpCommand, failureActions.cActions);

            int offset = 0;

            for (int i = 0; i < failureActions.cActions; i++)
            {
                ServiceFailureAction action = new ServiceFailureAction();
                action.Type  = (ServiceFailureActionType)Marshal.ReadInt32(failureActions.lpsaActions, offset);
                offset      += sizeof(Int32);
                action.Delay = (UInt32)Marshal.ReadInt32(failureActions.lpsaActions, offset);
                offset      += sizeof(Int32);
                serviceConfigInformation.Actions[i] = action;
            }

            // clean up
            Marshal.FreeHGlobal(ptr);
            if (serviceHandle != IntPtr.Zero)
            {
                CloseServiceHandle(serviceHandle);
            }

            return(serviceConfigInformation);
        }
    public static void SetRecoveryOptions(String serviceName, int pDaysToResetFailureCount = 0)
    {
        ServiceController svcController = new ServiceController(serviceName);
        IntPtr _ServiceHandle = svcController.ServiceHandle.DangerousGetHandle();

        int NUM_ACTIONS = 3;
        int[] arrActions = new int[NUM_ACTIONS * 2];
        int index = 0;
        arrActions[index++] = SC_ACTION_RESTART;
        arrActions[index++] = DELAY_IN_MILLISECONDS;
        arrActions[index++] = (int)SC_ACTION_RESTART;
        arrActions[index++] = DELAY_IN_MILLISECONDS;
        arrActions[index++] = (int)SC_ACTION_RESTART;
        arrActions[index++] = DELAY_IN_MILLISECONDS;

        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 static void SetRecoveryOptions(IntPtr service, SC_ACTION[] actions, bool applyOnErrorStop = false, uint failureResetSeconds = 3600, string command = null, string rebootMsg = null)
        {
            var recovery      = new SERVICE_FAILURE_ACTIONS();
            var defaultAction = new SC_ACTION(SC_ACTION_TYPE.SC_ACTION_NONE, 0);

            recovery.cActions = 3;
            var size = Marshal.SizeOf(typeof(SC_ACTION));

            recovery.lpsaActions = Marshal.AllocHGlobal((System.Int32)(size * recovery.cActions));
            for (int ix = 0; ix < recovery.cActions; ++ix)
            {
                var action = (actions != null && ix < actions.Length) ? actions[ix] : defaultAction;
                Marshal.StructureToPtr(action, IntPtr.Add(recovery.lpsaActions, ix * size), false);
            }
            recovery.dwResetPeriod = failureResetSeconds;   // time to reset failure counter, seconds
            recovery.lpCommand     = command;               // command to execute
            recovery.lpRebootMsg   = rebootMsg;             // reboot message (we don't use it)

            try
            {
                if (!ChangeServiceConfig2(service, SERVICE_INFO_LEVEL.FAILURE_ACTIONS, ref recovery))
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }
            }
            finally
            {
                // clean up so no memory leak
                // Note, does nothing when given IntPtr.Zero
                Marshal.FreeHGlobal(recovery.lpsaActions);
            }

            // Set whether or not to apply recovery actions if service stops itself with non-0 Win32ExitCode
            var failure_actions_flag = new SERVICE_FAILURE_ACTIONS_FLAG();

            failure_actions_flag.fFailureActionsOnNonCrashFailures = applyOnErrorStop;
            ChangeServiceConfig2(service, SERVICE_INFO_LEVEL.FAILURE_ACTIONS_FLAG, ref failure_actions_flag);
        }
Пример #9
0
 internal static extern bool ChangeServiceConfig2(SafeHandle serviceHandle, SERVICE_CONFIG_INFOLEVEL infoLevel, ref SERVICE_FAILURE_ACTIONS serviceDesc);
Пример #10
0
        private bool SetRestartOnFailureRecovery(List <FailureAction> FailureActions, String RunProgram, String RebootMessage)
        {
            // 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)
                {
                    EventLog.WriteEntry(serviceInstaller.ServiceName, Properties.Resources.ScmHndlInfo, EventLogEntryType.Error);
                    return(false);
                }

                // Lock the Service Database
                svcLock = LockServiceDatabase(scmHndl);

                if (svcLock.ToInt32() <= 0)
                {
                    EventLog.WriteEntry(serviceInstaller.ServiceName, Properties.Resources.SvcLockInfo, EventLogEntryType.Error);
                    return(false);
                }

                // Open the service
                svcHndl = OpenService(scmHndl, serviceInstaller.ServiceName, SERVICE_ALL_ACCESS);

                if (svcHndl.ToInt32() <= 0)
                {
                    EventLog.WriteEntry(serviceInstaller.ServiceName, Properties.Resources.SvcHndlInfo, EventLogEntryType.Error);
                    return(false);
                }

                // 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.

                // 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[FailureActions.Count * 2];

                int currInd = 0;
                foreach (FailureAction fa in FailureActions)
                {
                    actions[currInd]   = (int)fa.Type;
                    actions[++currInd] = fa.Delay;
                    currInd++;
                }

                // Need to pack 8 bytes per struct
                tmpBuf = Marshal.AllocHGlobal(FailureActions.Count * 8);

                // Move array into marshallable pointer
                Marshal.Copy(actions, 0, tmpBuf, FailureActions.Count * 2);

                // Set the SERVICE_FAILURE_ACTIONS struct
                SERVICE_FAILURE_ACTIONS sfa = new SERVICE_FAILURE_ACTIONS();

                sfa.cActions      = FailureActions.Count;
                sfa.dwResetPeriod = SERVICE_NO_CHANGE;
                sfa.lpCommand     = RunProgram;
                sfa.lpRebootMsg   = RebootMessage;
                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(Properties.Resources.AccessDenied);
                    }
                }

                // Free the memory
                Marshal.FreeHGlobal(tmpBuf); tmpBuf = IntPtr.Zero;

                EventLog.WriteEntry(serviceInstaller.ServiceName, Properties.Resources.Successfully, EventLogEntryType.Information);
            }
            catch (Exception ex)
            {
                EventLog.WriteEntry(serviceInstaller.ServiceName, ex.Message, EventLogEntryType.Error);

                return(false);
            }
            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;
                }
            }

            return(true);
        }
        /// <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;
                }
            }
        }
        public static void SetServiceRecoveryOptions(
            string serviceName, [NotNull] ServiceRecoveryOptions recoveryOptions)
        {
            if (recoveryOptions == null)
            {
                throw new ArgumentNullException("recoveryOptions");
            }

            bool requiresShutdownPriveleges =
                recoveryOptions.FirstFailureAction == ServiceRecoveryAction.RestartComputer ||
                recoveryOptions.SecondFailureAction == ServiceRecoveryAction.RestartComputer ||
                recoveryOptions.SubsequentFailureAction == ServiceRecoveryAction.RestartComputer;

            if (requiresShutdownPriveleges)
            {
                GrantShutdownPrivileges();
            }

            int actionCount         = 3;
            var restartServiceAfter = (uint)TimeSpan.FromMinutes(
                recoveryOptions.RestartServiceWaitMinutes).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();
                failureActions.dwResetPeriod = (int)TimeSpan.FromDays(recoveryOptions.ResetFailureCountWaitDays).TotalSeconds;
                failureActions.cActions      = (uint)actionCount;
                failureActions.lpRebootMsg   = recoveryOptions.RestartSystemMessage;

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

                string command = recoveryOptions.RunProgramCommand;
                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.Dispose();
                }

                //log.Debug(m => m("Done setting service recovery options."));
            }
        }
        public void InstallService(string serviceName, string serviceDisplayName, string logonAccount, string logonPassword)
        {
            Trace.Entering();

            string agentServiceExecutable = Path.Combine(IOUtil.GetBinPath(), WindowsServiceControlManager.WindowsServiceControllerName);
            IntPtr scmHndl = IntPtr.Zero;
            IntPtr svcHndl = IntPtr.Zero;
            IntPtr tmpBuf  = IntPtr.Zero;
            IntPtr svcLock = IntPtr.Zero;

            try
            {
                Trace.Verbose(StringUtil.Format("Trying to open SCManager."));
                scmHndl = OpenSCManager(null, null, ServiceManagerRights.AllAccess);
                if (scmHndl.ToInt64() <= 0)
                {
                    throw new Exception(StringUtil.Loc("FailedToOpenSCM"));
                }

                Trace.Verbose(StringUtil.Format("Opened SCManager. Trying to create service {0}", serviceName));
                svcHndl = CreateService(scmHndl,
                                        serviceName,
                                        serviceDisplayName,
                                        ServiceRights.AllAccess,
                                        SERVICE_WIN32_OWN_PROCESS,
                                        ServiceBootFlag.AutoStart,
                                        ServiceError.Normal,
                                        agentServiceExecutable,
                                        null,
                                        IntPtr.Zero,
                                        null,
                                        logonAccount,
                                        logonPassword);
                if (svcHndl.ToInt64() <= 0)
                {
                    throw new InvalidOperationException(StringUtil.Loc("OperationFailed", nameof(CreateService), GetLastError()));
                }

                //invoke the service with special argument, that tells it to register an event log trace source (need to run as an admin)
                using (var processInvoker = HostContext.CreateService <IProcessInvoker>())
                {
                    processInvoker.ExecuteAsync(string.Empty, agentServiceExecutable, "init", null, default(System.Threading.CancellationToken)).GetAwaiter().GetResult();
                }

                _term.WriteLine(StringUtil.Loc("ServiceInstalled", serviceName));

                //set recovery option to restart on failure.
                ArrayList failureActions = new ArrayList();
                //first failure, we will restart the service right away.
                failureActions.Add(new FailureAction(RecoverAction.Restart, 0));
                //second failure, we will restart the service after 1 min.
                failureActions.Add(new FailureAction(RecoverAction.Restart, 60000));
                //subsequent failures, we will restart the service after 1 min
                failureActions.Add(new FailureAction(RecoverAction.Restart, 60000));

                // Lock the Service Database
                svcLock = LockServiceDatabase(scmHndl);
                if (svcLock.ToInt64() <= 0)
                {
                    throw new Exception(StringUtil.Loc("FailedToLockServiceDB"));
                }

                int[] actions = new int[failureActions.Count * 2];
                int   currInd = 0;
                foreach (FailureAction fa in failureActions)
                {
                    actions[currInd]   = (int)fa.Type;
                    actions[++currInd] = fa.Delay;
                    currInd++;
                }

                // Need to pack 8 bytes per struct
                tmpBuf = Marshal.AllocHGlobal(failureActions.Count * 8);
                // Move array into marshallable pointer
                Marshal.Copy(actions, 0, tmpBuf, failureActions.Count * 2);

                // Set the SERVICE_FAILURE_ACTIONS struct
                SERVICE_FAILURE_ACTIONS sfa = new SERVICE_FAILURE_ACTIONS();
                sfa.cActions      = failureActions.Count;
                sfa.dwResetPeriod = SERVICE_NO_CHANGE;
                sfa.lpCommand     = String.Empty;
                sfa.lpRebootMsg   = String.Empty;
                sfa.lpsaActions   = tmpBuf.ToInt64();

                // Call the ChangeServiceFailureActions() abstraction of ChangeServiceConfig2()
                bool result = ChangeServiceFailureActions(svcHndl, SERVICE_CONFIG_FAILURE_ACTIONS, ref sfa);
                //Check the return
                if (!result)
                {
                    int       lastErrorCode  = (int)GetLastError();
                    Exception win32exception = new Win32Exception(lastErrorCode);
                    if (lastErrorCode == ReturnCode.ERROR_ACCESS_DENIED)
                    {
                        throw new SecurityException(StringUtil.Loc("AccessDeniedSettingRecoveryOption"), win32exception);
                    }
                    else
                    {
                        throw win32exception;
                    }
                }
                else
                {
                    _term.WriteLine(StringUtil.Loc("ServiceRecoveryOptionSet", serviceName));
                }

                _term.WriteLine(StringUtil.Loc("ServiceConfigured", serviceName));
            }
            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;
                }
            }
        }
Пример #14
0
        public static void InstallAndStart(string serviceName, string displayName, string fileName)
        {
            IntPtr scm = OpenSCManager(ScmAccessRights.AllAccess);

            try
            {
                IntPtr service = OpenService(scm, serviceName, ServiceAccessRights.AllAccess);

                if (service == IntPtr.Zero)
                    service = CreateService(scm, serviceName, displayName, ServiceAccessRights.AllAccess, SERVICE_WIN32_OWN_PROCESS, ServiceBootFlag.AutoStart, ServiceError.Normal, fileName, null, IntPtr.Zero, null, null, null);

                if (service == IntPtr.Zero)
                    throw new ApplicationException("Failed to install service.");

                // set restart options

                try
                {
                    SC_ACTION action = new SC_ACTION();
                    action.Type = SC_ACTION_TYPE.RestartService;
                    action.Delay = (uint)TimeSpan.FromSeconds(10).TotalMilliseconds;

                    IntPtr lpsaActions = Marshal.AllocHGlobal(Marshal.SizeOf(action) * 2);
                    if (lpsaActions == IntPtr.Zero)
                    {
                        throw new Exception(String.Format("Unable to allocate memory for service action, error was: 0x{0:X}", Marshal.GetLastWin32Error()));
                    }

                    Marshal.StructureToPtr(action, lpsaActions, false);

                    IntPtr nextAction = (IntPtr)(lpsaActions.ToInt64() + Marshal.SizeOf(action));
                    action.Type = SC_ACTION_TYPE.RestartService;

                    Marshal.StructureToPtr(action, nextAction, false);
                    action.Delay = (uint)TimeSpan.FromSeconds(30).TotalMilliseconds;

                    SERVICE_FAILURE_ACTIONS failureActions = new SERVICE_FAILURE_ACTIONS();
                    failureActions.dwResetPeriod = (int)TimeSpan.FromDays(1).TotalSeconds;
                    failureActions.lpRebootMsg = "";
                    failureActions.lpCommand = "";
                    failureActions.cActions = 2;
                    failureActions.lpsaActions = lpsaActions;

                    IntPtr lpInfo = Marshal.AllocHGlobal(Marshal.SizeOf(failureActions));
                    if (lpInfo == IntPtr.Zero)
                    {
                        Marshal.FreeHGlobal(lpsaActions);
                        throw new Exception(String.Format("Unable to allocate memory, error was: 0x{0:X}", Marshal.GetLastWin32Error()));
                    }

                    Marshal.StructureToPtr(failureActions, lpInfo, false);

                    if (!ChangeServiceConfig2(service, 2, lpInfo))
                    {
                        Marshal.FreeHGlobal(lpInfo);
                        Marshal.FreeHGlobal(lpsaActions);
                        int err = Marshal.GetLastWin32Error();
                        if (err == 1072)
                        {
                            throw new Exception(String.Format("Can't set service config.  Service " + serviceName + " is marked for delete. Restart machine to clear this up.", err));
                        }
                        else
                        {
                            throw new Exception(String.Format("Error setting service config, error was: {0}", err));
                        }
                    }

                    Marshal.FreeHGlobal(lpInfo);
                    Marshal.FreeHGlobal(lpsaActions);

                }
                finally
                {
                }

                try
                {
                    StartService(service);
                }
                finally
                {
                    CloseServiceHandle(service);
                }
            }
            finally
            {
                CloseServiceHandle(scm);
            }
        }
Пример #15
0
        public static ServiceRecoveryOptions GetServiceRecoveryOptions(
            string serviceName)
        {
            ThrowHelper.ThrowArgumentNullIfNull(serviceName, "serviceName");
            ThrowHelper.ThrowArgumentOutOfRangeIfEmpty(serviceName, "serviceName");

            log.Debug(m => m("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();
                recoveryOptions.DaysToResetFailAcount = (int)
                                                        TimeSpan.FromSeconds(config.dwResetPeriod).TotalDays;
                recoveryOptions.RebootMessage            = config.lpRebootMsg;
                recoveryOptions.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(m => m("Done getting service recovery options."));
            }


            return(recoveryOptions);
        }
Пример #16
0
        /// <summary>
        /// Changes the service failure action information
        /// </summary>
        /// <param name="serviceName">The service to look for</param>
        /// <param name="resetPeriodInDays">The reset period (in days)</param>
        /// <param name="rebootMessage">The message displayed on reboot</param>
        /// <param name="commandLine">Program command line</param>
        /// <param name="actions">Ordered list of actions to add to the service configuration</param>
        public static void SetServiceInformation(string serviceName, int resetPeriodInDays, string rebootMessage, string commandLine, ServiceFailureActionType[] actions)
        {
            // Get a valid service handle
            IntPtr serviceHandle = LookupServiceHandle(serviceName, scope.Modify);

            // marshal the actions
            ServiceFailureAction action = new ServiceFailureAction();
            IntPtr lpsaActions = Marshal.AllocHGlobal(Marshal.SizeOf(action) * actions.Length);
            // Marshal.StructureToPtr(action, lpsaActions, false);
            IntPtr nextAction = lpsaActions;

            for (int i = 0; i < actions.Length; i++)
            {
                action = new ServiceFailureAction();
                action.Type = actions[i];
                action.Delay = (UInt32)TimeSpan.FromMinutes(1).TotalMilliseconds;

                Marshal.StructureToPtr(action, nextAction, false);
                nextAction = (IntPtr)(nextAction.ToInt64() + Marshal.SizeOf(action));
            }

            // now put it all in one struct
            SERVICE_FAILURE_ACTIONS failureActions = new SERVICE_FAILURE_ACTIONS();
            failureActions.dwResetPeriod = (int)TimeSpan.FromDays(resetPeriodInDays).TotalSeconds;
            failureActions.lpRebootMsg = rebootMessage;
            failureActions.lpCommand = commandLine;
            failureActions.cActions = actions.Length;
            failureActions.lpsaActions = lpsaActions;

            IntPtr lpInfo = Marshal.AllocHGlobal(Marshal.SizeOf(failureActions));
            Marshal.StructureToPtr(failureActions, lpInfo, true);

            // do the change
            bool success = ChangeServiceConfig2(serviceHandle, SERVICE_CONFIG_FAILURE_ACTIONS, lpInfo);
            //int errorcode = GetLatError();
            // clean up
            Marshal.FreeHGlobal(lpInfo);
            Marshal.FreeHGlobal(lpsaActions);
            if (serviceHandle != IntPtr.Zero)
            {
                CloseServiceHandle(serviceHandle);
            }

            if (false == success)
            {
                throw new System.Runtime.InteropServices.ExternalException(string.Format("Cannot set ServiceConfig. Last Error: {0}.", Marshal.GetLastWin32Error()));
            }
        }
Пример #17
0
        /// <summary>
        /// Look up the Failure action information for a service
        /// </summary>
        /// <param name="serviceName">The service to look up</param>
        /// <returns>Service Failure Action information</returns>
        public static ServiceInformation GetSericeInformation(string serviceName)
        {
            UInt32 dwBytesNeeded;

            // Get a valid service handle
            IntPtr serviceHandle = LookupServiceHandle(serviceName, scope.Query);

            // Determine the buffer size needed
            bool sucess = QueryServiceConfig2(serviceHandle, SERVICE_CONFIG_FAILURE_ACTIONS, IntPtr.Zero, 0, out dwBytesNeeded);

            IntPtr ptr = Marshal.AllocHGlobal((int)dwBytesNeeded);
            sucess = QueryServiceConfig2(serviceHandle, SERVICE_CONFIG_FAILURE_ACTIONS, ptr, dwBytesNeeded, out dwBytesNeeded);

            if (false == sucess)
            {
                throw new System.Runtime.InteropServices.ExternalException(string.Format("Cannot find  SERVICE_FAILURE_ACTIONS struct. Last Error: {0}.", Marshal.GetLastWin32Error()));
            }

            SERVICE_FAILURE_ACTIONS failureActions = new SERVICE_FAILURE_ACTIONS();
            Marshal.PtrToStructure(ptr, failureActions);

            ServiceInformation serviceConfigInformation = new ServiceInformation((UInt32)failureActions.dwResetPeriod, failureActions.lpRebootMsg, failureActions.lpCommand, failureActions.cActions);

            int offset = 0;
            for (int i = 0; i < failureActions.cActions; i++)
            {
                ServiceFailureAction action = new ServiceFailureAction();
                action.Type = (ServiceFailureActionType)Marshal.ReadInt32(failureActions.lpsaActions, offset);
                offset += sizeof(Int32);
                action.Delay = (UInt32)Marshal.ReadInt32(failureActions.lpsaActions, offset);
                offset += sizeof(Int32);
                serviceConfigInformation.Actions[i] = action;
            }

            // clean up
            Marshal.FreeHGlobal(ptr);
            if (serviceHandle != IntPtr.Zero)
            {
                CloseServiceHandle(serviceHandle);
            }

            return serviceConfigInformation;
        }
Пример #18
0
        public static void InstallAndStart(string serviceName, string displayName, string fileName)
        {
            IntPtr scm = OpenSCManager(ScmAccessRights.AllAccess);

            try
            {
                IntPtr service = OpenService(scm, serviceName, ServiceAccessRights.AllAccess);

                if (service == IntPtr.Zero)
                {
                    service = CreateService(scm, serviceName, displayName, ServiceAccessRights.AllAccess, SERVICE_WIN32_OWN_PROCESS, ServiceBootFlag.AutoStart, ServiceError.Normal, fileName, null, IntPtr.Zero, null, null, null);
                }

                if (service == IntPtr.Zero)
                {
                    throw new ApplicationException("Failed to install service.");
                }

                // set restart options

                try
                {
                    SC_ACTION action = new SC_ACTION();
                    action.Type  = SC_ACTION_TYPE.RestartService;
                    action.Delay = (uint)TimeSpan.FromSeconds(10).TotalMilliseconds;

                    IntPtr lpsaActions = Marshal.AllocHGlobal(Marshal.SizeOf(action) * 2);
                    if (lpsaActions == IntPtr.Zero)
                    {
                        throw new Exception(String.Format("Unable to allocate memory for service action, error was: 0x{0:X}", Marshal.GetLastWin32Error()));
                    }

                    Marshal.StructureToPtr(action, lpsaActions, false);

                    IntPtr nextAction = (IntPtr)(lpsaActions.ToInt64() + Marshal.SizeOf(action));
                    action.Type = SC_ACTION_TYPE.RestartService;

                    Marshal.StructureToPtr(action, nextAction, false);
                    action.Delay = (uint)TimeSpan.FromSeconds(30).TotalMilliseconds;

                    SERVICE_FAILURE_ACTIONS failureActions = new SERVICE_FAILURE_ACTIONS();
                    failureActions.dwResetPeriod = (int)TimeSpan.FromDays(1).TotalSeconds;
                    failureActions.lpRebootMsg   = "";
                    failureActions.lpCommand     = "";
                    failureActions.cActions      = 2;
                    failureActions.lpsaActions   = lpsaActions;

                    IntPtr lpInfo = Marshal.AllocHGlobal(Marshal.SizeOf(failureActions));
                    if (lpInfo == IntPtr.Zero)
                    {
                        Marshal.FreeHGlobal(lpsaActions);
                        throw new Exception(String.Format("Unable to allocate memory, error was: 0x{0:X}", Marshal.GetLastWin32Error()));
                    }

                    Marshal.StructureToPtr(failureActions, lpInfo, false);

                    if (!ChangeServiceConfig2(service, 2, lpInfo))
                    {
                        Marshal.FreeHGlobal(lpInfo);
                        Marshal.FreeHGlobal(lpsaActions);
                        int err = Marshal.GetLastWin32Error();
                        if (err == 1072)
                        {
                            throw new Exception(String.Format("Can't set service config.  Service " + serviceName + " is marked for delete. Restart machine to clear this up.", err));
                        }
                        else
                        {
                            throw new Exception(String.Format("Error setting service config, error was: {0}", err));
                        }
                    }

                    Marshal.FreeHGlobal(lpInfo);
                    Marshal.FreeHGlobal(lpsaActions);
                }
                finally
                {
                }

                try
                {
                    StartService(service);
                }
                finally
                {
                    CloseServiceHandle(service);
                }
            }
            finally
            {
                CloseServiceHandle(scm);
            }
        }
        ////////////////////////////////////////////////////////////////////////////////////
        // 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

        }
Пример #20
0
 public static extern bool ChangeServiceConfig2A(
     int hService, InfoLevel dwInfoLevel,
     [MarshalAs(UnmanagedType.Struct)] ref SERVICE_FAILURE_ACTIONS lpInfo);
Пример #21
0
 public static extern int ChangeServiceFailureActions(
     Win32ServiceControlHandle hService,
     INFO_LEVEL dwInfoLevel,
     [MarshalAs(UnmanagedType.Struct)] ref SERVICE_FAILURE_ACTIONS lpInfo);
        public static void SetServiceRecoveryOptions(
            string serviceName, [NotNull] ServiceRecoveryOptions recoveryOptions)
        {
            if (recoveryOptions == null)
                throw new ArgumentNullException("recoveryOptions");

            bool requiresShutdownPriveleges =
                recoveryOptions.FirstFailureAction == ServiceRecoveryAction.RestartComputer ||
                recoveryOptions.SecondFailureAction == ServiceRecoveryAction.RestartComputer ||
                recoveryOptions.SubsequentFailureAction == ServiceRecoveryAction.RestartComputer;
            if (requiresShutdownPriveleges)
                GrantShutdownPrivileges();

            int actionCount = 3;
            var restartServiceAfter = (uint)TimeSpan.FromMinutes(
                                                                 recoveryOptions.RestartServiceWaitMinutes).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();
                failureActions.dwResetPeriod = (int)TimeSpan.FromDays(recoveryOptions.ResetFailureCountWaitDays).TotalSeconds;
                failureActions.cActions = (uint)actionCount;
                failureActions.lpRebootMsg = recoveryOptions.RestartSystemMessage;

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

                string command = recoveryOptions.RunProgramCommand;
                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.Dispose();
                }

                //log.Debug(m => m("Done setting service recovery options."));
            }
        }
Пример #23
0
 ChangeServiceFailureActions(IntPtr hService, int dwInfoLevel,
                             [MarshalAs(UnmanagedType.Struct)] ref SERVICE_FAILURE_ACTIONS lpInfo);
 public static extern bool ChangeServiceFailureActions(IntPtr hService, int dwInfoLevel, ref SERVICE_FAILURE_ACTIONS lpInfo);
Пример #25
0
        public static void ServiceQuery(string host, string svcname)
        {
            bool   success;
            IntPtr dbHandle;
            IntPtr svcHandle;
            IntPtr ptr;
            UInt32 dwBytesNeeded;
            QUERY_SERVICE_CONFIG    qconf;
            SERVICE_FAILURE_ACTIONS qfail;
            int failStructOffset;
            QUERY_SERVICE_STATUS_PROCESS qproc;


            if (host == "")
            {
                dbHandle = OpenSCManager(null, null, SC_MANAGER_ALL_ACCESS);
            }
            else
            {
                dbHandle = OpenSCManager(host, null, SC_MANAGER_ALL_ACCESS);
            }

            svcHandle = OpenService(dbHandle, svcname, SERVICE_QUERY_CONFIG);
            if (svcHandle == IntPtr.Zero)
            {
                throw new System.Runtime.InteropServices.ExternalException("Couldn't open the service");
            }

            ptr     = Marshal.AllocHGlobal(4096);
            success = QueryServiceConfig(svcHandle, ptr, 4096, out dwBytesNeeded);

            if (success == false)
            {
                throw new System.Runtime.InteropServices.ExternalException("Couldn't query the service");
            }

            qconf = new QUERY_SERVICE_CONFIG(); // copy ptr to query_service_config struct
            Marshal.PtrToStructure(ptr, qconf);

            Marshal.FreeHGlobal(ptr); //reset states
            success       = false;
            dwBytesNeeded = 0;

            success = QueryServiceConfig2(svcHandle, SERVICE_CONFIG_FAILURE_ACTIONS, IntPtr.Zero, 0, out dwBytesNeeded); //the first call of this function will get the number of bytes needed for the struct
            ptr     = Marshal.AllocHGlobal((int)dwBytesNeeded);
            success = QueryServiceConfig2(svcHandle, SERVICE_CONFIG_FAILURE_ACTIONS, ptr, dwBytesNeeded, out dwBytesNeeded);

            qfail = new SERVICE_FAILURE_ACTIONS();
            Marshal.PtrToStructure(ptr, qfail);
            SC_ACTION[] actions = new SC_ACTION[qfail.cActions];
            failStructOffset = 0;

            Marshal.FreeHGlobal(ptr); //reset states
            success       = false;
            dwBytesNeeded = 0;

            success = QueryServiceStatusEx(svcHandle, SC_STATUS_PROCESS_INFO, IntPtr.Zero, 0, out dwBytesNeeded);//again first call gets buffer size required for struct
            ptr     = Marshal.AllocHGlobal((int)dwBytesNeeded);
            success = QueryServiceStatusEx(svcHandle, SC_STATUS_PROCESS_INFO, ptr, dwBytesNeeded, out dwBytesNeeded);

            qproc = new QUERY_SERVICE_STATUS_PROCESS();
            Marshal.PtrToStructure(ptr, qproc);

            Marshal.FreeHGlobal(ptr); //reset states
            success       = false;
            dwBytesNeeded = 0;

            for (int i = 0; i < qfail.cActions; i++)
            {
                SC_ACTION act = new SC_ACTION();
                act.type          = Marshal.ReadInt32(qfail.lpsaActions, failStructOffset);
                failStructOffset += sizeof(Int32);
                act.dwDelay       = (UInt32)Marshal.ReadInt32(qfail.lpsaActions, failStructOffset);
                failStructOffset += sizeof(Int32);
                actions[i]        = act;
            }


            Console.WriteLine("Service Name:\t" + svcname);
            Console.WriteLine("Service Type:\t" + qproc.dwServiceType);
            Console.WriteLine("State:\t" + qproc.dwCurrentState);
            Console.WriteLine("PID:\t" + qproc.dwProcessId);
            Console.WriteLine();
            Console.WriteLine("Start Type:\t" + qconf.dwStartType);
            Console.WriteLine("Error Control:\t" + qconf.dwErrorControl);
            Console.WriteLine("BinPath:\t" + qconf.lpBinaryPathName);
            Console.WriteLine("Display Name:\t" + qconf.lpDisplayName);
            Console.WriteLine("Dependencies:\t" + qconf.lpDependencies);
            Console.WriteLine("Reset Period:\t" + qfail.dwResetPeriod);
            Console.WriteLine("Reboot Message:\t" + qfail.lpRebootMsg);
            Console.WriteLine("Failure Command Line:\t" + qfail.lpCommand);
            Console.WriteLine("Failure Actions:\t");
            for (int i = 0; i < actions.Length; i++)
            {
                Console.Write("{0} -- Delay = {1}", actions[i].type, actions[i].dwDelay);
            }
        }
Пример #26
0
        ////////////////////////////////////////////////////////////////////////////////////
        // 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 = 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
        }
Пример #27
0
        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.");
            }
        }
        void SetRestartOnFailure(string serviceName)
        {
            const int  actionCount = 2;
            const uint delay       = 60000;

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

            try
            {
                service   = OpenService(serviceName, SERVICE_ACCESS_RIGHTS.SERVICE_CHANGE_CONFIG | SERVICE_ACCESS_RIGHTS.SERVICE_START);
                actionPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SC_ACTION)) * actionCount);

                var action1 = new SC_ACTION
                {
                    Type  = SC_ACTION_TYPE.SC_ACTION_RESTART,
                    Delay = delay
                };

                Marshal.StructureToPtr(action1, actionPtr, false);

                var action2 = new SC_ACTION
                {
                    Type  = SC_ACTION_TYPE.SC_ACTION_NONE,
                    Delay = delay
                };
                Marshal.StructureToPtr(action2, (IntPtr)((long)actionPtr + Marshal.SizeOf(typeof(SC_ACTION))), false);

                var failureActions = new SERVICE_FAILURE_ACTIONS
                {
                    dwResetPeriod = 0,
                    cActions      = actionCount,
                    lpsaActions   = actionPtr
                };

                failureActionsPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SERVICE_FAILURE_ACTIONS)));
                Marshal.StructureToPtr(failureActions, failureActionsPtr, false);
                var changeResult = ChangeServiceConfig2(
                    service,
                    ServiceConfig2InfoLevel.SERVICE_CONFIG_FAILURE_ACTIONS,
                    failureActionsPtr);

                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)
                {
                    CloseServiceHandle(service);
                }
            }
        }
 public static extern bool ChangeServiceConfig2(IntPtr hService, SERVICE_INFO_LEVEL dwInfoLevel, [MarshalAs(UnmanagedType.Struct)] ref SERVICE_FAILURE_ACTIONS lpInfo);