[英]How to start a new instance of Windows Service using ServiceController in C#
[英]Start / stop windows services with C# ServiceController and Impersonation
我正在为机器人框架开发远程关键字库。 这个库运行在 c# .net。
远程库是使用NRobot-Server构建的。 这是处理 xml-rpc 服务器和其他东西,所以我只能为机器人框架编写关键字。 仅供参考,这个 xml-rpc 服务器是多线程的。
基于这个答案和这个演示,我设法把一些东西放在一起。 但是我总是Cannot open <<my service>> service on computer '192.168.0.105'
Cannot open <<my service>> service on computer '192.168.0.105'.
at System.ServiceProcess.ServiceController.GetServiceHandle(Int32 desiredAccess)
at System.ServiceProcess.ServiceController.Stop()
at RKL.KeywordLibrary.KeywordLibraryImpl.ControlService(String host, String username, String password, String name, String action, String domain) in C:\Dev\QueueServiceSystemTestRKL\src\RKL\KeywordLibrary\KeywordLibraryImpl.cs:line 115
at RKL.KeywordLibrary.RklKeywordClass.ControlService(String h
ost, String username, String password, String name, String action) in C:\Dev\RKL\src\RKL\KeywordLibrary\RKLKeywordClass.cs:line 21
由于我应该能够远程控制服务,因此开发环境如下所示:
------------------- --------------------
| OS X | | Win 10 |
| | | |
| robot framework | --> | remote keyword |
| | | library (C#) |
------------------- --------------------
|
|
v
---------------------
| Win Server 2019 |
| |
| service |
| |
---------------------
实际代码如下所示(我使用的是SimpleImpersonation nuget )
public void ControlService(string host, string username, string password, string name, string action)
{
var credentials = new UserCredentials(username, password);
Impersonation.RunAsUser(credentials, SimpleImpersonation.LogonType.Interactive, () =>
{
ServiceController sc = new ServiceController(name, host);
TimeSpan timeout = new TimeSpan(0,0,30);
switch (action)
{
case "start":
sc.Start();
sc.WaitForStatus(ServiceControllerStatus.Running, timeout);
break;
case "stop":
sc.Stop();
sc.WaitForStatus(ServiceControllerStatus.Stopped, timeout);
break;
default:
string msg = String.Format("Unknown action: '{0}'", action);
throw new Exception(msg);
}
});
}
还要提一下,我在两台 windows 机器上都创建了testuser
,并且这两个用户都是管理员。
目前我正在尝试禁用所有 windows 安全性,但我已经死在水中了。 只是尝试随机的东西。
有谁知道哪里可能有问题? 任何帮助,将不胜感激!
所以我发现了ServiceControllerPermission 类并尝试了它。 它起作用了
public void ControlService(string host, string username, string password, string name, string action)
{
var credentials = new UserCredentials(username, password);
Impersonation.RunAsUser(credentials, SimpleImpersonation.LogonType.Interactive, () =>
{
ServiceControllerPermission scp = new ServiceControllerPermission(ServiceControllerPermissionAccess.Control, host, name);
scp.Assert();
ServiceController sc = new ServiceController(name, host);
TimeSpan timeout = new TimeSpan(0,0,30);
switch (action)
{
case "start":
sc.Start();
sc.WaitForStatus(ServiceControllerStatus.Running, timeout);
break;
case "stop":
sc.Stop();
sc.WaitForStatus(ServiceControllerStatus.Stopped, timeout);
break;
default:
string msg = String.Format("Unknown action: '{0}'", action);
throw new Exception(msg);
}
});
}
我尝试使用上面的解决方案来启动 Windows 服务,以及我在 inte.net 上找到的其他可能的解决方案。 在所有情况下,我都会遇到同样的问题,但无法找到/理解原因。 此刻“sc.Start();” 被称为我得到一个异常>内部异常“access dinied”。
基于上面的代码,我通过“WindowsIdentity.RunImpersonated”将其改编为较新的版本。 rest 应该是相同的。 使用的凭据是测试机器上的本地管理员。 通过 mmc 或 cmd 我可以用这个用户启动服务。 但不是这个代码。
欢迎任何帮助,因为我现在不知道如何完成它。
谢谢。
public void MainRun()
{
// Get the user token for the specified user, domain, and password using the
// unmanaged LogonUser method.
// The local machine name can be used for the domain name to impersonate a user on this machine.
Console.Write("Enter the name of the domain on which to log on: ");
string domainName = Console.ReadLine();
Console.Write("Enter the login of a user on {0} that you wish to impersonate: ", domainName);
string userName = Console.ReadLine();
Console.Write("Enter the password for {0}: ", userName);
const int LOGON32_PROVIDER_DEFAULT = 0;
//This parameter causes LogonUser to create a primary token.
const int LOGON32_LOGON_INTERACTIVE = 2;
// Call LogonUser to obtain a handle to an access token.
SafeAccessTokenHandle safeAccessTokenHandle;
bool returnValue = LogonUser(userName, domainName, Console.ReadLine(),
LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT,
out safeAccessTokenHandle);
if (false == returnValue)
{
int ret = Marshal.GetLastWin32Error();
Console.WriteLine("LogonUser failed with error code : {0}", ret);
throw new System.ComponentModel.Win32Exception(ret);
}
Console.WriteLine("Did LogonUser Succeed? " + (returnValue ? "Yes" : "No"));
// Check the identity.
Console.WriteLine("Before impersonation: " + WindowsIdentity.GetCurrent().Name);
// Note: if you want to run as unimpersonated, pass
// 'SafeAccessTokenHandle.InvalidHandle' instead of variable 'safeAccessTokenHandle'
WindowsIdentity.RunImpersonated(
safeAccessTokenHandle,
// User action
() =>
{
ServiceControllerPermission scp = new ServiceControllerPermission(ServiceControllerPermissionAccess.Control,
Program.host, Program.serviceName);
scp.Assert();
ServiceController sc = new ServiceController(Program.serviceName, Program.host);
TimeSpan timeout = new TimeSpan(0, 0, 30);
sc.Start();
sc.WaitForStatus(ServiceControllerStatus.Running, timeout);
// Check the identity.
Console.WriteLine("During impersonation: " + WindowsIdentity.GetCurrent().Name);
}
);
// Check the identity again.
Console.WriteLine("After impersonation: " + WindowsIdentity.GetCurrent().Name);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.