joshcomley
joshcomley

Reputation: 28808

How do I change a Windows Service's startup type in .NET (post-install)?

I have a program that installs a service, and I'd like to be able to give the user the option later on to change the startup type to "Automatic".

The OS is XP - if it makes any difference (Windows APIs?).

How can I do this in .NET? C# if possible! :)

Upvotes: 37

Views: 61384

Answers (9)

John Bartels
John Bartels

Reputation: 2763

You can use WMI to query all services and then match the service name to the inputted user value

Once the service has been found just change the StartMode Property

if(service.Properties["Name"].Value.ToString() == userInputValue)
{
    service.Properties["StartMode"].Value = "Automatic";
    //service.Properties["StartMode"].Value = "Manual";
}

//This will get all of the Services running on a Domain Computer and change the "Apple Mobile Device" Service to the StartMode of Automatic.  These two functions should obviously be separated, but it is simple to change a service start mode after installation using WMI

private void getServicesForDomainComputer(string computerName)
{
    ConnectionOptions co1 = new ConnectionOptions();
    co1.Impersonation = ImpersonationLevel.Impersonate;
    //this query could also be: ("select * from Win32_Service where name = '" + serviceName + "'");
    ManagementScope scope = new ManagementScope(@"\\" + computerName + @"\root\cimv2");
    scope.Options = co1;

    SelectQuery query = new SelectQuery("select * from Win32_Service");

    using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query))
    {
        ManagementObjectCollection collection = searcher.Get();

        foreach (ManagementObject service in collection)
        {
            //the following are all of the available properties 
            //boolean AcceptPause
            //boolean AcceptStop
            //string Caption
            //uint32 CheckPoint
            //string CreationClassName
            //string Description
            //boolean DesktopInteract
            //string DisplayName
            //string ErrorControl
            //uint32 ExitCode;
            //datetime InstallDate;
            //string Name
            //string PathName
            //uint32 ProcessId
            //uint32 ServiceSpecificExitCode
            //string ServiceType
            //boolean Started
            //string StartMode
            //string StartName
            //string State
            //string Status
            //string SystemCreationClassName
            //string SystemName;
            //uint32 TagId;
            //uint32 WaitHint;
            if(service.Properties["Name"].Value.ToString() == "Apple Mobile Device")
            {
                service.Properties["StartMode"].Value = "Automatic";
            }
        }
    }         
}

I wanted to improve this response... One method to change startMode for Specified computer, service:

public void changeServiceStartMode(string hostname, string serviceName, string startMode)
{
    try
    {
        ManagementObject classInstance = 
            new ManagementObject(@"\\" + hostname + @"\root\cimv2",
                                 "Win32_Service.Name='" + serviceName + "'",
                                 null);

        // Obtain in-parameters for the method
        ManagementBaseObject inParams = classInstance.GetMethodParameters("ChangeStartMode");

        // Add the input parameters.
        inParams["StartMode"] = startMode;

        // Execute the method and obtain the return values.
        ManagementBaseObject outParams = classInstance.InvokeMethod("ChangeStartMode", inParams, null);

        // List outParams
        //Console.WriteLine("Out parameters:");
        //richTextBox1.AppendText(DateTime.Now.ToString() + ": ReturnValue: " + outParams["ReturnValue"]);
    }
    catch (ManagementException err)
    {
        //richTextBox1.AppendText(DateTime.Now.ToString() + ": An error occurred while trying to execute the WMI method: " + err.Message);
    }
}

Upvotes: 7

Chou George
Chou George

Reputation: 61

How about make use of c:\windows\system32\sc.exe to do that ?!

In VB.NET Codes, use System.Diagnostics.Process to call sc.exe to change the startup mode of a windows service. following is my sample code

    Public Function SetStartModeToDisabled(ByVal ServiceName As String) As Boolean
    Dim sbParameter As New StringBuilder
    With sbParameter
        .Append("config ")
        .AppendFormat("""{0}"" ", ServiceName)
        .Append("start=disabled")
    End With

    Dim processStartInfo As ProcessStartInfo = New ProcessStartInfo()
    Dim scExeFilePath As String = String.Format("{0}\sc.exe", Environment.GetFolderPath(Environment.SpecialFolder.System))
    processStartInfo.FileName = scExeFilePath
    processStartInfo.Arguments = sbParameter.ToString
    processStartInfo.UseShellExecute = True

    Dim process As Process = process.Start(processStartInfo)
    process.WaitForExit()

    Return process.ExitCode = 0 

End Function

Upvotes: 3

Peter Kelly
Peter Kelly

Reputation: 14391

I wrote a blog post on how to do this using P/Invoke. Using the ServiceHelper class from my post you can do the following to change the Start Mode.

var svc = new ServiceController("ServiceNameGoesHere");  
ServiceHelper.ChangeStartMode(svc, ServiceStartMode.Automatic); 

Upvotes: 64

Christian.K
Christian.K

Reputation: 49220

You can use the OpenService() and ChangeServiceConfig() native Win32 APIs for that purpose. I believe that there is some information on pinvoke.net and of course on MSDN. You might want to check out the P/Invoke Interopt Assistant.

Upvotes: 10

HasaniH
HasaniH

Reputation: 8392

You can do it in the Installer class for the service by setting ServiceInstaller.StartType property to whatever value you get (you'll probably have to do this in a custom action since you want the user to specify) or you can modify the Service's "Start" REG_DWORD entry, the value 2 is automatic and 3 is manual. Its in HKEY_LOCAL_MACHINE\SYSTEM\Services\YourServiceName

Upvotes: 0

lubos hasko
lubos hasko

Reputation: 25052

One way would be to uninstall previous service and install new one with updated parameters directly from your C# application.

You will need WindowsServiceInstaller in your app.

[RunInstaller(true)]
public class WindowsServiceInstaller : Installer
{
    public WindowsServiceInstaller()
    {
        ServiceInstaller si = new ServiceInstaller();
        si.StartType = ServiceStartMode.Automatic; // get this value from some global variable
        si.ServiceName = @"YOUR APP";
        si.DisplayName = @"YOUR APP";
        this.Installers.Add(si);

        ServiceProcessInstaller spi = new ServiceProcessInstaller();
        spi.Account = System.ServiceProcess.ServiceAccount.LocalSystem;
        spi.Username = null;
        spi.Password = null;
        this.Installers.Add(spi);
    }
}

and to reinstall service just use these two lines.

ManagedInstallerClass.InstallHelper(new string[] { "/u", Assembly.GetExecutingAssembly().Location });
ManagedInstallerClass.InstallHelper(new string[] { Assembly.GetExecutingAssembly().Location });

Upvotes: -3

Matt Wrock
Matt Wrock

Reputation: 6640

In ProjectInstaller.cs, click/select the Service1 component on the design surface. In the properties windo there is a startType property for you to set this.

Upvotes: 2

CSharpAtl
CSharpAtl

Reputation: 7512

ServiceInstaller myInstaller = new System.ServiceProcess.ServiceInstaller();
myInstaller.StartType = System.ServiceProcess.ServiceStartMode.Automatic;

Upvotes: -1

Arthur
Arthur

Reputation: 8129

In the service installer you have to say

[RunInstaller(true)]
public class ProjectInstaller : System.Configuration.Install.Installer 
{
    public ProjectInstaller()
    {
        ...
        this.serviceInstaller1.StartType = System.ServiceProcess.ServiceStartMode.Automatic;
    }
}

You could also ask the user during installation and then set this value. Or just set this property in the visual studio designer.

Upvotes: 15

Related Questions