如何以编程方式在c#中安装windows服务?

时间:2022-09-16 23:10:35

I have 3 projects in my VS solution. One of them is a Web app, the second one is a Windows Service and the last one a Setup project for my Web app.

我在VS解决方案中有3个项目。其中一个是Web应用,第二个是Windows服务,最后一个是我的Web应用的安装项目。

What I want is by the end of the installation of the web app in my setup project, within my custom action to try and install my windows service given that I have the location of the assembly by then.

我想要的是在我的安装项目中安装web应用程序的最后,在我的自定义操作中尝试安装我的windows服务,前提是那时我已经有了程序集的位置。

8 个解决方案

#1


68  

I found several errors in the code that you reused and have fixed these and also cleaned it up a little. Again, the original code is taken from here.

我在代码中发现了几个错误,这些错误是您重复使用的,并且已经修复了这些错误,并将其清理了一些。同样,原始代码是从这里获取的。

public static class ServiceInstaller
{
    private const int STANDARD_RIGHTS_REQUIRED = 0xF0000;
    private const int SERVICE_WIN32_OWN_PROCESS = 0x00000010;

    [StructLayout(LayoutKind.Sequential)]
    private class SERVICE_STATUS
    {
        public int dwServiceType = 0;
        public ServiceState dwCurrentState = 0;
        public int dwControlsAccepted = 0;
        public int dwWin32ExitCode = 0;
        public int dwServiceSpecificExitCode = 0;
        public int dwCheckPoint = 0;
        public int dwWaitHint = 0;
    }

    #region OpenSCManager
    [DllImport("advapi32.dll", EntryPoint = "OpenSCManagerW", ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)]
    static extern IntPtr OpenSCManager(string machineName, string databaseName, ScmAccessRights dwDesiredAccess);
    #endregion

