如何在 C# 中以编程方式安装 Windows 服务?
Posted
技术标签:
【中文标题】如何在 C# 中以编程方式安装 Windows 服务?【英文标题】:How to install a windows service programmatically in C#? 【发布时间】:2010-09-26 09:36:18 【问题描述】:我的 VS 解决方案中有 3 个项目。其中一个是 Web 应用程序,第二个是 Windows 服务,最后一个是我的 Web 应用程序的安装项目。
我想要的是在我的安装项目中安装网络应用程序结束时,在我的自定义操作中尝试安装我的 Windows 服务,因为那时我已经有了程序集的位置。
【问题讨论】:
【参考方案1】:我在您重用的代码中发现了几个错误,并已修复这些错误并对其进行了一些清理。同样,原始代码取自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
如果有人发现此代码有任何问题,请告诉我!
【讨论】:
我正在尝试使用此代码。但我有一个问题。我的服务中的代码取决于(需要)服务的名称。虽然我使用这个方法InstallService
和一个特定的服务名称,但如果我在我的服务中查询ServiceBase
的ServiceName
属性,它总是返回给我别的东西。有关如何从服务内部实际获取该名称的任何建议?
您将如何将它与 ServiceInstaller 和 ServiceProcessInstaller 结合使用?
非常感谢拉斯!这段代码似乎完全符合我的需要,但我不得不改变一些事情,因为它不耐烦。 “WaitForServiceStatus”功能中断,我收到“无法启动服务”错误,即使服务实际上正在启动。我摆脱了很多检查,现在我有一个潜在的无限循环,但它可以工作......也许你知道为什么函数没有等待?
据我记忆,服务状态变化的速度是高度不可预测的(卸载也是如此)。我认为文档也提到了这一点。
该代码在哪个许可证下?我可以在 MS-PL 项目中使用它吗?【参考方案2】:
好的,这对我来说真的很有效,它已经在多台具有不同操作系统(Vista、XP、Win2k、Win2003 服务器)的机器上进行了测试
代码取自here,因此完全归功于编写这段代码的人。
一旦您将 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");
我希望这会有所帮助。
【讨论】:
我已经发布了一个答案,其中包含对您发布的代码的一些错误修复。查看您在其中找到代码的讨论帖,您会发现代码的作者意识到其中存在一些错误。 我参考的帖子是:tech-archive.net/Archive/VB/microsoft.public.vb.winapi/2006-08/… 另外,我发现了另外一两个错误,服务句柄没有释放。 当你想要的只是在公园里安静地散步时,这个解决方案看起来就像是与一只 25 头的九头蛇搏斗......必须有一个更简单的方法 如何设置服务应该在哪个用户和密码下运行?我也可以使用上面提到的ServiceInstaller吗? 如果安装时间超过10秒,会报失败。【参考方案3】:请查看this article。
有时您可能希望以编程方式安装 Windows 服务,但目标计算机没有 InstallUtil.exe。
添加对System.Configuration.Install
的引用
使用下面的代码。
请注意,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);
卸载:
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);
【讨论】:
我已经尝试过了,但它不起作用。没有例外或其他什么,它只是不安装服务 可能是完整路径或凭据问题> 你可以尝试编写一个简单的服务。您是否也尝试过使用上面的 url,其中 SCM 在 C# 中使用 P/Invoke 调用适当的 API 我的编译器抱怨说 AssemblyInstaller(ExeFilename) 消耗了多个参数 - 它实际上似乎有 3 个重载 - 一个没有参数,另外两个每个有 2 个参数。自从你们发布后,有什么变化吗? 这是将程序集安装为服务的正确方法。如果它不适合你,那么你做错了什么!您不需要所有其他第三部分代码。谢谢 lakshmanaraj! 这应该是公认的答案。这很简单,而且很有效。 (由于缺少第二个参数,我建议进行编辑。此外,您应该引用 InstallerClass 而不是 ServiceClass 作为 exeFileName)。【参考方案4】:在为我的服务(非常基本)创建安装程序类的实例后,我所要做的就是调用:
ManagedInstallerClass.InstallHelper(new string[]
Assembly.GetExecutingAssembly().Location );
安装它并
ManagedInstallerClass.InstallHelper(new string[] "/u",
Assembly.GetExecutingAssembly().Location );
卸载服务。此处,调用代码与服务可执行文件位于同一程序集中。
要通过命令行安装服务,我所要做的就是通过命令行参数将其连接到可执行文件并测试System.Environment.UserInteractive
以了解它是正在执行的服务还是有人试图安装-卸载它瞧……没有时髦的互操作的东西……没有指针泄漏……
总共大约 20 行代码分布在两个类中。
要替换 InstallUtil,只需查看 ManagedInstallerClass.InstallHelper
【讨论】:
简单。在反映到 InstallUtil.exe 时,您可能会得出相同的结论。它做同样的事情。此外,它还有一些有趣的控制台编码修正。安装和卸载工作正常。 (记得以管理员身份运行...)【参考方案5】:通过使用Topshelf 项目,您可以通过调用可执行文件来安装:
MyService.exe install
Topshelf 还负责其他 Windows 服务管道。
【讨论】:
【参考方案6】:因为我面临以编程方式安装在特定用户下运行的服务的挑战。我扩展了InstallAndStart
方法以使用lp
和lpPassword
...
不多,但可能会有所帮助。
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】:我使用 Lars answer 来管理我的服务,它运行良好。但是我需要将参数传递给服务,我花了几个小时才弄清楚如何去做。因此,我决定发布具有使用参数启动服务的能力的更改类:
public static class ServiceHelper
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, string[] 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,string[] args)
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,args);
finally
CloseServiceHandle(service);
finally
CloseServiceHandle(scm);
public static void StartService(string serviceName,string[] args)
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,args);
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,string[] args)
SERVICE_STATUS status = new SERVICE_STATUS();
StartService(service, args.Length, args);
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
【讨论】:
【参考方案8】:在这篇文章中,我阅读了所有帖子和 cmets 但我仍然不知道如何设置帐户类型和 StartType 方法,当我要添加 Windows 服务时。这个代码示例在我这边运行良好,它只是添加了一个服务自己的本地系统)但是我准备安装程序我必须考虑 StartMode 和 User Account Type 方法,因为客户系统。 ServiceBootFlag 枚举似乎提供了 StartType,但 Account Type 仍然是个问题。
[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);
【讨论】:
【参考方案9】:使用以下代码使用 C# 安装 windows 服务:
public void InstallWinService(string winServicePath)
try
ManagedInstallerClass.InstallHelper(new string[] winServicePath);
catch (Exception)
throw;
【讨论】:
【参考方案10】:另一种方法是在命令提示符下使用 SC.exe:
System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new
System.Diagnostics.ProcessStartInfo();
startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
startInfo.FileName = "cmd.exe";
startInfo.Arguments = "/C sc create MyService binpath=\"c:\\...\\MyService.exe\"";
process.StartInfo = startInfo;
process.Start();
【讨论】:
以上是关于如何在 C# 中以编程方式安装 Windows 服务?的主要内容,如果未能解决你的问题,请参考以下文章
在 C# 中以编程方式设置 Windows XP Embedded 区域设置
如果应用程序具有应用程序清单,如何在 C# 中以编程方式获取?
在c#中以编程方式查询网卡的入站/出站IPv4数据包计数统计