![](/img/trans.png)
[英]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.