private void DoCreateService(ServiceControlManager serviceControlManager, ServiceDefinition serviceDefinition, bool startImmediately)
        {
            using (ServiceHandle svc = serviceControlManager.CreateService(serviceDefinition.ServiceName, serviceDefinition.DisplayName, serviceDefinition.BinaryPath, ServiceType.Win32OwnProcess,
                                                                           serviceDefinition.AutoStart ? ServiceStartType.AutoStart : ServiceStartType.StartOnDemand, serviceDefinition.ErrorSeverity, serviceDefinition.Credentials))
            {
                string description = serviceDefinition.Description;
                if (!string.IsNullOrEmpty(description))
                {
                    svc.SetDescription(description);
                }

                ServiceFailureActions serviceFailureActions = serviceDefinition.FailureActions;
                if (serviceFailureActions != null)
                {
                    svc.SetFailureActions(serviceFailureActions);
                    svc.SetFailureActionFlag(serviceDefinition.FailureActionsOnNonCrashFailures);
                }

                if (serviceDefinition.AutoStart && serviceDefinition.DelayedAutoStart)
                {
                    svc.SetDelayedAutoStartFlag(true);
                }

                if (startImmediately)
                {
                    svc.Start();
                }
            }
        }
Exemplo n.º 2
0
        private static void InstallService(string ServiceName, string DisplayName, string Description, ServiceStartType StartType, bool Immediate,
                                           ServiceFailureActions FailureActions, Win32ServiceCredentials Credentials)
        {
            ServiceInstaller host = new ServiceInstaller(ServiceName);
            int i;

            switch (i = host.Install(DisplayName, Description, StartType, Immediate, FailureActions, Credentials))
            {
            case 0:
                Console.Out.WriteLine("Service successfully installed. Service start is pending.");
                break;

            case 1:
                Console.Out.WriteLine("Service successfully installed and started.");
                break;

            case 2:
                Console.Out.WriteLine("Service registration successfully updated. Service start is pending.");
                break;

            case 3:
                Console.Out.WriteLine("Service registration successfully updated. Service started.");
                break;

            default:
                throw new Exception("Unexpected installation result: " + i.ToString());
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Installs the service.
        /// </summary>
        /// <param name="DisplayName">Service display name.</param>
        /// <param name="Description">Service description.</param>
        /// <param name="StartType">How the service should be started.</param>
        /// <param name="StartImmediately">If the service should be started immediately.</param>
        /// <param name="FailureActions">Service failure actions.</param>
        /// <param name="Credentials">Credentials to use when running service.</param>
        /// <returns>
        /// Return code:
        ///
        /// 0: Installed, not started.
        /// 1: Installed, started.
        /// 2: Updated, not started.
        /// 3: Updated, started.
        /// </returns>
        /// <exception cref="Exception">If service could not be installed.</exception>
        public int Install(string DisplayName, string Description, ServiceStartType StartType, bool StartImmediately,
                           ServiceFailureActions FailureActions, Win32ServiceCredentials Credentials)
        {
            string Path = Assembly.GetExecutingAssembly().Location.Replace(".dll", ".exe");

            try
            {
                using (ServiceControlManager mgr = ServiceControlManager.Connect(null, null, ServiceControlManagerAccessRights.All))
                {
                    if (mgr.TryOpenService(this.serviceName, ServiceControlAccessRights.All, out ServiceHandle existingService,
                                           out Win32Exception errorException))
                    {
                        using (existingService)
                        {
                            existingService.ChangeConfig(DisplayName, Path, ServiceType.Win32OwnProcess,
                                                         StartType, ErrorSeverity.Normal, Credentials);

                            if (!string.IsNullOrEmpty(Description))
                            {
                                existingService.SetDescription(Description);
                            }

                            if (!(FailureActions is null))
                            {
                                existingService.SetFailureActions(FailureActions);
                                existingService.SetFailureActionFlag(true);
                            }
                            else
                            {
                                existingService.SetFailureActionFlag(false);
                            }

                            if (StartImmediately)
                            {
                                existingService.Start(throwIfAlreadyRunning: false);
                                return(3);
                            }
                            else
                            {
                                return(2);
                            }
                        }
 public static extern bool ChangeServiceFailureActions(IntPtr hService, int dwInfoLevel,
                                                       [MarshalAs(UnmanagedType.Struct)]
                                                       ref ServiceFailureActions lpInfo);
Exemplo n.º 5
0
        protected async override Task RemoteConfigureAsync(IRemoteOperationExecutionContext context)
        {
            if (this.Template == null)
            {
                throw new InvalidOperationException("Template is not set.");
            }

            this.LogDebug($"Looking for service \"{this.Template.Name}\"...");

            bool userWasChanged = false;

            using (var service = GetOrCreateService(!context.Simulation))
            {
                if (this.Template.Exists)
                {
                    if (service == null)
                    {
                        // simulation
                        this.LogInformation($"{this.Template.Name} service does not exist.");
                        return;
                    }

                    if (this.Template.DisplayName != null && this.Template.DisplayName != service.DisplayName)
                    {
                        service.DisplayName = this.Template.DisplayName;
                    }

                    if (this.Template.Description != null && this.Template.Description != service.Description)
                    {
                        service.Description = this.Template.Description;
                    }

                    if (this.Template.Path != null && this.Template.Path != service.FileName)
                    {
                        service.FileName = this.Template.Path;
                    }

                    if (this.Template.StartMode != null && this.Template.StartMode != service.StartMode)
                    {
                        service.StartMode = this.Template.StartMode.Value;
                    }

                    if (this.Template.DelayedStart != null && this.Template.DelayedStart != service.DelayedStart)
                    {
                        service.DelayedStart = this.Template.DelayedStart.Value;
                    }

                    if (this.Template.UserAccount != null && this.Template.UserAccount != service.UserAccountName)
                    {
                        userWasChanged = true;
                        service.SetUserAccount(this.Template.UserAccount, this.Template.Password);
                    }

                    if (this.Template.Dependencies != null && !this.Template.Dependencies.ToHashSet().SetEquals(service.Dependencies))
                    {
                        service.SetDependencies(this.Template.Dependencies.ToList());
                    }

                    if (FailureActionsChanged(service))
                    {
                        var timeDelay = this.Template.RestartDelay != null?TimeSpan.FromMinutes(this.Template.RestartDelay.Value) : TimeSpan.Zero;

                        var newFailureActions = new ServiceFailureActions(
                            resetPeriod: this.Template.RestartDelay,
                            rebootMessage: this.Template.RebootMessage,
                            command: this.Template.OnFailureProgramPath,
                            actions: new[]
                        {
                            new ServiceControllerAction(this.Template.OnFirstFailure ?? ServiceControllerActionType.None, timeDelay),
                            new ServiceControllerAction(this.Template.OnSecondFailure ?? ServiceControllerActionType.None, timeDelay),
                            new ServiceControllerAction(this.Template.OnSubsequentFailures ?? ServiceControllerActionType.None, timeDelay)
                        });

                        service.FailureActions = newFailureActions;
                    }

                    if (this.Template.Status != null)
                    {
                        if (!IsPending(this.Template.Status.Value))
                        {
                            await this.EnsureServiceStatusAsync(service.Name, this.Template.Status.Value);
                        }
                        else
                        {
                            this.LogWarning($"Specified service status \"{this.Template.Status.Value}\" is invalid, therefore the service's status will not be modified.");
                        }
                    }
                }
                else
                {
                    if (service == null)
                    {
                        this.LogWarning("Service doesn't exist.");
                        return;
                    }

                    this.LogDebug("Service exists. Stopping before deleting...");
                    await this.EnsureServiceStatusAsync(service.Name, ServiceControllerStatus.Stopped);

                    this.LogDebug($"Deleting {service.Name} service...");
                    service.Delete();
                }
            }

            if (userWasChanged && this.Template.Status == ServiceControllerStatus.Running)
            {
                this.LogDebug("The service user was changed, therefore the service will be restarted.");
                await this.EnsureServiceStatusAsync(this.Template.Name, ServiceControllerStatus.Stopped);

                await this.EnsureServiceStatusAsync(this.Template.Name, ServiceControllerStatus.Running);
            }
        }
 private void WhenATestServiceIsCreatedOrUpdated(string testServiceName, bool autoStart, bool startImmediately, ServiceFailureActions serviceFailureActions = null, bool failureActionsOnNonCrashFailures = false)
 {
     sut.CreateOrUpdateService(testServiceName, TestServiceDisplayName, TestServiceDescription, TestServiceBinaryPath, TestCredentials,
                               serviceFailureActions, failureActionsOnNonCrashFailures, autoStart,
                               startImmediately, TestServiceErrorSeverity);
 }
Exemplo n.º 7
0
        private void OnCommitted(object sender, InstallEventArgs args)
        {
            IntPtr handleManager  = IntPtr.Zero;
            IntPtr handleService  = IntPtr.Zero;
            IntPtr handleDatabase = IntPtr.Zero;
            IntPtr buffer         = IntPtr.Zero;

            try
            {
                // Open the service control manager
                handleManager = OpenSCManager(null, null, ManagerAllAccessFlag);
                if (handleManager.ToInt64() <= 0)
                {
                    throw new InvalidOperationException("Error accessing service control manager.");
                }

                // Lock the Service Database
                handleDatabase = LockServiceDatabase(handleManager);
                if (handleDatabase.ToInt64() <= 0)
                {
                    throw new InvalidOperationException("Error locking service database.");
                }

                // Open the service
                handleService = OpenService(handleManager, _serviceInfo.Name, ServiceAllAccessFlag);
                if (handleService.ToInt64() <= 0)
                {
                    throw new InvalidOperationException("Error opening service '" + _serviceInfo.Name + "'");
                }

                // define actions
                int   countActions = 3;
                int[] actions      = new int[countActions * 2];
                // first failure
                actions[0] = (int)RecoverAction.Restart;
                actions[1] = 0;
                // second failure
                actions[2] = (int)RecoverAction.Restart;
                actions[3] = 0;
                // any subsequent failure
                actions[4] = (int)RecoverAction.Restart;
                actions[5] = 0;
                // 8 bytes per struct
                buffer = Marshal.AllocHGlobal(countActions * 8);
                Marshal.Copy(actions, 0, buffer, countActions * 2);

                // create the unmanaged struct
                ServiceFailureActions unmanagedActions = new ServiceFailureActions();
                unmanagedActions.cActions      = countActions;
                unmanagedActions.dwResetPeriod = 0;
                unmanagedActions.lpCommand     = null;
                unmanagedActions.lpRebootMsg   = null;
                unmanagedActions.lpsaActions   = buffer;

                if (!ChangeServiceFailureActions(handleService, RecoveryOptionsFlag, ref unmanagedActions))
                {
                    throw new Exception("Error while setting service recovery options.");
                }
            }
            finally
            {
                if (handleService != IntPtr.Zero)
                {
                    CloseServiceHandle(handleService);
                }
                if (handleDatabase != IntPtr.Zero)
                {
                    UnlockServiceDatabase(handleDatabase);
                }
                if (handleManager != IntPtr.Zero)
                {
                    CloseServiceHandle(handleManager);
                }
                if (buffer != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(buffer);
                }
            }
        }
Exemplo n.º 8
0
        private Func <ServiceHandle, ServiceConfigInfoTypeLevel, IntPtr, bool> CreateChangeService2WHandler(string serviceName)
        {
            return((handle, infoLevel, info) =>
            {
                switch (infoLevel)
                {
                case ServiceConfigInfoTypeLevel.ServiceDescription:
                    var serviceDescription = Marshal.PtrToStructure <ServiceDescriptionInfo>(info);
                    if (string.IsNullOrEmpty(serviceDescription.ServiceDescription))
                    {
                        serviceDescriptions.Remove(serviceName);
                    }
                    else
                    {
                        serviceDescriptions[serviceName] = serviceDescription.ServiceDescription;
                    }
                    return true;

                case ServiceConfigInfoTypeLevel.FailureActions:
                    var failureAction = Marshal.PtrToStructure <ServiceFailureActionsInfo>(info);
                    if (failureAction.Actions?.Length == 0)
                    {
                        failureActions.Remove(serviceName);
                    }
                    else
                    {
                        failureActions[serviceName] = new ServiceFailureActions(failureAction.ResetPeriod, failureAction.RebootMsg, failureAction.Command, failureAction.Actions);
                    }
                    return true;

                case ServiceConfigInfoTypeLevel.FailureActionsFlag:
                    var failureActionFlag = Marshal.PtrToStructure <ServiceFailureActionsFlag>(info);
                    failureActionsFlags[serviceName] = failureActionFlag.Flag;
                    return true;

                case ServiceConfigInfoTypeLevel.DelayedAutoStartInfo:
                    if (info != IntPtr.Zero)
                    {
                        delayedAutoStartInfoSetOnNativeInterop = Marshal.ReadInt32(info) > 0;
                    }
                    else
                    {
                        delayedAutoStartInfoSetOnNativeInterop = null;
                    }
                    return true;

                case ServiceConfigInfoTypeLevel.ServiceSidInfo:
                    break;

                case ServiceConfigInfoTypeLevel.RequiredPrivilegesInfo:
                    break;

                case ServiceConfigInfoTypeLevel.PreShutdownInfo:
                    break;

                case ServiceConfigInfoTypeLevel.TriggerInfo:
                    break;

                case ServiceConfigInfoTypeLevel.PreferredNode:
                    break;

                case ServiceConfigInfoTypeLevel.LaunchProtected:
                    break;

                default:
                    throw new ArgumentOutOfRangeException(nameof(infoLevel), infoLevel, null);
                }

                return false;
            });
        }
Exemplo n.º 9
0
        static int Main(string[] args)
        {
            if (args.Length != 1)
            {
                Console.WriteLine("Usage: {0} <name of service to adjust>", Path.GetFileName(typeof(Program).Assembly.Location));
                Console.WriteLine("If you'd like to run this test against a dummy service, use these commands:");
                Console.WriteLine("=> Create:   sc create TestSvc binPath= {0} start= demand", EscapeArg(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "ping.exe")));
                Console.WriteLine("=> Remove:   sc delete TestSvc");

                return(2);
            }

            Console.WriteLine("Adjusting service failure actions for service: {0}", args[0]);

            var actions =
                new ServiceFailureActions()
            {
                ResetPeriod    = TimeSpan.FromSeconds(60),
                RestartCommand = null,
                RebootMessage  = null,
                PerformFailureActionsOnStopWithNonZeroExitCode = false,
                Actions =
                    new ServiceFailureAction[]
                {
                    new ServiceFailureAction()
                    {
                        Type = ServiceFailureActionType.RestartService, DelayBeforeAction = TimeSpan.FromSeconds(5)
                    },
                    new ServiceFailureAction()
                    {
                        Type = ServiceFailureActionType.RestartService, DelayBeforeAction = TimeSpan.FromSeconds(15)
                    },
                    new ServiceFailureAction()
                    {
                        Type = ServiceFailureActionType.RestartService, DelayBeforeAction = TimeSpan.FromSeconds(25)
                    },
                    new ServiceFailureAction()
                    {
                        Type = ServiceFailureActionType.RestartService, DelayBeforeAction = TimeSpan.FromSeconds(35)
                    },
                    new ServiceFailureAction()
                    {
                        Type = ServiceFailureActionType.RestartService, DelayBeforeAction = TimeSpan.FromSeconds(45)
                    },
                    new ServiceFailureAction()
                    {
                        Type = ServiceFailureActionType.None, DelayBeforeAction = TimeSpan.FromSeconds(0)
                    },
                },
            };

            try
            {
                actions.ApplyToService(args[0]);

                Console.WriteLine("The operation appears to have succeeded.");

                return(0);
            }
            catch (Exception e)
            {
                Console.WriteLine("EXCEPTION:");
                Console.WriteLine(e);

                return(1);
            }
        }
Exemplo n.º 10
0
        ////////////////////////////////////////////////////////////////////////////////////
        // The worker method to set all the extension properties for the service
        private void UpdateServiceConfig(object sender, InstallEventArgs ea)
        {
            // Determine if we need to set fail actions

            _setFailActions = false;

            var numActions = FailureActions.Count;

            if (numActions > 0)
            {
                _setFailActions = true;
            }

            // Do we need to do any work that the base installer did not do already?
            if (!(_setDescription || _setFailActions))
            {
                return;
            }

            // We've got work to do
            var scmHndl = IntPtr.Zero;
            var svcHndl = IntPtr.Zero;
            var tmpBuf  = IntPtr.Zero;
            var svcLock = IntPtr.Zero;

            // Place all our code in a try block
            try
            {
                // Open the service control manager
                scmHndl = OpenSCManager(null, null, ScManagerAllAccess);

                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, ServiceAllAccess);

                if (svcHndl.ToInt32() <= 0)
                {
                    LogInstallMessage(EventLogEntryType.Information, "Failed to Open Service ");

                    return;
                }

                // Need to set service failure actions. 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 the API allows
                // granularity of seconds whereas GUI only shows days and minutes.

                bool rslt;

                if (_setFailActions)
                {
                    // We're gonna serialize the SA_ACTION structs into an array of ints
                    // for simplicity in marshalling this variable length ptr to win32

                    var actions = new int[numActions * 2];

                    var currInd = 0;

                    var needShutdownPrivilege = false;

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

                        currInd++;

                        if (fa.RecoverAction == RecoverAction.Reboot)
                        {
                            needShutdownPrivilege = true;
                        }
                    }

                    // If we need shutdown privilege, then grant it to this process
                    if (needShutdownPrivilege)
                    {
                        rslt = 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
                    var sfa = new ServiceFailureActions
                    {
                        cActions      = numActions,
                        dwResetPeriod = _failResetTime,
                        lpCommand     = _failRunCommand,
                        lpRebootMsg   = _failRebootMsg,
                        lpsaActions   = tmpBuf.ToInt32()
                    };

                    // Call the ChangeServiceFailureActions() abstraction of ChangeServiceConfig2()
                    rslt = ChangeServiceFailureActions(svcHndl, ServiceConfigFailureActions, ref sfa);

                    //Check the return
                    if (!rslt)
                    {
                        var err = GetLastError();

                        if (err == ErrorAccessDenied)
                        {
                            throw new Exception(_logMsgBase + "Access Denied while setting Failure Actions");
                        }
                    }

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

                // Need to set the description field?
                if (_setDescription)
                {
                    var sd = new ServiceDescription {
                        lpDescription = _description
                    };

                    // Call the ChangeServiceDescription() abstraction of ChangeServiceConfig2()
                    rslt = ChangeServiceDescription(svcHndl, ServiceConfigDescription, ref sd);

                    // Error setting description?
                    if (!rslt)
                    {
                        throw new Exception(_logMsgBase + "Failed to set description");
                    }
                }
            }
            catch (Exception e) { LogInstallMessage(EventLogEntryType.Error, e.Message); }
            finally
            {
                if (scmHndl != IntPtr.Zero)
                {
                    // Unlock the service database
                    if (svcLock != IntPtr.Zero)
                    {
                        UnlockServiceDatabase(svcLock);
                    }

                    // Close the service control manager handle
                    CloseServiceHandle(scmHndl);
                }

                // Close the service handle
                if (svcHndl != IntPtr.Zero)
                {
                    CloseServiceHandle(svcHndl);
                }

                // Free the memory
                if (tmpBuf != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(tmpBuf);
                }
            }
        }