[英]Changing user name of a Windows service in C#
我正在尝试通过 WinAPI 调用更改 C# 中 Windows 服务的用户名和密码。 我自己使用 WinAPI 的CreateService()
创建了服务,基于此 Stack Overflow 答案中的代码。
如果我在调用ChangeServiceConfigA()
时使用相同的凭据,我会被告知用户名和密码不正确。 我可以使用ChangeServiceConfigA()
更改其他所有内容,甚至是密码,但是一旦我尝试设置用户名和密码,就会出现错误。
我的代码如下所示:
private const uint SERVICE_NO_CHANGE = 0xffffffff;
[Flags]
private 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
}
private enum ServiceBootFlag : UInt32
{
Start = 0x00000000,
SystemStart = 0x00000001,
AutoStart = 0x00000002,
DemandStart = 0x00000003,
Disabled = 0x00000004,
ServiceNoChange = SERVICE_NO_CHANGE
}
private enum ServiceError : UInt32
{
Ignore = 0x00000000,
Normal = 0x00000001,
Severe = 0x00000002,
Critical = 0x00000003,
ServiceNoChange = SERVICE_NO_CHANGE
}
private enum ServiceType : UInt32
{
ServiceFileSystemDriver = 0x00000002,
ServiceKernelDrvier = 0x00000001,
ServiceWin32OwnProcess = 0x00000010,
ServiveWin32ShareProcess = 0x00000020,
ServiceNoChange = SERVICE_NO_CHANGE
}
[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? lpServiceStartName, string? lpPassword);
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern bool ChangeServiceConfigA(IntPtr hService, ServiceType dwServiceType, ServiceBootFlag dwStartType, ServiceError dwErrorControl, string? lpBinaryPathName, string? lpLoadOrderGroup, IntPtr lpdwTagId, string? lpDependencies, string? lpServiceStartName, string? lpPassword, string? lpDisplayName);
public static bool ChangeService(string serviceName, string? userName, string? password)
{
IntPtr scm = OpenSCManager(ScmAccessRights.Connect);
try
{
IntPtr service = OpenService(scm, serviceName, ServiceAccessRights.ChangeConfig);
if (service == IntPtr.Zero)
return false;
if (!ChangeServiceConfigA(service,
ServiceType.ServiceNoChange,
ServiceBootFlag.ServiceNoChange,
ServiceError.ServiceNoChange,
null, null, IntPtr.Zero, null,
userName, password, null))
throw new ApplicationException(":( sadface");
CloseServiceHandle(service);
return true;
}
finally
{
CloseServiceHandle(scm);
}
}
啊,我在做我想做的其他WinAPI 事情时偶然找到了答案:
QueryServiceConfigA()
使用 ANSI 字符串(而QueryServiceConfigW()
使用 Unicode),但最重要的是, QueryServiceConfig()
是一个自动选择正确字符串的别名。
像这样声明,它就像一个魅力:
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern bool ChangeServiceConfig(IntPtr hService, ServiceType dwServiceType, ServiceBootFlag dwStartType, ServiceError dwErrorControl, string? lpBinaryPathName, string? lpLoadOrderGroup, IntPtr lpdwTagId, string? lpDependencies, string? lpServiceStartName, string? lpPassword, string? lpDisplayName);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.