如何使用 C# 在远程计算机中启动或停止 IIS 和 Windows 服务

本文关键字:IIS 服务 Windows 启动 何使用 计算机 | 更新日期: 2023-09-27 18:31:26

使用此代码获取异常...即使我在远程计算机中具有管理员权限

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 中发生类型为"System.InvalidOperationException"的未处理异常.dll

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

如何使用 C# 在远程计算机中启动或停止 IIS 和 Windows 服务

计算机是否位于同一域中?如果机器 1 上没有AdministratorAdministrator机器 2 上不等同,因此这可能是您的问题。

一种可能性是,您需要在远程计算机上为此用户授予访问权限,以停止和启动服务,如下所示:

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

在下面第二个代码块的注释中有一个示例(因为即使使用代码内标识模拟,我也需要这个)。

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

首先,创建一个新类 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;
    }
}

然后,您应该能够运行以下内容。请注意,您需要更改计算机名称、用户名和密码以匹配您的设置。还要注意评论,因为我在此过程中发现了重要的安全设置信息:

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

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

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

检查这个

网络本地组管理员

在远程计算机上

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

网络本地组管理员/添加用户