通过C#和PowerShell查询SCVMM 2012 R2的最佳方法

时间:2014-05-27 18:29:44

标签: c# powershell

Microsoft指出您使用PowerShell来管理和查询VMM。有很多例子可以在c#中使用PS,没有人指出最新版本或示例代码的PS版本是什么。我们使用我们发现的代码中使用VMM的方法,但在内存消耗方面似乎非常差。在云中执行简单的VM列表会导致应用程序增长近300mb!它只是坐在那里,有时会变得更大。我们正在尽可能地进行所有适当的处理和对象清理。我只是相信在c#中使用PS似乎不是一个非常好的方法。我觉得如果有一个带有API调用的SDK,它会使用更少的内存。

使用当前版本的PS 4.0,从C#中调用PS命令的最有效方法是什么?如果您想要一个示例PS命令,我们可以调用它作为示例,您可以使用以下内容:这将列出云中的所有VM。

Get-SCVMMServer -ComputerName 'vmmserver' -Credential $cred | Get-SCCloud -Name 'cloud name' | Get-VM

1 个答案:

答案 0 :(得分:0)

我目前正在努力解决完全相同的内存问题。但是,我认为我有一个解决方案 - 目前正处于现在的步伐中,所以我不确定发布的解决方案是最佳解决方案还是最终解决方案。我的环境是Windows 2012 R2 Datacenter和SCVMM 2012 R2。

以下是我的发现

考虑到以下脚本在循环中运行或只是被称为反复遍历

If (-Not(Get-Module -Name VirtualMachineManager)) {
    Import-Module -Name VirtualMachineManager
}

[Hashtable]$return = @{}

$vmm = Get-VMMServer -ComputerName $vmmHostname
If ($vmm -eq $null) {
    $return.Code = 1
    $return.Text = "VMM server '$vmmHostname' cannot be accessed."
    $return
    Exit
}

Get-SCVirtualMachine -Name $hostname

我看到以下

  1. 客户端系统中的内存消耗可以继续增长,而不会释放内存。 (即使在当前脚本完成执行之后。)
  2. 与VMM服务器建立的网络连接数(通过在VMM服务器上运行netstat -an观察)也会继续增加。
  3. 最终,新连接需要非常长时间才能建立(30-60秒),或者他们只是完全停止。
  4. 但是,经过我的所有研究和测试后,我发现以下脚本工作正常,并且两者都使内存消耗较低,网络连接数较少(1或2)。 (事实上​​,连接的建立,使用和清理速度足够快,netstat通常甚至不会在列表中显示它。)

    If (-Not(Get-Module -Name VirtualMachineManager)) {
        Import-Module -Name VirtualMachineManager
    }
    
    Get-SCVirtualMachine -VMM $vmmHostname -Name $hostname
    

    此时,由于某些未知原因,密钥似乎是在单个cmdlet上指定VMM服务器,而不是在脚本顶部建立连接。

    就从C#执行脚本而言,我的Framework 4.5.1代码目前看起来像这样

    using (var rs = System.Management.Automation.Runspaces.RunspaceFactory.CreateRunspace()) {
        rs.Open();
    
        using (var ps = PowerShell.Create()) {
            ps.Runspace = rs;
    
            var assembly = System.Reflection.Assembly.GetExecutingAssembly();
            var scriptName = "LabManagement.Scripts.GetVirtualMachineStatus.ps1";
    
            using (var s = assembly.GetManifestResourceStream(scriptName)) {
                using (var reader = new System.IO.StreamReader(s)) {
                    var script = reader.ReadToEnd();
    
                    ps.AddScript(script);
                }
            }
    
            ps.Runspace.SessionStateProxy.SetVariable("vmmHostname", this.ServerName);
            ps.Runspace.SessionStateProxy.SetVariable("hostname", hostname);
    
            var output = ps.Invoke();
    
            ...
            // process output and errors
            ...
    
                rs.Close();
            }
            else {
                rs.Close();
            }
        }
    }
    

    但是,我不确定是否需要显式创建/打开/关闭Runspace对象。最初我只是创建了PowerShell对象。 (由于PS脚本最终在RunSpace中运行,我的内存消耗搜索的一部分是测试,如果没有明确创建RunSpace导致它"在PowerShell对象被清理后坚持下去。)作为后续跟进在将cmdlet参数修复应用于我的所有脚本之后,我将查看是否会影响代码。