繁体   English   中英

在 C# 中更改 Windows 服务的用户名

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM