UI/HDTFailure.xaml
|
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Hephaestus Deployment Toolkit" WindowStyle="None" ResizeMode="NoResize" SizeToContent="WidthAndHeight" WindowStartupLocation="CenterScreen" Background="#FF1E1E1E"> <!-- WHAT A TECHNICIAN SEES WHEN A DEPLOYMENT FAILS, and until now that was nothing: 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, under a folder named after a computer that never finished being built. MDT SHOWS A SUMMARY DIALOG NAMING THE STEP, and an admin has read it a hundred times. This is that, in HDT's ground. THE MACHINE DOES NOT POWER OFF WHILE THIS IS UP. The three buttons are the three things a technician actually does next, and the payload obeys whichever was pressed: go and look (Open CMD), try again from the top (Restart), or leave (Shut down). SAME GROUND AS THE WIZARD AND THE PROGRESS SCREEN. A technician meets all three on one machine minutes apart, and they must look like one product: #FF1E1E1E behind, #FF252526 on the card. NOT Topmost, AND A TECHNICIAN AT A BENCH IS WHY. This window used to carry Topmost="True", and the cost of it was the one button on the screen that matters: Open CMD (and F8) launched the command prompt CORRECTLY and it opened BEHIND this window, where it could not be seen, clicked, or reached. A topmost window outranks any non-topmost foreground window, so the prompt was not merely unfocused - it was unreachable, on the screen whose entire purpose is to hand a broken machine back to a human being who can look inside it. AND IT BOUGHT NOTHING IN RETURN. In WinPE there is no shell, no taskbar and no other application: there is nothing for this window to lose itself behind, which is exactly why the attribute was never noticed. HDTProgress.xaml keeps its Topmost for the opposite reason - that board outlives WinPE and draws on a real desktop, where a Start menu opens over it - and Start-HDTDeployment closes it before any prompt can be opened, so it never stands in front of one. TOPMOST IS STATE, NOT MARKUP. A window that hands the machine to another process has to stop outranking it, and an attribute cannot. tests/contract/WinPeWindowReach.Contract.Tests.ps1 holds the rule for every window in this folder. AND THE REFERENCE IMPLEMENTATION SAYS THE SAME, WHICH IS WHY THIS IS A RULE AND NOT ONE BENCH'S OPINION. friendsOfMDT/PSD - MIT licensed, NOTICE.md - clears Topmost on the line before EVERY ShowDialog, under its own comment "always force windows on bottom" (Scripts/PSDWizardNew.psm1:760 and :2995, Scripts/PSDStartLoader.psm1:2780), binds Esc to lower the window (PSDWizardNew.psm1:2764-2767), and where it does raise a window it drives it from a runtime flag rather than markup (PSDStartLoader.psm1:2352). What was derived is that mechanism, not code: HDT deletes the attribute instead of assigning the property, because a window that never outranks the prompt has nothing to undo. NO x:Class AND NO MERGED DICTIONARY: there is no compiler in WinPE, and a second file that must reach the RAM disk intact is a XamlParseException on the one machine nobody can debug. --> <Grid Background="#FF1E1E1E"> <Border Width="900" VerticalAlignment="Center" HorizontalAlignment="Center" Background="#FF252526" BorderBrush="#FF3A3A3C" BorderThickness="1"> <StackPanel Margin="36,30,36,30"> <!-- ============ the grab handle ============ THE HEADLINE IS WHAT YOU DRAG THE WINDOW BY. WindowStyle= "None" is right here - an X on a failure screen is a fourth answer nobody meant to give - but it takes the title bar away, and with it the thing a hand reaches for. A technician in front of a failed machine could not move this window at all: not off a log they wanted to read behind it, not out of the way of a command prompt. New-HDTWizardHost wires DragMove onto whatever is named HDTDragBanner and onto nothing else, and its lookup is null-guarded - so a window without one does not fail, log or warn. It is simply immovable, which is precisely how this screen shipped that way and why the rule now lives in tests/contract/WinPeWindowReach.Contract.Tests.ps1 rather than in one file's memory. The wizard shell, the welcome screen and both credential pages have carried the same named Border since they were written; this is that. IT NEEDS A GROUND TO BE GRABBED AT ALL. A Border with no Background is invisible to hit-testing in WPF, and so is a TextBlock - the mouse would go straight through the headline to the card behind it and no drag would ever start. So it paints the card's own #FF252526: the same colour that was already there, which is why nothing about this screen looks different. No padding, no margin, no border thickness - the three lines below sit exactly where they sat. THE BUTTONS ARE OUTSIDE IT, deliberately. A banner that covered Open CMD would answer a click by moving the window instead of opening the prompt, which is the same defect in a new coat. --> <Border x:Name="HDTDragBanner" Background="#FF252526"> <StackPanel> <!-- RED, ONCE, AT THE TOP. The status line on the progress screen paints failures #FFF48771 and so does this: the same colour means the same thing across the product. --> <TextBlock x:Name="HDTFailureTitleText" Foreground="#FFF48771" FontSize="28" FontWeight="SemiBold" /> <!-- AND THE SAME WINDOW REPORTS A RUN THAT WORKED, because MDT ends a deployment on ONE Deployment Summary rather than two windows to keep in step with each other. TWO HEADLINES, ONE VISIBLE. The colour is the whole reason this is a second TextBlock instead of one line of text that changes: #FFF48771 is what failure looks like everywhere in this product, and a success painted in it reads as a failure that somebody mislabelled. Red only ever means wrong. Which one shows is a Pane flag, the mechanism the host already has - Get-HDTDeploymentFailure decides, and this file only says what the two look like. --> <TextBlock x:Name="HDTFailureSuccessText" Foreground="#FF6FCF97" FontSize="28" FontWeight="SemiBold" Visibility="Collapsed" /> <TextBlock x:Name="HDTFailureSequenceText" Text="" Foreground="#FFCCCCCC" FontSize="15" Margin="0,6,0,0" TextTrimming="CharacterEllipsis" /> </StackPanel> </Border> <Border Height="1" Background="#FF3A3A3C" Margin="0,20,0,20" /> <!-- ============ which step ============ --> <TextBlock x:Name="HDTFailureStepLabel" Foreground="#FF8A8A8A" FontSize="13" /> <TextBlock x:Name="HDTFailureStepText" Text="" Foreground="White" FontSize="18" Margin="0,4,0,0" TextWrapping="Wrap" /> <!-- ============ and why ============ --> <!-- THE REASON IS NOT SUMMARISED AND IT SCROLLS. The pre-flight writes several lines - one per failed check - and the most useful sentence a technician can read is the one the step wrote: "disk 0 carries existing data on volume C (NTFS), D (NTFS), and the step did not declare that it may be replaced" contains the fix. A box that cut it off at one line would send them to the log for the rest. --> <TextBlock x:Name="HDTFailureReasonLabel" Foreground="#FF8A8A8A" FontSize="13" Margin="0,18,0,0" /> <Border x:Name="HDTFailureReasonBox" Background="#FF1E1E1E" BorderBrush="#FF3A3A3C" BorderThickness="1" Margin="0,4,0,0" MaxHeight="220"> <ScrollViewer VerticalScrollBarVisibility="Auto" Padding="12,10,12,10"> <TextBlock x:Name="HDTFailureMessageText" Text="" Foreground="#FFF48771" FontSize="14" TextWrapping="Wrap" FontFamily="Consolas, Courier New" /> </ScrollViewer> </Border> <!-- ============ where the evidence is ============ --> <!-- THE LOG PATH IS ON THE SCREEN BECAUSE X: DIES WITH THE POWER. A technician who writes nothing down and shuts the machine off must still be able to find the run afterwards, and the run id is what names the folder. --> <TextBlock x:Name="HDTFailureLogLabel" Foreground="#FF8A8A8A" FontSize="13" Margin="0,18,0,0" /> <TextBlock x:Name="HDTFailureLogText" Text="" Foreground="#FFCCCCCC" FontSize="13" Margin="0,4,0,0" TextWrapping="Wrap" FontFamily="Consolas, Courier New" /> <TextBlock x:Name="HDTFailureRunText" Text="" Foreground="#FF8A8A8A" FontSize="12" Margin="0,4,0,0" FontFamily="Consolas, Courier New" /> <!-- ============ what happens next ============ --> <!-- THE SAME THREE NAMES THE WIZARD USES, so the host that already knows how to read a window can read this one: HDTOpenCmdButton, HDTNextButton, HDTCancelButton. OPEN CMD IS FIRST ON A FAILURE because that is the reason the failure screen exists - the technician is standing in front of a machine they can still look inside. AND IT IS COLLAPSED ON A SUCCESS, by the same Pane list that collapses Restart and Shut down: a machine that finished has nothing left to diagnose, and the summary offers Finish alone. The '*' column beside it absorbs the space, so Finish stays in the corner either way. F8 still opens a prompt on both - a key nobody can see is not clutter. --> <Grid Margin="0,28,0,0"> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="*" /> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" /> </Grid.ColumnDefinitions> <Button Grid.Column="0" x:Name="HDTOpenCmdButton" MinWidth="130" Height="36" Background="#FF3A3A3C" Foreground="White" BorderBrush="#FF3A3A3C" FontSize="14" /> <Button Grid.Column="2" x:Name="HDTCancelButton" MinWidth="130" Height="36" Margin="0,0,10,0" Background="#FF3A3A3C" Foreground="White" BorderBrush="#FF3A3A3C" FontSize="14" /> <Button Grid.Column="3" x:Name="HDTNextButton" MinWidth="130" Height="36" Background="#FF0E639C" Foreground="White" BorderBrush="#FF0E639C" FontSize="14" /> <!-- MDT'S DEPLOYMENT SUMMARY HAS ONE BUTTON AND IT IS Finish. This window reports both outcomes, so it carries both sets and Get-HDTDeploymentFailure collapses the pair that does not apply: Restart and Shut down on a failure, this on a finished machine. IT SHARES A COLUMN WITH Restart, which is why only one of them is ever visible. Two primary buttons in one corner is a screen asking a technician which of two identical-looking things they meant. WHAT HAPPENS AFTERWARDS IS NOT THIS BUTTON'S ANSWER. HDTFinishAction owns that - MDT's property, MDT's meaning - and this only says the technician has read the screen. Restart and Shut down override it, because a button naming a power state and not producing it is worse than no button. --> <Button Grid.Column="3" x:Name="HDTFinishButton" MinWidth="130" Height="36" Background="#FF0E639C" Foreground="White" BorderBrush="#FF0E639C" FontSize="14" Visibility="Collapsed" /> </Grid> </StackPanel> </Border> </Grid> </Window> |