Public/Show-HDTDeploymentFailure.ps1
|
function Show-HDTDeploymentFailure { <# .SYNOPSIS Shows the technician why the deployment failed, and reports what they want the machine to do about it. .DESCRIPTION THE SCREEN A FAILED MACHINE NEVER HAD. The reason went into the JSONL, a FATAL line went into a console the payload had hidden, and five seconds later wpeutil powered the machine off. Everything needed to fix it was on a share, in a folder named after a computer that never finished being built, and the person standing in front of the machine had a black screen. MDT shows a summary dialog naming the step; this is HDT's. IT ADDS NO WPF. The window is Show-HDTWizard's - a XAML path, fields applied by name, a button reported - so the failure page is markup and this command is the one decision in it: what each button means. Restart the technician will try again from the top Shut down they are finished with this machine Open CMD they are going to go and look, and the machine must stay on while they do ANYTHING ELSE IS A SHUT DOWN, including a window that answered nothing. A failed machine left running in a room nobody visits is not a kindness - and the technician's PRESS is what keeps it on, never a silence. A WINDOW THAT WILL NOT OPEN IS NOT A SECOND FAILURE. A boot image built without WinPE-NetFx has no PresentationFramework at all, and this command is called on a machine that has ALREADY failed. So the exception is caught, Shown comes back false, and the caller ends the machine as it would have without a screen. .PARAMETER Failure What Get-HDTDeploymentFailure returned. .PARAMETER XamlPath The failure window. X:\HDT\UI\HDTFailure.xaml inside a boot image. .PARAMETER Title The window title. .PARAMETER WizardHost An IWizardHost. Defaults to the real adapter. .PARAMETER FileSystem An IFileSystem, for reading the markup. .INPUTS None. This command does not accept pipeline input. .OUTPUTS System.Management.Automation.PSCustomObject with Action ('Restart', 'Shutdown' or 'CommandPrompt') and Shown. .EXAMPLE $failure = Get-HDTDeploymentFailure -Record $record -LogPath $log.LogPath $answer = Show-HDTDeploymentFailure -Failure $failure -XamlPath 'X:\HDT\UI\HDTFailure.xaml' #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Justification = 'Shows a window and reports the button pressed; it changes no state. A confirmation prompt in front of a technician reading a failure would be a second thing to dismiss.')] [CmdletBinding()] [OutputType([pscustomobject])] param( [Parameter(Mandatory = $true, Position = 0)] [ValidateNotNull()] [object] $Failure, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $XamlPath, [Parameter()] [ValidateNotNullOrEmpty()] [string] $Title = 'Hephaestus Deployment Toolkit', [Parameter()] [AllowNull()] [object] $WizardHost, [Parameter()] [AllowNull()] [object] $FileSystem ) Set-StrictMode -Version Latest $ErrorActionPreference = 'Stop' $field = @() if ($null -ne $Failure.PSObject.Properties['Field']) { $field = @($Failure.Field) } # SHOWN IS PART OF THE ANSWER. A caller that cannot tell "they pressed shut # down" from "there was no window" cannot log the difference, and those two # runs look identical afterwards. $answer = '' $shown = $false try { $result = Show-HDTWizard -XamlPath $XamlPath -Title $Title -Field $field ` -WizardHost $WizardHost -FileSystem $FileSystem $answer = [string] $result.Action $shown = $true } catch { # See the header: this runs on a machine that has already failed. Write-Verbose ("the failure window could not be shown: {0}" -f [string] $_.Exception.Message) } $action = 'Shutdown' if ($answer -eq 'Next') { $action = 'Restart' } if ($answer -eq 'CommandPrompt') { $action = 'CommandPrompt' } return [pscustomobject] @{ Action = $action Shown = $shown } } |