与ServiceController的和模拟启动远程的Windo

与ServiceController的和模拟启动远程的Windo

本文介绍了与ServiceController的和模拟启动远程的Windows服务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

予有需要,以便能够把一个远程服务和关闭一个.NET MVC3应用。为了做到这一点,我通过WindowsIdentity.Impersonate冒充特定的用户帐户()。为了验证用户的权限,我可以作为用户登录并执行 SC.EXE \\ [系统]启动[服务] 从命令提示符。我也知道,冒充命令工作正常,因为应用程序运行匿名,因此不能在我的本地机器控制服务()不带模拟,但是的可以的控制本地服务与模拟。然而,当我把它放在一起,尝试启动远程服务,而不是当地的服务,我总是得到错误可以在计算机<$ C $不能打开 [服务] 服务C> [服务器]

有没有人经历过类似的问题?我期待这是一个服务器的配置,而不​​是.NET的问题,直到我意识到,SC.EXE工作没有问题。下面是类的,我使用的是简化版本:

 公共类服务
{
    公共字符串名称;
    公共BOOL运行;
    私人的ServiceController的ServiceController;

    公共服务(字符串名称,字符串主机)
    {
        名称=名称;

        ServiceController的=新的ServiceController(名称,主机);
        运行= serviceController.Status == ServiceControllerStatus.Running;
    }

    公共BOOL StartService()
    {
        ServiceControllerPermission SCP =新ServiceControllerPermission(ServiceControllerPermissionAccess.Control,serviceController.MachineName,姓名);
        scp.Assert();

        serviceController.Start();
        serviceController.WaitForStatus(ServiceControllerStatus.Running,新时间跨度(0,0,5));
        serviceController.Refresh();

        运行= serviceController.Status == ServiceControllerStatus.Running;

        返回运行;
    }
}
 

,还应注意:不是服务器如果我指向另一台Windows 7 PC上的领域的应用,改变模拟凭据那些电脑的主人,我居然能没有问题远程控制他们的服务。

每个请求,我在这里加入了模拟code。这是一个长一点让我忍受:

 公共类冒充
{
    公共const int的LOGON32_LOGON_INTERACTIVE = 2;
    公共const int的LOGON32_PROVIDER_DEFAULT = 0;

    WindowsImpersonationContext impersonationContext;

    [的DllImport(advapi32.dll中)
    公共静态外部INT LogonUserA(字符串lpszUserName,
        字符串lpszDomain,
        字符串lpszPassword,
        INT dwLogonType,
        INT dwLogonProvider,
        裁判的IntPtr phToken);
    [的DllImport(advapi32.dll的,字符集= CharSet.Auto,SetLastError =真)
    公共静态外部INT DuplicateToken(IntPtr的hToken,
        INT impersonationLevel,
        裁判的IntPtr hNewToken);

    [的DllImport(advapi32.dll的,字符集= CharSet.Auto,SetLastError =真)
    公共静态的extern BOOL了RevertToSelf();

    [的DllImport(KERNEL32.DLL,字符集= CharSet.Auto)
    公共静态的extern BOOL CloseHandle的(IntPtr的手柄);

    公共BOOL impersonateValidUser(用户名字符串,字符串域,字符串密码)
    {
        的WindowsIdentity tempWindowsIdentity;
        IntPtr的令牌= IntPtr.Zero;
        IntPtr的tokenDuplicate = IntPtr.Zero;

        如果(RevertToSelf的())
        {
            如果(LogonUserA(用户名,域,密码,LOGON32_LOGON_INTERACTIVE,
                LOGON32_PROVIDER_DEFAULT,楼盘令牌)!= 0)
            {
                如果(DuplicateToken(令牌,2,参考tokenDuplicate)!= 0)
                {
                    tempWindowsIdentity =新的WindowsIdentity(tokenDuplicate);
                    impersonationContext = tempWindowsIdentity.Impersonate();
                    如果(impersonationContext!= NULL)
                    {
                        CloseHandle的(标记);
                        CloseHandle的(tokenDuplicate);
                        返回true;
                    }
                }
            }
        }
        如果(令牌!= IntPtr.Zero)
            CloseHandle的(标记);
        如果(tokenDuplicate!= IntPtr.Zero)
            CloseHandle的(tokenDuplicate);
        返回false;
    }

    公共无效undoImpersonation()
    {
        impersonationContext.Undo();
    }
}
 

我把这code只是试图启动或停止服务之前:

 服务S =新服务(服务名称,计算机名);

如果(Impersonation.impersonateValidUser(用户名,域,密码))
{
    如果(s.Running)
        s.StopService();
    其他
        s.StartService();

    Impersonation.undoImpersonation();
}
 

这可能是值得指出的是,我可以列出的服务,并获得个性化服务的状态(如我在这里做的)就好了 - 只有当我去启动或停止,我遇到麻烦了服务

解决方案

也许我已经找到了答案:

在模拟方法的 LogonUserA

使用 LOGON32_LOGON_SERVICE (= 5),而不是 LOGON32_LOGON_INTERACTIVE

请确保您正在模拟用户是运行该服务的用户。

在我的情况下,用户被包含在本地策略 - >启动会话服务。我还没有与用户未包括在该本地策略进行测试。

希望它能帮助!

I have a .NET MVC3 application that needs to be able to turn a remote service on and off. In order to do this I am impersonating a specific user account via WindowsIdentity.Impersonate(). To test the user's permissions I can log in as the user and execute sc.exe \\[server] start [service] from the command prompt. I also know that the impersonate command is working as expected because the application runs anonymously and therefore cannot control services on my local machine (.) without impersonation, but can control local services with impersonation. However, when I put it together and attempt to start the remote service rather than local service I always get the error "Cannot open [service] service on computer '[server]'"

Has anyone ever experienced a similar issue? I was expecting it to be a server configuration rather than .NET issue until I realized that sc.exe works without issue. Here is an abbreviated version of the class that I am using:

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;
    }
}

One additional note: If instead of the server I point the application at another Windows 7 PC on the domain and change the impersonation credentials to those of the owner of that PC, I am actually able to remotely control their services without issue.

Per request, I am adding the impersonation code here. It is a little longer so bear with me:

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();
    }
}

I call this code just before attempting to start or stop the service:

Service s = new Service(ServiceName, MachineName);

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

    Impersonation.undoImpersonation();
}

It may be worth noting that I can list the services and get the status of an individual service (as I do here) just fine - it is only when I go to start or stop the service that I run into trouble.

解决方案

Maybe I've found the answer:

In the impersonation method LogonUserA

use LOGON32_LOGON_SERVICE (= 5) instead of LOGON32_LOGON_INTERACTIVE.

Make sure that the user that you're impersonating is the same user that runs the service.

In my case, the user is included in Local Policies --> Start session as service. I have not tested with an user not included in that local policy.

Hope it helps!

这篇关于与ServiceController的和模拟启动远程的Windows服务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-20 20:10