簡體   English   中英

使用 C# ServiceController 和 Impersonation 啟動/停止 windows 服務

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM