【问题标题】:How to start or stop IIS and also a Windows Service in remote machine using C#如何使用 C# 在远程机器中启动或停止 IIS 以及 Windows 服务
【发布时间】:2016-01-23 12:55:04
【问题描述】:

使用此代码获取异常...即使我在远程机器上拥有管理员权限

class Program
    {
        static void Main(string[] args)
        {
            var sc = new System.ServiceProcess.ServiceController("W3SVC", "10.201.58.114");
            sc.Start();
            sc.WaitForStatus(System.ServiceProcess.ServiceControllerStatus.Running);            
            sc.Stop();
            sc.WaitForStatus(System.ServiceProcess.ServiceControllerStatus.Stopped);
        }
    }

例外

System.ServiceProcess.dll 中出现“System.InvalidOperationException”类型的未处理异常

附加信息:无法在计算机“10.201.58.114”上打开服务控制管理器。此操作可能需要其他权限。

【问题讨论】:

  • 目标系统是否没有安全软件?你会发现有些安全软件可以起到这种作用。
  • 以“管理员身份”运行应用程序有帮助吗?还假设您对提供的 IP 拥有权利...
  • 以管理员身份使用命令提示符:C:\>iisreset.exe <ip address of remote computer>,出现错误为:Access denied, you must be an administrator of the remote computer to use this command. Either have your account added to the administrator local group of the remote computer or to the domain administrator global group. 请注意,我在远程机器上拥有管理员权限,但仍然出现错误。

标签: c#


【解决方案1】:

机器是否在同一个域中?如果不是 machine1 上的 Administrator 不等于 machine2 上的 Administrator,那么这可能是您的问题。

一种可能性是您需要授予该用户访问权限 - 在远程计算机上 - 像这样停止和启动服务:

SUBINACL /SERVICE \\<MACHINE>\W3SVC /GRANT=<MACHINE>\<USER>=TO

在下面第二个代码块的 cmets 中有一个这样的例子(因为我需要这个,即使是在代码中的身份模拟)。

如果这不能解决问题,您可以尝试模拟远程用户。我设法使用以下代码使其正常工作。

首先,新建一个类 WrapperImpersonationContext.cs:

using System;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Security.Permissions;
using System.ComponentModel;

//Version from http://michiel.vanotegem.nl/2006/07/windowsimpersonationcontext-made-easy/

public class WrapperImpersonationContext
{
    [DllImport("advapi32.dll", SetLastError = true)]
    public static extern bool LogonUser(String lpszUsername, String lpszDomain,
        String lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);

    [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
    public extern static bool CloseHandle(IntPtr handle);

    private const int LOGON32_PROVIDER_DEFAULT = 0;
    private const int LOGON32_LOGON_INTERACTIVE = 2;

    private string m_Domain;
    private string m_Password;
    private string m_Username;
    private IntPtr m_Token;

    private WindowsImpersonationContext m_Context = null;


    protected bool IsInContext
    {
        get { return m_Context != null; }
    }

    public WrapperImpersonationContext(string domain, string username, string password)
    {
        m_Domain = domain;
        m_Username = username;
        m_Password = password;
    }

    [PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
    public void Enter()
    {
        if (this.IsInContext) return;
        m_Token = new IntPtr(0);
        try
        {
            m_Token = IntPtr.Zero;
            bool logonSuccessfull = LogonUser(
                m_Username,
                m_Domain,
                m_Password,
                LOGON32_LOGON_INTERACTIVE,
                LOGON32_PROVIDER_DEFAULT,
                ref m_Token);
            if (logonSuccessfull == false)
            {
                int error = Marshal.GetLastWin32Error();
                throw new Win32Exception(error);
            }
            WindowsIdentity identity = new WindowsIdentity(m_Token);
            m_Context = identity.Impersonate();
        }
        catch (Exception exception)
        {
            // Catch exceptions here
        }
    }


    [PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
    public void Leave()
    {
        if (this.IsInContext == false) return;
        m_Context.Undo();

        if (m_Token != IntPtr.Zero) CloseHandle(m_Token);
        m_Context = null;
    }
}

那么您应该能够运行以下命令。请注意,您需要更改机器名称、用户名和密码以匹配您的设置。还要注意 cmets,因为我在此过程中发现了重要的安全设置信息:

//Code for Program.cs demonstrating the identity impersonation for a ServiceController.

using System;
using System.Security.Principal;
using System.ServiceProcess;

namespace RemoteConnectionTest
{
    class MainClass
    {
        public static void Main (string[] args)
        {

            try {

                //Based on the code from http://michiel.vanotegem.nl/2006/07/windowsimpersonationcontext-made-easy/

                Console.WriteLine("Current user: " + WindowsIdentity.GetCurrent().Name);
                //Also worked with the IP address of GARNET (which was the machine name).
                WrapperImpersonationContext context = new WrapperImpersonationContext("GARNET", "TestAdmin1", "password123");
                context.Enter();
                // Execute code under other uses context
                Console.WriteLine("Current user: " + WindowsIdentity.GetCurrent().Name);

                // Code to execute.

                //Try running the following command on the remote server first to ensure
                //the user has the appropriate access (obviously substitute the
                //username and machine name).
                // runas /user:TestAdmin "sc \\GARNET stop W3SVC"

                //Also, make sure the user on the remote server has access for
                //services granted as described here: http://stackoverflow.com/a/5084563/201648
                //Otherwise you may see an error along the lines of:
                //Cannot open W3SVC service on computer '<SERVER>'. ---> System.ComponentModel.Win32Exception: Access is denied
                //For my configuration I had to run the command:
                // SUBINACL /SERVICE \\GARNET\W3SVC /GRANT=GARNET\TestAdmin=TO
                //It's entirely possible that running this command will allow your existing code to work without using impersonation.

                //You may need to install SUBINACL https://www.microsoft.com/en-au/download/details.aspx?id=23510
                //By default SUBINACL will install to C:\Program Files (x86)\Windows Resource Kits\Tools
                //so CD to that directory and then run the SUBINACL command above.

                //Also worked with the IP address of GARNET (which was the machine name).
                var sc = new ServiceController("W3SVC", "GARNET");
                sc.Start();

                sc.WaitForStatus(ServiceControllerStatus.Running);            
                sc.Stop();
                sc.WaitForStatus(ServiceControllerStatus.Stopped);

                //END - code to execute.
                context.Leave();
                Console.WriteLine("Your code ran successfully. Current user: " + WindowsIdentity.GetCurrent().Name);

            } catch (Exception ex) {
                Console.WriteLine("An exception occured - details as follows: {0}", ex.Message);
                Console.WriteLine("The full stack trace is: {0}", ex);
            }

            Console.WriteLine ("Press any key to exit...");
            Console.ReadLine();

        }
    }

}

在您尝试在代码中执行此操作之前,请确保可以使用提供的凭据评估远程计算机,例如通过远程桌面以该用户身份连接。

【讨论】:

  • 错误The type or namespace name 'RemoteAccessHelper' could not be found (are you missing a using directive or an assembly reference?)
  • 教程里的代码看了吗dotnet-assembly.blogspot.com.au/2012/11/…
  • 所以只是为了澄清 1) 确定远程机器的计算机/域名 2) 尝试使用该计算机/域名从运行代码的机器连接到远程机器代码之外的用​​户名和密码,例如使用远程桌面 3) 如果成功,请尝试根据该教程中的代码进行 C# 模拟。另外,您是否确定您是否在域上?如果两台机器都在同一个域上,则可能是其他问题。
  • 两台机器在同一个域。我可以 ping 远程机器但无法连接远程机器我仍然得到与 System.InvalidOperationException 相同的异常
  • 暂时忽略代码。您必须能够在代码之外为所需用户连接到远程计算机,否则此代码将永远无法工作。当我过去这样做时,我已经为用户设置了远程桌面以测试是否存在一些连接问题,然后再尝试使用代码technet.microsoft.com/en-au/library/cc758036(v=ws.10).aspx 执行此操作。除此之外,你能告诉我你在哪里得到那个错误。我现在正在尝试在本地复制它。
【解决方案2】:

听起来您没有添加到本地组管理员中

检查一下

网络本地组管理员

在远程机器上

如果用户不在列表中,则运行

net localgroup 管理员/添加用户

【讨论】:

  • 我的名字已经列在本地管理员组中。但仍然遇到同样的异常。
猜你喜欢
  • 2010-10-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多