![為什麼 Powershell Runspace 作業中的 Server 2012R2 託管 VM 的 Get-VHD 檔案大小回傳 0?](https://rvso.com/image/718157/%E7%82%BA%E4%BB%80%E9%BA%BC%20Powershell%20Runspace%20%E4%BD%9C%E6%A5%AD%E4%B8%AD%E7%9A%84%20Server%202012R2%20%E8%A8%97%E7%AE%A1%20VM%20%E7%9A%84%20Get-VHD%20%E6%AA%94%E6%A1%88%E5%A4%A7%E5%B0%8F%E5%9B%9E%E5%82%B3%200%EF%BC%9F.png)
我有這個腳本來製作託管在我們的 Hyper-V 叢集上的虛擬機器的 CSV。它工作得很好,我甚至把每個虛擬機分成了一個工作!
附註:我不介意關於如何更有效地進行日程安排的建議。主要問題是一些叢集是 WS 2016,其他叢集是 WS 2012R2,它們需要較舊的 Hyper-V PowerShell 模組。我不確定如何並行化不同的模組,因此我只是獲取每個 Hyper-V 節點的 VM 列表,並行化它們,然後在下一個節點需要時更改模組。
無論如何,我的問題。這是我的腳本。
$numThreads = 4
$ScriptBlock = {
Param (
[string]$Cluster,
[string]$Node,
$VM
)
If ($ADComputer = (Get-ADComputer $VM.Name -Properties OperatingSystem)) {
$OS = $ADComputer.OperatingSystem
}
Else {
$OS = 'Unknown (not on domain)'
}
try {
Return [pscustomobject] @{
Cluster = $Cluster
Node = $Node
Name = $VM.Name
OS = $OS
State = $VM.State
Status = $VM.Status
Uptime = "{0:dd} days {0:hh} hours" -f $VM.Uptime
CPUUsage = $VM.CPUUsage
ProcessorCount = $VM.ProcessorCount
'MemoryDemand (GB)' = [math]::Round( $VM.MemoryDemand / 1GB, 2 )
'MemoryAssigned (GB)' = [math]::Round( $VM.MemoryAssigned / 1GB, 2 )
'VHD Size (GB)' = [math]::Round( ((Get-VHD -ComputerName $Node -VMId $VM.Id).FileSize | Measure-Object -Sum).Sum / 1GB, 2 )
Version = $VM.Version
'VLAN IDs' = ($VM | Select-Object -ExpandProperty NetworkAdapters | Select-Object -ExpandProperty VlanSetting).AccessVlanId -Join ", "
'IP Addresses' = ($VM | Select-Object -ExpandProperty NetworkAdapters).IPAddresses -Join ", "
}
}
catch {
Return [pscustomobject] @{
Cluster = $Cluster
Node = $Node
Name = $VM.Name
State = "Script Fail"
Status = $_.Exception.Message
}
}
}
$RunspacePool = [RunspaceFactory]::CreateRunspacePool(1, $numThreads)
$RunspacePool.Open()
$Jobs = @()
$VMInfoList = @()
ForEach ($Cluster in 'USHOMECLU0', 'USHOMECLU1') {
If ((Get-ADComputer $Cluster -Property OperatingSystem).OperatingSystem -Match '2016') {
Remove-Module Hyper-V
Import-Module Hyper-V -RequiredVersion 2.0.0.0
}
Else {
Remove-Module Hyper-V
Import-Module Hyper-V -RequiredVersion 1.1
}
ForEach ($Node in Get-ClusterNode -Cluster $Cluster) {
Get-VM -ComputerName $Node | ForEach-Object {
$Job = [powershell]::Create().AddScript($ScriptBlock).AddParameter("Cluster", $Cluster).AddParameter("Node", $Node).AddParameter("VM", $_)
$Job.RunspacePool = $RunspacePool
$Jobs += New-Object PSObject -Property @{
Job = $Job
Result = $Job.BeginInvoke()
}
}
}
}
# EndInvoke returns the objects from the background threads
ForEach ($Job in $Jobs) {
$VMInfoList += $Job.Job.EndInvoke($Job.Result)
}
$VMInfoList | Export-Csv -NoTypeInformation C:\PSReports_vms.csv
我遇到的問題是,Windows Server 2012R2 節點上的虛擬機器作業始終傳回 0:
'VHD Size' = ((Get-VHD -ComputerName $Node -VMId $VM.Id).FileSize | Measure-Object -Sum).Sum
但是,對於 Windows Server 2016 節點,所有 VM 都會傳回適當的值。同樣有趣的是,如果我捕獲分配給這些 Server 2012R2 託管 VM 的 VHD 大小的確切表達式(用直接字串替換變數),並在作業的腳本區塊之外執行它,我將獲得準確的值。