2011-09-02 31 views
2

我试图从网站启动远程计算机上的进程。当用户按下网站上的特定按钮时,我需要在远程计算机上启动PowerShell。使用WMI和Win32_Process创建远程进程

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

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

我给运行与网站相关的应用程序池的帐户上的远程VM以下权限: - 在WMI上ROOT \ CIMV2完全权限,所有子命名空间 - 全DCOM权限

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

我基本上遵循下面的文章:

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

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

有没有人有这类问题的经验?

非常感谢

克里斯

+0

真的想说“旋转起来”吧? –

回答

3

尝试使用模拟连接与管理priveleges远程计算机。以下是我为编程模拟创建的课程:

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

非常感谢代码。现在我可能需要它来解决这个问题,我知道发生了什么!

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

如果我从Web服务器外部进行连接,IIS提供给网站的令牌当前无法传递,因为Web服务器未注册到Kerberos。 (我传递了我最近在这里所说的,为了最终解决问题,我需要更好地理解这一点。)

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

感谢您的帮助

+0

如果您觉得有帮助,您应该投票选出答案。 – havardhu

+0

看来你可能不得不[为远程监控启用WMI](http://www.poweradmin.com/help/enableWMI。aspx)以及让事情工作。启用远程监控和[保护远程WMI连接](http://msdn.microsoft.com/en-us/library/aa393266.aspx)的组合似乎对我而言效果不错。尽管如此,仍在研究安全性问题。 – jerhewet