Private/Invoke-GuestScript.ps1
|
function Invoke-GuestScript { <# .SYNOPSIS Run a short PowerShell snippet inside the guest through Azure Run Command .DESCRIPTION Wraps Invoke-AzVMRunCommand (RunPowerShellScript) and normalises the result into Success / Output / Error. Success means the Run Command itself executed; the caller decides what the output means. Only short-lived commands go through here, never the upgrade itself (ADR 0001). The snippet executes under Windows PowerShell 5.1 inside the VM, so script text passed in must not use PowerShell 7 syntax. #> [CmdletBinding()] [OutputType([pscustomobject])] param( [Parameter(Mandatory)][string]$ResourceGroupName, [Parameter(Mandatory)][string]$VMName, [Parameter(Mandatory)][string]$ScriptText, [Parameter()][hashtable]$Parameter ) $tempFile = Join-Path ([System.IO.Path]::GetTempPath()) ("ipu-{0}.ps1" -f [guid]::NewGuid()) try { # UTF-8 without BOM: a BOM would be treated as part of the first statement by the guest. [System.IO.File]::WriteAllText($tempFile, $ScriptText, [System.Text.UTF8Encoding]::new($false)) $invokeParams = @{ ResourceGroupName = $ResourceGroupName VMName = $VMName CommandId = 'RunPowerShellScript' ScriptPath = $tempFile ErrorAction = 'Stop' # Probes are read-only and must run even when a caller has -WhatIf set. WhatIf = $false Confirm = $false } if ($Parameter -and $Parameter.Count -gt 0) { $stringParams = @{} foreach ($key in $Parameter.Keys) { $stringParams[$key] = [string]$Parameter[$key] } $invokeParams['Parameter'] = $stringParams } $result = Invoke-AzVMRunCommand @invokeParams $stdOut = ($result.Value | Where-Object { $_.Code -like '*StdOut*' } | Select-Object -ExpandProperty Message) -join "`n" $stdErr = ($result.Value | Where-Object { $_.Code -like '*StdErr*' } | Select-Object -ExpandProperty Message) -join "`n" Write-Verbose "[$VMName] Run Command stdout: $($stdOut.Trim())" if (-not [string]::IsNullOrWhiteSpace($stdErr)) { Write-Verbose "[$VMName] Run Command stderr: $($stdErr.Trim())" } return [pscustomobject]@{ Success = $true Output = $stdOut.Trim() Error = $stdErr.Trim() } } catch { Write-Verbose "[$VMName] Run Command invocation failed: $($_.Exception.Message)" return [pscustomobject]@{ Success = $false; Output = ''; Error = $_.Exception.Message } } finally { if (Test-Path -LiteralPath $tempFile) { Remove-Item -LiteralPath $tempFile -Force -ErrorAction SilentlyContinue } } } |