【问题标题】:Remote process creation using WMI and Win32_Process使用 WMI 和 Win32_Process 创建远程进程
【发布时间】:2011-11-09 07:16:58
【问题描述】:

我正在尝试从网站启动远程计算机上的进程。当用户按下网站上的特定按钮时,我需要在远程机器上启动 PowerShell。

我正在使用 C# 中的 System.Management 连接到远程计算机并创建一个 Win32_Process 对象。当我在 Visual Studio 中以自己的域帐户启动网站并单击按钮时,这一切在两个 VM 之间运行良好。我在两个 VM 的管理员组中,我可以看到脚本尽职尽责地在远程 VM 上运行。

我已将网站部署到系统测试环境,并且该网站现在在我的测试 PowerShell 脚本所在的 Web 服务器或远程框上不是管理员的服务帐户下运行。

我已授予运行与网站关联的应用程序池的帐户在远程 VM 上的以下权限: - 对 WMI 中的 ROOT\CIMV2 和所有子命名空间的完全权限 - 完整的 DCOM 权限

远程虚拟机上没有运行防火墙。

我基本上是按照下面的文章来的:

http://msdn.microsoft.com/en-us/library/aa393266.aspx

我还尝试将运行网站的帐户添加到两个 VM 上的管理员组,但无济于事。当这不起作用时,我不知道下一步该去哪里!

有人遇到过这类问题吗?

非常感谢

克里斯

【问题讨论】:

  • 真的很想说“转起来”吧?

标签: c# asp.net wmi


【解决方案1】:

尝试使用模拟连接到具有管理员权限的远程计算机。这是我为编程模拟创建的一个类:

using System;
using System.Security.Principal;
using System.Diagnostics;
using System.Runtime.InteropServices;

/// <summary> 
/// Leverages the Windows API (advapi32.dll) to programmatically impersonate a user. 
/// </summary> 
public class ImpersonationContext : IDisposable 
{ 
    #region constants 

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

    #endregion 

    #region global variables 

    private WindowsImpersonationContext impersonationContext; 
    private bool impersonating; 

    #endregion 

    #region unmanaged code 

    [DllImport("advapi32.dll")] 
    private 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)] 
    private static extern int DuplicateToken(IntPtr hToken, int impersonationLevel, ref IntPtr hNewToken); 

    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
    private static extern bool RevertToSelf(); 

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

    #endregion 

    #region constructors 

    public ImpersonationContext() 
    { 
        impersonating = false; 
    } 

    /// <summary> 
    /// Overloaded constructor and begins impersonating. 
    /// </summary> 
    public ImpersonationContext(string userName, string password, string domain) 
    { 
        this.BeginImpersonationContext(userName, password, domain); 
    } 

    #endregion 

    #region impersonation methods 

    /// <summary> 
    /// Begins the impersonation context for the specified user. 
    /// </summary> 
    /// <remarks>Don't call this method if you used the overloaded constructor.</remarks> 
    public void BeginImpersonationContext(string userName, string password, string domain) 
    { 
        //initialize token and duplicate variables 
        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) 
                { 
                    using (WindowsIdentity tempWindowsIdentity = new WindowsIdentity(tokenDuplicate)) 
                    { 
                        //begin the impersonation context and mark impersonating true 
                        impersonationContext = tempWindowsIdentity.Impersonate(); 
                        impersonating = true; 
                    } 
                } 
            } 
        } 

        //close the handle to the account token 
        if (token != IntPtr.Zero) 
            CloseHandle(token); 

        //close the handle to the duplicated account token 
        if (tokenDuplicate != IntPtr.Zero) 
            CloseHandle(tokenDuplicate); 
    } 

    /// <summary> 
    /// Ends the current impersonation context. 
    /// </summary> 
    public void EndImpersonationContext() 
    { 
        //if the context exists undo it and dispose of the object 
        if (impersonationContext != null) 
        { 
            //end the impersonation context and dispose of the object 
            impersonationContext.Undo(); 
            impersonationContext.Dispose(); 
        } 

        //mark the impersonation flag false 
        impersonating = false; 
    } 

    #endregion 

    #region properties 

    /// <summary> 
    /// Gets a value indicating whether the impersonation is currently active. 
    /// </summary> 
    public bool Impersonating 
    { 
        get 
        { 
            return impersonating; 
        } 
    } 

    #endregion 

    #region IDisposable implementation 

    ~ImpersonationContext() 
    { 
        Dispose(false); 
    } 

    public void Dispose() 
    { 
        Dispose(true);                
    } 

    protected virtual void Dispose(bool disposing) 
    { 
        if (disposing) 
        { 
            if (impersonationContext != null) 
            { 
                impersonationContext.Undo(); 
                impersonationContext.Dispose(); 
            } 
        } 
    } 

    #endregion     
} 

【讨论】:

    【解决方案2】:

    非常感谢您的代码。既然我知道发生了什么,我很可能需要它来解决问题!

    事实证明,问题与 Kerberos 有关。我发现如果我在本地进入 IIS 管理器并“浏览”网页,远程 WMI 调用就会起作用。该网站设置为模拟连接的用户,如果我在本地连接,身份验证令牌将传递到远程框,一切正常。

    如果我从 Web 服务器外部连接,则当前无法传递由 IIS 提供给网站的令牌,因为 Web 服务器未向 Kerberos 注册。 (我在这里传递我最近被告知的内容。我需要更好地理解这一点才能最终解决问题。)

    我认为这里的解决方案不是传递连接用户的令牌,而是以编程方式禁用 WMI 调用的模拟,并将其作为运行应用程序池的帐户执行。我确信我可以通过快速搜索找到如何做到这一点。

    感谢您的帮助

    【讨论】:

    猜你喜欢
    • 2012-04-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-02
    • 1970-01-01
    • 2014-06-03
    相关资源
    最近更新 更多