    #region OpenService
    [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    static extern IntPtr OpenService(IntPtr hSCManager, string lpServiceName, ServiceAccessRights dwDesiredAccess);
    #endregion

    #region CreateService
    [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    private static extern IntPtr CreateService(IntPtr hSCManager, string lpServiceName, string lpDisplayName, ServiceAccessRights dwDesiredAccess, int dwServiceType, ServiceBootFlag dwStartType, ServiceError dwErrorControl, string lpBinaryPathName, string lpLoadOrderGroup, IntPtr lpdwTagId, string lpDependencies, string lp, string lpPassword);
    #endregion

    #region CloseServiceHandle
    [DllImport("advapi32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool CloseServiceHandle(IntPtr hSCObject);
    #endregion

    #region QueryServiceStatus
    [DllImport("advapi32.dll")]
    private static extern int QueryServiceStatus(IntPtr hService, SERVICE_STATUS lpServiceStatus);
    #endregion

    #region DeleteService
    [DllImport("advapi32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool DeleteService(IntPtr hService);
    #endregion

    #region ControlService
    [DllImport("advapi32.dll")]
    private static extern int ControlService(IntPtr hService, ServiceControl dwControl, SERVICE_STATUS lpServiceStatus);
    #endregion

    #region StartService
    [DllImport("advapi32.dll", SetLastError = true)]
    private static extern int StartService(IntPtr hService, int dwNumServiceArgs, int lpServiceArgVectors);
    #endregion

    public static void Uninstall(string serviceName)
    {
        IntPtr scm = OpenSCManager(ScmAccessRights.AllAccess);

        try
        {
            IntPtr service = OpenService(scm, serviceName, ServiceAccessRights.AllAccess);
            if (service == IntPtr.Zero)
                throw new ApplicationException("Service not installed.");

            try
            {
                StopService(service);
                if (!DeleteService(service))
                    throw new ApplicationException("Could not delete service " + Marshal.GetLastWin32Error());
            }
            finally
            {
                CloseServiceHandle(service);
            }
        }
        finally
        {
            CloseServiceHandle(scm);
        }
    }

    public static bool ServiceIsInstalled(string serviceName)
    {
        IntPtr scm = OpenSCManager(ScmAccessRights.Connect);

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

            if (service == IntPtr.Zero)
                return false;

            CloseServiceHandle(service);
            return true;
        }
        finally
        {
            CloseServiceHandle(scm);
        }
    }

    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.");

            try
            {
                StartService(service);
            }
            finally
            {
                CloseServiceHandle(service);
            }
        }
        finally
        {
            CloseServiceHandle(scm);
        }
    }

    public static void StartService(string serviceName)
    {
        IntPtr scm = OpenSCManager(ScmAccessRights.Connect);

        try
        {
            IntPtr service = OpenService(scm, serviceName, ServiceAccessRights.QueryStatus | ServiceAccessRights.Start);
            if (service == IntPtr.Zero)
                throw new ApplicationException("Could not open service.");

            try
            {
                StartService(service);
            }
            finally
            {
                CloseServiceHandle(service);
            }
        }
        finally
        {
            CloseServiceHandle(scm);
        }
    }

    public static void StopService(string serviceName)
    {
        IntPtr scm = OpenSCManager(ScmAccessRights.Connect);

        try
        {
            IntPtr service = OpenService(scm, serviceName, ServiceAccessRights.QueryStatus | ServiceAccessRights.Stop);
            if (service == IntPtr.Zero)
                throw new ApplicationException("Could not open service.");

            try
            {
                StopService(service);
            }
            finally
            {
                CloseServiceHandle(service);
            }
        }
        finally
        {
            CloseServiceHandle(scm);
        }
    }

    private static void StartService(IntPtr service)
    {
        SERVICE_STATUS status = new SERVICE_STATUS();
        StartService(service, 0, 0);
        var changedStatus = WaitForServiceStatus(service, ServiceState.StartPending, ServiceState.Running);
        if (!changedStatus)
            throw new ApplicationException("Unable to start service");
    }

    private static void StopService(IntPtr service)
    {
        SERVICE_STATUS status = new SERVICE_STATUS();
        ControlService(service, ServiceControl.Stop, status);
        var changedStatus = WaitForServiceStatus(service, ServiceState.StopPending, ServiceState.Stopped);
        if (!changedStatus)
            throw new ApplicationException("Unable to stop service");
    }

    public static ServiceState GetServiceStatus(string serviceName)
    {
        IntPtr scm = OpenSCManager(ScmAccessRights.Connect);

        try
        {
            IntPtr service = OpenService(scm, serviceName, ServiceAccessRights.QueryStatus);
            if (service == IntPtr.Zero)
                return ServiceState.NotFound;

            try
            {
                return GetServiceStatus(service);
            }
            finally
            {
                CloseServiceHandle(service);
            }
        }
        finally
        {
            CloseServiceHandle(scm);
        }
    }

    private static ServiceState GetServiceStatus(IntPtr service)
    {
        SERVICE_STATUS status = new SERVICE_STATUS();

        if (QueryServiceStatus(service, status) == 0)
            throw new ApplicationException("Failed to query service status.");

        return status.dwCurrentState;
    }

    private static bool WaitForServiceStatus(IntPtr service, ServiceState waitStatus, ServiceState desiredStatus)
    {
        SERVICE_STATUS status = new SERVICE_STATUS();

        QueryServiceStatus(service, status);
        if (status.dwCurrentState == desiredStatus) return true;

        int dwStartTickCount = Environment.TickCount;
        int dwOldCheckPoint = status.dwCheckPoint;

        while (status.dwCurrentState == waitStatus)
        {
            // Do not wait longer than the wait hint. A good interval is
            // one tenth the wait hint, but no less than 1 second and no
            // more than 10 seconds.

            int dwWaitTime = status.dwWaitHint / 10;

            if (dwWaitTime < 1000) dwWaitTime = 1000;
            else if (dwWaitTime > 10000) dwWaitTime = 10000;

            Thread.Sleep(dwWaitTime);

            // Check the status again.

            if (QueryServiceStatus(service, status) == 0) break;

            if (status.dwCheckPoint > dwOldCheckPoint)
            {
                // The service is making progress.
                dwStartTickCount = Environment.TickCount;
                dwOldCheckPoint = status.dwCheckPoint;
            }
            else
            {
                if (Environment.TickCount - dwStartTickCount > status.dwWaitHint)
                {
                    // No progress made within the wait hint
                    break;
                }
            }
        }
        return (status.dwCurrentState == desiredStatus);
    }

    private static IntPtr OpenSCManager(ScmAccessRights rights)
    {
        IntPtr scm = OpenSCManager(null, null, rights);
        if (scm == IntPtr.Zero)
            throw new ApplicationException("Could not connect to service control manager.");

        return scm;
    }
}


public enum ServiceState
{
    Unknown = -1, // The state cannot be (has not been) retrieved.
    NotFound = 0, // The service is not known on the host server.
    Stopped = 1,
    StartPending = 2,
    StopPending = 3,
    Running = 4,
    ContinuePending = 5,
    PausePending = 6,
    Paused = 7
}

[Flags]
public enum ScmAccessRights
{
    Connect = 0x0001,
    CreateService = 0x0002,
    EnumerateService = 0x0004,
    Lock = 0x0008,
    QueryLockStatus = 0x0010,
    ModifyBootConfig = 0x0020,
    StandardRightsRequired = 0xF0000,
    AllAccess = (StandardRightsRequired | Connect | CreateService |
                 EnumerateService | Lock | QueryLockStatus | ModifyBootConfig)
}

[Flags]
public enum ServiceAccessRights
{
    QueryConfig = 0x1,
    ChangeConfig = 0x2,
    QueryStatus = 0x4,
    EnumerateDependants = 0x8,
    Start = 0x10,
    Stop = 0x20,
    PauseContinue = 0x40,
    Interrogate = 0x80,
    UserDefinedControl = 0x100,
    Delete = 0x00010000,
    StandardRightsRequired = 0xF0000,
    AllAccess = (StandardRightsRequired | QueryConfig | ChangeConfig |
                 QueryStatus | EnumerateDependants | Start | Stop | PauseContinue |
                 Interrogate | UserDefinedControl)
}

public enum ServiceBootFlag
{
    Start = 0x00000000,
    SystemStart = 0x00000001,
    AutoStart = 0x00000002,
    DemandStart = 0x00000003,
    Disabled = 0x00000004
}

public enum ServiceControl
{
    Stop = 0x00000001,
    Pause = 0x00000002,
    Continue = 0x00000003,
    Interrogate = 0x00000004,
    Shutdown = 0x00000005,
    ParamChange = 0x00000006,
    NetBindAdd = 0x00000007,
    NetBindRemove = 0x00000008,
    NetBindEnable = 0x00000009,
    NetBindDisable = 0x0000000A
}

public enum ServiceError
{
    Ignore = 0x00000000,
    Normal = 0x00000001,
    Severe = 0x00000002,
    Critical = 0x00000003
}

Please let me know if anyone finds anything wrong with this code!

如果有人发现这个代码有问题,请告诉我!

#2


68  

Ok, here is what REALLY worked for me, it has been tested on multiple machines with different OS ( Vista, XP, Win2k, Win2003 server )

好的,这就是我的工作原理,它已经在多台不同操作系统的机器上进行了测试(Vista, XP, Win2k, Win2003服务器)

The code has been taken from here so full credit goes to whoever wrote this piece of code.

代码已经从这里被拿走了所以所有的功劳都归给了写这段代码的人。

Once you add the dll or source file into your project make sure to add the ServiceTools namespace and then you have access to some very handy functionality such as...

一旦您将dll或源文件添加到项目中,请确保添加ServiceTools名称空间,然后您就可以访问一些非常方便的功能,比如……

//Installs and starts the service
ServiceInstaller.InstallAndStart("MyServiceName", "MyServiceDisplayName", "C:\\PathToServiceFile.exe");

//Removes the service
ServiceInstaller.Uninstall("MyServiceName");

//Checks the status of the service
ServiceInstaller.GetServiceStatus("MyServiceName");

//Starts the service
ServiceInstaller.StartService("MyServiceName");

//Stops the service
ServiceInstaller.StopService("MyServiceName");

//Check if service is installed
ServiceInstaller.ServiceIsInstalled("MyServiceName");

I hope this helps.

我希望这可以帮助。

#3


28  

Please have a look at this article.

请看这篇文章。


Sometimes you may want to install a Windows Service programmatically, but the target machine does not have InstallUtil.exe.

有时,您可能希望以编程方式安装Windows服务,但目标机器没有InstallUtil.exe。

Add a reference to System.Configuration.Install

添加对System.Configuration.Install的引用

Use the code below.

使用下面的代码。

Note that the exeFileName is the InstallerClass .exe and not the ServiceClass .exe.

注意,exeFileName是InstallerClass .exe,而不是ServiceClass .exe。

public static void InstallService(string exeFilename)
{
    string[] commandLineOptions = new string[1] { "/LogFile=install.log" };

    System.Configuration.Install.AssemblyInstaller installer = new System.Configuration.Install.AssemblyInstaller(exeFilename, commandLineOptions);

    installer.UseNewContext = true;    
    installer.Install(null);    
    installer.Commit(null);

}

To uninstall:

卸载:

public static void UninstallService(string exeFilename)
{
    string[] commandLineOptions = new string[1] { "/LogFile=uninstall.log" };

    System.Configuration.Install.AssemblyInstaller installer = new System.Configuration.Install.AssemblyInstaller(exeFilename, commandLineOptions);

    installer.UseNewContext = true;    
    installer.Uninstall(null);

}

#4


11  

After creating an instance of an installer class for my service (very basic) all I had to do is to call :

在为我的服务创建一个安装程序类实例(非常基本)之后,我只需调用:

ManagedInstallerClass.InstallHelper(new string[] { 
    Assembly.GetExecutingAssembly().Location });

to install it and

要安装它,

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

to uninstall the service. The calling code is, here, in the same assembly as the service executable.

卸载服务。在这里,调用代码位于与服务可执行文件相同的程序集中。

to get the service to install through command line all I had to do is to connect this to the executable though command line arguments and test for System.Environment.UserInteractive to know if it is the service executing or someone trying to install-uninstall it and voila... no funky interop stuff... no pointers leaking...

要让服务通过命令行来安装,我所要做的就是将这个连接到可执行文件,尽管命令行参数和System.Environment测试。UserInteractive知道是正在执行的服务还是有人试图安装-卸载它,然后……没有时髦的互操作的东西…没有指针泄漏…

Total about 20 lines of code spread over two classes did the trick.

总共有20行代码分散在两个类上。

to replace InstallUtil just take a look at ManagedInstallerClass.InstallHelper

要替换InstallUtil,只需查看ManagedInstallerClass.InstallHelper

#5


4  

By using the Topshelf project you can install by calling your executable:

通过使用Topshelf项目,您可以通过调用可执行文件来安装:

MyService.exe install

Topshelf also takes care of other Windows Service plumbing.

Topshelf还能处理其他Windows服务系统。

#6


3  

Since I was faced with the challenge to install services programmatically which run under a certain user. I extended the InstallAndStart method to make use of lp and lpPassword...

因为我面临着以编程方式安装在某个用户下运行的服务的挑战。我扩展了InstallAndStart方法来使用lp和lpPassword…

Not much but might help.

没什么,但可能会有帮助。

public static void InstallAndStart(
    string serviceName, 
    string displayName, 
    string fileName, 
    string username, 
    string password)
{
    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, 
                username, 
                password);

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

        try
        {
            StartService(service);
        }
        finally
        {
            CloseServiceHandle(service);
        }
    }
    finally
    {
        CloseServiceHandle(scm);
    }
}

#7


1  

In this article I read all posts and comments Bu still I don't know How can I set Account Type and StartType method when I gonna add windows service. This code example works fine my side its just add a service own local system) But I prepare Setup program I must think StartMode and User Account Type method because of customers system.
there is every appearance that ServiceBootFlag enum provide StartType but Account Type still a problem.

在本文中,我阅读了所有的文章和评论,但我仍然不知道如何设置帐户类型和StartType方法,当我要添加windows服务时。这个代码示例运行良好,我的方面只是添加一个服务本地系统),但我准备安装程序,我必须考虑StartMode和用户帐户类型方法,因为客户系统。ServiceBootFlag enum的每个外观都提供了StartType,但帐户类型仍然是一个问题。

    [DllImport("advapi32.dll", EntryPoint = "CreateServiceA")]

    private static extern IntPtr CreateService(IntPtr hSCManager, string

    lpServiceName, string lpDisplayName, ServiceRights dwDesiredAccess, int

    dwServiceType, ServiceBootFlag dwStartType, ServiceError dwErrorControl,

    string lpBinaryPathName, string lpLoadOrderGroup, IntPtr lpdwTagId, string

    lpDependencies, string lp, string lpPassword); 

