PowerShell Direct executes PowerShell commands inside a Hyper-V virtual machine through its host, without requiring network connectivity to the guest. A control script connects to the hypervisor, making the technique useful for initial configuration, enabling native remoting, and operating machines in DMZs or cloud environments. section 5.5
Account for these operational constraints:
- Use the virtual machine name expected by the hypervisor; it may differ from the guest operating-system name. section 5.5
- A control script can start stopped virtual machines, run commands, and turn them off afterward, but host capacity may prevent starting all machines simultaneously. section 5.5
- Check machines individually and record connection failures when automation must remain reliable. section 5.5
Listing 5.4 Connecting to all virtual machines from a Hyper-V host
$Credential = Get-Credential #1
$CsvFile = 'P:\Scripts\VSCodeExtensions.csv' #2
$ScriptFile = 'P:\Scripts\Get-VSCodeExtensions.ps1' #3
$ConnectionErrors = "P:\Scripts\VSCodeErrors.csv" #4
$servers = Get-VM #5
foreach ($VM in $servers) {
$TurnOff = $false
if ($VM.State -ne 'Running') { #6
try {
$VM | Start-VM -ErrorAction Stop #7
}
catch {
[pscustomobject]@{
ComputerName = $s
Date = Get-Date
ErrorMsg = $_
} | Export-Csv -Path $ConnectionErrors -Append
continue #8
}
$TurnOff = $true
$timer = [system.diagnostics.stopwatch]::StartNew()
while ($VM.Heartbeat -notmatch '^OK') { #9
if ($timer.Elapsed.TotalSeconds -gt 5) {
break #10
}
}
}
$Command = @{ #11
VMId = $Vm.Id
FilePath = $ScriptFile
Credential = $Credential
ErrorAction = 'Stop'
}
try {
$Results = Invoke-Command @Command #12
$Results | Export-Csv -Path $CsvFile -Append
}
catch {
[pscustomobject]@{ #13
ComputerName = $s
Date = Get-Date
ErrorMsg = $_
} | Export-Csv -Path $ConnectionErrors -Append
}
if ($TurnOff -eq $true) { #14
$VM | Stop-VM
}
} #15
The control-script listing demonstrates credential capture, VM enumeration, conditional startup, exception handling, and CSV error logging. section 5.5
