繁体   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