#8


0  

Use below code to install windows service using C#:

使用下面的代码使用c#安装windows服务:

public void InstallWinService(string winServicePath)
{
        try
        {
            ManagedInstallerClass.InstallHelper(new string[] { winServicePath});
        }
        catch (Exception)
        {

            throw;
        }
}

#1


68  

I found several errors in the code that you reused and have fixed these and also cleaned it up a little. Again, the original code is taken from here.

我在代码中发现了几个错误,这些错误是您重复使用的,并且已经修复了这些错误,并将其清理了一些。同样,原始代码是从这里获取的。

public static class ServiceInstaller
{
    private const int STANDARD_RIGHTS_REQUIRED = 0xF0000;
    private const int SERVICE_WIN32_OWN_PROCESS = 0x00000010;

    [StructLayout(LayoutKind.Sequential)]
    private class SERVICE_STATUS
    {
        public int dwServiceType = 0;
        public ServiceState dwCurrentState = 0;
        public int dwControlsAccepted = 0;
        public int dwWin32ExitCode = 0;
        public int dwServiceSpecificExitCode = 0;
        public int dwCheckPoint = 0;
        public int dwWaitHint = 0;
    }

    #region OpenSCManager
    [DllImport("advapi32.dll", EntryPoint = "OpenSCManagerW", ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)]
    static extern IntPtr OpenSCManager(string machineName, string databaseName, ScmAccessRights dwDesiredAccess);
    #endregion

    #region OpenService
    [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    static extern IntPtr OpenService(IntPtr hSCManager, string lpServiceName, ServiceAccessRights dwDesiredAccess);
    #endregion

    #region CreateService
    [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    private static extern IntPtr CreateService(IntPtr hSCManager, string lpServiceName, string lpDisplayName, ServiceAccessRights dwDesiredAccess, int dwServiceType, ServiceBootFlag dwStartType, ServiceError dwErrorControl, string lpBinaryPathName, string lpLoadOrderGroup, IntPtr lpdwTagId, string lpDependencies, string lp, string lpPassword);
    #endregion

    #region CloseServiceHandle
    [DllImport("advapi32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool CloseServiceHandle(IntPtr hSCObject);
    #endregion

    #region QueryServiceStatus
    [DllImport("advapi32.dll")]
    private static extern int QueryServiceStatus(IntPtr hService, SERVICE_STATUS lpServiceStatus);
    #endregion

    #region DeleteService
    [DllImport("advapi32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool DeleteService(IntPtr hService);
    #endregion

    #region ControlService
    [DllImport("advapi32.dll")]
    private static extern int ControlService(IntPtr hService, ServiceControl dwControl, SERVICE_STATUS lpServiceStatus);
    #endregion

    #region StartService
    [DllImport("advapi32.dll", SetLastError = true)]
    private static extern int StartService(IntPtr hService, int dwNumServiceArgs, int lpServiceArgVectors);
    #endregion

    public static void Uninstall(string serviceName)
    {
        IntPtr scm = OpenSCManager(ScmAccessRights.AllAccess);

        try
        {
            IntPtr service = OpenService(scm, serviceName, ServiceAccessRights.AllAccess);
            if (service == IntPtr.Zero)
                throw new ApplicationException("Service not installed.");

            try
            {
                StopService(service);
                if (!DeleteService(service))
                    throw new ApplicationException("Could not delete service " + Marshal.GetLastWin32Error());
            }
            finally
            {
                CloseServiceHandle(service);
            }
        }
        finally
        {
            CloseServiceHandle(scm);
        }
    }

    public static bool ServiceIsInstalled(string serviceName)
    {
        IntPtr scm = OpenSCManager(ScmAccessRights.Connect);

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

            if (service == IntPtr.Zero)
                return false;

            CloseServiceHandle(service);
            return true;
        }
        finally
        {
            CloseServiceHandle(scm);
        }
    }

    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.");

            try
            {
                StartService(service);
            }
            finally
            {
                CloseServiceHandle(service);
            }
        }
        finally
        {
            CloseServiceHandle(scm);
        }
    }

    public static void StartService(string serviceName)
    {
        IntPtr scm = OpenSCManager(ScmAccessRights.Connect);

        try
        {
            IntPtr service = OpenService(scm, serviceName, ServiceAccessRights.QueryStatus | ServiceAccessRights.Start);
            if (service == IntPtr.Zero)
                throw new ApplicationException("Could not open service.");

            try
            {
                StartService(service);
            }
            finally
            {
                CloseServiceHandle(service);
            }
        }
        finally
        {
            CloseServiceHandle(scm);
        }
    }

    public static void StopService(string serviceName)
    {
        IntPtr scm = OpenSCManager(ScmAccessRights.Connect);

        try
        {
            IntPtr service = OpenService(scm, serviceName, ServiceAccessRights.QueryStatus | ServiceAccessRights.Stop);
            if (service == IntPtr.Zero)
                throw new ApplicationException("Could not open service.");

            try
            {
                StopService(service);
            }
            finally
            {
                CloseServiceHandle(service);
            }
        }
        finally
        {
            CloseServiceHandle(scm);
        }
    }

    private static void StartService(IntPtr service)
    {
        SERVICE_STATUS status = new SERVICE_STATUS();
        StartService(service, 0, 0);
        var changedStatus = WaitForServiceStatus(service, ServiceState.StartPending, ServiceState.Running);
        if (!changedStatus)
            throw new ApplicationException("Unable to start service");
    }

    private static void StopService(IntPtr service)
    {
        SERVICE_STATUS status = new SERVICE_STATUS();
        ControlService(service, ServiceControl.Stop, status);
        var changedStatus = WaitForServiceStatus(service, ServiceState.StopPending, ServiceState.Stopped);
        if (!changedStatus)
            throw new ApplicationException("Unable to stop service");
    }

    public static ServiceState GetServiceStatus(string serviceName)
    {
        IntPtr scm = OpenSCManager(ScmAccessRights.Connect);

        try
        {
            IntPtr service = OpenService(scm, serviceName, ServiceAccessRights.QueryStatus);
            if (service == IntPtr.Zero)
                return ServiceState.NotFound;

            try
            {
                return GetServiceStatus(service);
            }
            finally
            {
                CloseServiceHandle(service);
            }
        }
        finally
        {
            CloseServiceHandle(scm);
        }
    }

    private static ServiceState GetServiceStatus(IntPtr service)
    {
        SERVICE_STATUS status = new SERVICE_STATUS();

        if (QueryServiceStatus(service, status) == 0)
            throw new ApplicationException("Failed to query service status.");

        return status.dwCurrentState;
    }

    private static bool WaitForServiceStatus(IntPtr service, ServiceState waitStatus, ServiceState desiredStatus)
    {
        SERVICE_STATUS status = new SERVICE_STATUS();

        QueryServiceStatus(service, status);
        if (status.dwCurrentState == desiredStatus) return true;

        int dwStartTickCount = Environment.TickCount;
        int dwOldCheckPoint = status.dwCheckPoint;

        while (status.dwCurrentState == waitStatus)
        {
            // Do not wait longer than the wait hint. A good interval is
            // one tenth the wait hint, but no less than 1 second and no
            // more than 10 seconds.

            int dwWaitTime = status.dwWaitHint / 10;

            if (dwWaitTime < 1000) dwWaitTime = 1000;
            else if (dwWaitTime > 10000) dwWaitTime = 10000;

            Thread.Sleep(dwWaitTime);

            // Check the status again.

            if (QueryServiceStatus(service, status) == 0) break;

            if (status.dwCheckPoint > dwOldCheckPoint)
            {
                // The service is making progress.
                dwStartTickCount = Environment.TickCount;
                dwOldCheckPoint = status.dwCheckPoint;
            }
            else
            {
                if (Environment.TickCount - dwStartTickCount > status.dwWaitHint)
                {
                    // No progress made within the wait hint
                    break;
                }
            }
        }
        return (status.dwCurrentState == desiredStatus);
    }

    private static IntPtr OpenSCManager(ScmAccessRights rights)
    {
        IntPtr scm = OpenSCManager(null, null, rights);
        if (scm == IntPtr.Zero)
            throw new ApplicationException("Could not connect to service control manager.");

        return scm;
    }
}


public enum ServiceState
{
    Unknown = -1, // The state cannot be (has not been) retrieved.
    NotFound = 0, // The service is not known on the host server.
    Stopped = 1,
    StartPending = 2,
    StopPending = 3,
    Running = 4,
    ContinuePending = 5,
    PausePending = 6,
    Paused = 7
}

[Flags]
public enum ScmAccessRights
{
    Connect = 0x0001,
    CreateService = 0x0002,
    EnumerateService = 0x0004,
    Lock = 0x0008,
    QueryLockStatus = 0x0010,
    ModifyBootConfig = 0x0020,
    StandardRightsRequired = 0xF0000,
    AllAccess = (StandardRightsRequired | Connect | CreateService |
                 EnumerateService | Lock | QueryLockStatus | ModifyBootConfig)
}

[Flags]
public enum ServiceAccessRights
{
    QueryConfig = 0x1,
    ChangeConfig = 0x2,
    QueryStatus = 0x4,
    EnumerateDependants = 0x8,
    Start = 0x10,
    Stop = 0x20,
    PauseContinue = 0x40,
    Interrogate = 0x80,
    UserDefinedControl = 0x100,
    Delete = 0x00010000,
    StandardRightsRequired = 0xF0000,
    AllAccess = (StandardRightsRequired | QueryConfig | ChangeConfig |
                 QueryStatus | EnumerateDependants | Start | Stop | PauseContinue |
                 Interrogate | UserDefinedControl)
}

public enum ServiceBootFlag
{
    Start = 0x00000000,
    SystemStart = 0x00000001,
    AutoStart = 0x00000002,
    DemandStart = 0x00000003,
    Disabled = 0x00000004
}

public enum ServiceControl
{
    Stop = 0x00000001,
    Pause = 0x00000002,
    Continue = 0x00000003,
    Interrogate = 0x00000004,
    Shutdown = 0x00000005,
    ParamChange = 0x00000006,
    NetBindAdd = 0x00000007,
    NetBindRemove = 0x00000008,
    NetBindEnable = 0x00000009,
    NetBindDisable = 0x0000000A
}

public enum ServiceError
{
    Ignore = 0x00000000,
    Normal = 0x00000001,
    Severe = 0x00000002,
    Critical = 0x00000003
}

Please let me know if anyone finds anything wrong with this code!

如果有人发现这个代码有问题,请告诉我!

#2


68  

Ok, here is what REALLY worked for me, it has been tested on multiple machines with different OS ( Vista, XP, Win2k, Win2003 server )

好的,这就是我的工作原理,它已经在多台不同操作系统的机器上进行了测试(Vista, XP, Win2k, Win2003服务器)

The code has been taken from here so full credit goes to whoever wrote this piece of code.

代码已经从这里被拿走了所以所有的功劳都归给了写这段代码的人。

Once you add the dll or source file into your project make sure to add the ServiceTools namespace and then you have access to some very handy functionality such as...

一旦您将dll或源文件添加到项目中,请确保添加ServiceTools名称空间,然后您就可以访问一些非常方便的功能,比如……

//Installs and starts the service
ServiceInstaller.InstallAndStart("MyServiceName", "MyServiceDisplayName", "C:\\PathToServiceFile.exe");

//Removes the service
ServiceInstaller.Uninstall("MyServiceName");

//Checks the status of the service
ServiceInstaller.GetServiceStatus("MyServiceName");

//Starts the service
ServiceInstaller.StartService("MyServiceName");

//Stops the service
ServiceInstaller.StopService("MyServiceName");

//Check if service is installed
ServiceInstaller.ServiceIsInstalled("MyServiceName");

I hope this helps.

我希望这可以帮助。

#3


28  

Please have a look at this article.

请看这篇文章。


Sometimes you may want to install a Windows Service programmatically, but the target machine does not have InstallUtil.exe.

有时,您可能希望以编程方式安装Windows服务,但目标机器没有InstallUtil.exe。

Add a reference to System.Configuration.Install

添加对System.Configuration.Install的引用

Use the code below.

使用下面的代码。

Note that the exeFileName is the InstallerClass .exe and not the ServiceClass .exe.

注意,exeFileName是InstallerClass .exe,而不是ServiceClass .exe。

public static void InstallService(string exeFilename)
{
    string[] commandLineOptions = new string[1] { "/LogFile=install.log" };

    System.Configuration.Install.AssemblyInstaller installer = new System.Configuration.Install.AssemblyInstaller(exeFilename, commandLineOptions);

    installer.UseNewContext = true;    
    installer.Install(null);    
    installer.Commit(null);

}

To uninstall:

卸载:

public static void UninstallService(string exeFilename)
{
    string[] commandLineOptions = new string[1] { "/LogFile=uninstall.log" };

    System.Configuration.Install.AssemblyInstaller installer = new System.Configuration.Install.AssemblyInstaller(exeFilename, commandLineOptions);

    installer.UseNewContext = true;    
    installer.Uninstall(null);

}

#4


11  

After creating an instance of an installer class for my service (very basic) all I had to do is to call :

在为我的服务创建一个安装程序类实例(非常基本)之后,我只需调用:

ManagedInstallerClass.InstallHelper(new string[] { 
    Assembly.GetExecutingAssembly().Location });

to install it and

要安装它,

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

to uninstall the service. The calling code is, here, in the same assembly as the service executable.

卸载服务。在这里,调用代码位于与服务可执行文件相同的程序集中。

to get the service to install through command line all I had to do is to connect this to the executable though command line arguments and test for System.Environment.UserInteractive to know if it is the service executing or someone trying to install-uninstall it and voila... no funky interop stuff... no pointers leaking...

要让服务通过命令行来安装,我所要做的就是将这个连接到可执行文件,尽管命令行参数和System.Environment测试。UserInteractive知道是正在执行的服务还是有人试图安装-卸载它,然后……没有时髦的互操作的东西…没有指针泄漏…

Total about 20 lines of code spread over two classes did the trick.

总共有20行代码分散在两个类上。

to replace InstallUtil just take a look at ManagedInstallerClass.InstallHelper

要替换InstallUtil,只需查看ManagedInstallerClass.InstallHelper

#5


4  

By using the Topshelf project you can install by calling your executable:

通过使用Topshelf项目,您可以通过调用可执行文件来安装:

MyService.exe install

Topshelf also takes care of other Windows Service plumbing.

Topshelf还能处理其他Windows服务系统。

#6


3  

Since I was faced with the challenge to install services programmatically which run under a certain user. I extended the InstallAndStart method to make use of lp and lpPassword...

因为我面临着以编程方式安装在某个用户下运行的服务的挑战。我扩展了InstallAndStart方法来使用lp和lpPassword…

Not much but might help.

没什么,但可能会有帮助。

public static void InstallAndStart(
    string serviceName, 
    string displayName, 
    string fileName, 
    string username, 
    string password)
{
    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, 
                username, 
                password);

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

        try
        {
            StartService(service);
        }
        finally
        {
            CloseServiceHandle(service);
        }
    }
    finally
    {
        CloseServiceHandle(scm);
    }
}

#7


1  

In this article I read all posts and comments Bu still I don't know How can I set Account Type and StartType method when I gonna add windows service. This code example works fine my side its just add a service own local system) But I prepare Setup program I must think StartMode and User Account Type method because of customers system.
there is every appearance that ServiceBootFlag enum provide StartType but Account Type still a problem.

在本文中,我阅读了所有的文章和评论,但我仍然不知道如何设置帐户类型和StartType方法,当我要添加windows服务时。这个代码示例运行良好,我的方面只是添加一个服务本地系统),但我准备安装程序,我必须考虑StartMode和用户帐户类型方法,因为客户系统。ServiceBootFlag enum的每个外观都提供了StartType,但帐户类型仍然是一个问题。

    [DllImport("advapi32.dll", EntryPoint = "CreateServiceA")]

    private static extern IntPtr CreateService(IntPtr hSCManager, string

    lpServiceName, string lpDisplayName, ServiceRights dwDesiredAccess, int

    dwServiceType, ServiceBootFlag dwStartType, ServiceError dwErrorControl,

    string lpBinaryPathName, string lpLoadOrderGroup, IntPtr lpdwTagId, string

    lpDependencies, string lp, string lpPassword); 

#8


0  

Use below code to install windows service using C#:

使用下面的代码使用c#安装windows服务:

public void InstallWinService(string winServicePath)
{
        try
        {
            ManagedInstallerClass.InstallHelper(new string[] { winServicePath});
        }
        catch (Exception)
        {

            throw;
        }
}