gpt4 book ai didi

.net - 使用 ServiceController 和模拟启动远程 Windows 服务

转载 作者:行者123 更新时间:2023-12-01 22:29:35 26 4
gpt4 key购买 nike

我有一个 .NET MVC3 应用程序,需要能够打开和关闭远程服务。为了做到这一点,我通过 WindowsIdentity.Impersonate() 模拟特定的用户帐户。为了测试用户的权限,我可以以用户身份登录并从命令提示符执行 sc.exe\\[server] start [service] 。我还知道模拟命令正在按预期工作,因为应用程序以匿名方式运行,因此无法在没有模拟的情况下控制本地计算机 (.) 上的服务,但可以控制本地服务与冒充。但是,当我将它们放在一起并尝试启动远程服务而不是本地服务时,我总是收到错误“无法在计算机 '[server] 上打开 [service] 服务” '"

有人遇到过类似的问题吗?我原以为这是服务器配置问题而不是 .NET 问题,直到我意识到 sc.exe 可以正常工作。这是我正在使用的类的缩写版本:

public class Service
{
public string Name;
public bool Running;
private ServiceController serviceController;

public Service(string name, string host)
{
Name = name;

serviceController = new ServiceController(Name, host);
Running = serviceController.Status == ServiceControllerStatus.Running;
}

public bool StartService()
{
ServiceControllerPermission scp = new ServiceControllerPermission(ServiceControllerPermissionAccess.Control, serviceController.MachineName, Name);
scp.Assert();

serviceController.Start();
serviceController.WaitForStatus(ServiceControllerStatus.Running, new TimeSpan(0, 0, 5));
serviceController.Refresh();

Running = serviceController.Status == ServiceControllerStatus.Running;

return Running;
}
}

一个附加说明:如果我将应用程序指向域中的另一台 Windows 7 PC,而不是服务器,并将模拟凭据更改为该 PC 所有者的凭据,那么我实际上可以毫无问题地远程控制他们的服务。

根据请求,我在此处添加模拟代码。有点长,请耐心等待:

public class Impersonate
{
public const int LOGON32_LOGON_INTERACTIVE = 2;
public const int LOGON32_PROVIDER_DEFAULT = 0;

WindowsImpersonationContext impersonationContext;

[DllImport("advapi32.dll")]
public static extern int LogonUserA(String lpszUserName,
String lpszDomain,
String lpszPassword,
int dwLogonType,
int dwLogonProvider,
ref IntPtr phToken);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int DuplicateToken(IntPtr hToken,
int impersonationLevel,
ref IntPtr hNewToken);

[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool RevertToSelf();

[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern bool CloseHandle(IntPtr handle);

public bool impersonateValidUser(String userName, String domain, String password)
{
WindowsIdentity tempWindowsIdentity;
IntPtr token = IntPtr.Zero;
IntPtr tokenDuplicate = IntPtr.Zero;

if (RevertToSelf())
{
if (LogonUserA(userName, domain, password, LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT, ref token) != 0)
{
if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)
{
tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
impersonationContext = tempWindowsIdentity.Impersonate();
if (impersonationContext != null)
{
CloseHandle(token);
CloseHandle(tokenDuplicate);
return true;
}
}
}
}
if (token != IntPtr.Zero)
CloseHandle(token);
if (tokenDuplicate != IntPtr.Zero)
CloseHandle(tokenDuplicate);
return false;
}

public void undoImpersonation()
{
impersonationContext.Undo();
}
}

我在尝试启动或停止服务之前调用此代码:

Service s = new Service(ServiceName, MachineName);

if (Impersonation.impersonateValidUser(Username, Domain, Password))
{
if (s.Running)
s.StopService();
else
s.StartService();

Impersonation.undoImpersonation();
}

可能值得注意的是,我可以列出服务并获取单个服务的状态(就像我在这里所做的那样) - 只有当我启动或停止服务时才会遇到麻烦。

最佳答案

也许我找到了答案:

在模拟方法中LogonUserA

使用LOGON32_LOGON_SERVICE (= 5)而不是LOGON32_LOGON_INTERACTIVE

确保您模拟的用户与运行该服务的用户是同一用户。

在我的例子中,用户包含在本地策略 --> 将 session 作为服务启动。我尚未对未包含在该本地策略中的用户进行测试。

希望对你有帮助!

关于.net - 使用 ServiceController 和模拟启动远程 Windows 服务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8581931/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com