Private/Show-ADTInstallationPromptClassic.ps1
#----------------------------------------------------------------------------- # # MARK: Show-ADTInstallationPromptClassic # #----------------------------------------------------------------------------- function Show-ADTInstallationPromptClassic { [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'formInstallationPromptStartLocation', Justification = "This parameter is used within delegates that PSScriptAnalyzer has no visibility of. See https://github.com/PowerShell/PSScriptAnalyzer/issues/1472 for more details.")] [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', 'UnboundArguments', Justification = "This parameter is just to trap any superfluous input at the end of the function's call.")] [CmdletBinding()] [OutputType([System.String])] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.String]$Title, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.String]$Message, [Parameter(Mandatory = $false)] [ValidateSet('Left', 'Center', 'Right')] [System.String]$MessageAlignment = 'Center', [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [System.String]$ButtonRightText, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [System.String]$ButtonLeftText, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [System.String]$ButtonMiddleText, [Parameter(Mandatory = $false)] [ValidateSet('Application', 'Asterisk', 'Error', 'Exclamation', 'Hand', 'Information', 'Question', 'Shield', 'Warning', 'WinLogo')] [System.String]$Icon, [Parameter(Mandatory = $false)] [System.Management.Automation.SwitchParameter]$PersistPrompt, [Parameter(Mandatory = $false)] [System.Management.Automation.SwitchParameter]$MinimizeWindows, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.UInt32]$Timeout, [Parameter(Mandatory = $false)] [System.Management.Automation.SwitchParameter]$NoExitOnTimeout, [Parameter(Mandatory = $false)] [System.Management.Automation.SwitchParameter]$NotTopMost, [Parameter(Mandatory = $false, ValueFromRemainingArguments = $true, DontShow = $true)] [ValidateNotNullOrEmpty()] [System.Collections.Generic.List[System.Object]]$UnboundArguments ) # Set up some default values. $controlSize = [System.Drawing.Size]::new($Script:Dialogs.Classic.Width, 0) $paddingNone = [System.Windows.Forms.Padding]::new(0, 0, 0, 0) $buttonSize = [System.Drawing.Size]::new(130, 24) $adtEnv = Get-ADTEnvironment $adtConfig = Get-ADTConfig # Define events for form windows. $installPromptTimer_Tick = { Write-ADTLogEntry -Message 'Installation action not taken within a reasonable amount of time.' $buttonAbort.PerformClick() } $installPromptTimerPersist_Tick = { $formInstallationPrompt.WindowState = [System.Windows.Forms.FormWindowState]::Normal $formInstallationPrompt.TopMost = !$NotTopMost $formInstallationPrompt.Location = $formInstallationPromptStartLocation $formInstallationPrompt.BringToFront() } $formInstallationPrompt_FormClosed = { # Remove all event handlers from the controls. $installPromptTimer.remove_Tick($installPromptTimer_Tick) $installPromptTimer.Dispose() $installPromptTimer = $null $installPromptTimerPersist.remove_Tick($installPromptTimerPersist_Tick) $installPromptTimerPersist.Dispose() $installPromptTimerPersist = $null $formInstallationPrompt.remove_Load($formInstallationPrompt_Load) $formInstallationPrompt.remove_FormClosed($formInstallationPrompt_FormClosed) $formInstallationPrompt.Dispose() $formInstallationPrompt = $null } $formInstallationPrompt_Load = { # Disable the X button. try { Disable-ADTWindowCloseButton -WindowHandle $formInstallationPrompt.Handle } catch { # Not a terminating error if we can't disable the button. Just disable the Control Box instead. Write-ADTLogEntry 'Failed to disable the Close button. Disabling the Control Box instead.' -Severity 2 $formInstallationPrompt.ControlBox = $false } # Correct the initial state of the form to prevent the .NET maximized form issue. $formInstallationPrompt.WindowState = [System.Windows.Forms.FormWindowState]::Normal $formInstallationPrompt.BringToFront() # Get the start position of the form so we can return the form to this position if PersistPrompt is enabled. $formInstallationPromptStartLocation = $formInstallationPrompt.Location } # Built out timer $installPromptTimer = [System.Windows.Forms.Timer]::new() $installPromptTimer.Interval = $Timeout * 1000 $installPromptTimer.add_Tick($installPromptTimer_Tick) # Built out timer for Persist Prompt mode. $installPromptTimerPersist = [System.Windows.Forms.Timer]::new() $installPromptTimerPersist.Interval = $adtConfig.UI.DefaultPromptPersistInterval * 1000 $installPromptTimerPersist.add_Tick($installPromptTimerPersist_Tick) # Picture Banner. $pictureBanner = [System.Windows.Forms.PictureBox]::new() $pictureBanner.SizeMode = [System.Windows.Forms.PictureBoxSizeMode]::Zoom $pictureBanner.MinimumSize = $pictureBanner.ClientSize = $pictureBanner.MaximumSize = [System.Drawing.Size]::new($Script:Dialogs.Classic.Width, $Script:Dialogs.Classic.BannerHeight) $pictureBanner.Location = [System.Drawing.Point]::new(0, 0) $pictureBanner.Name = 'PictureBanner' $pictureBanner.Image = $Script:Dialogs.Classic.Assets.Banner $pictureBanner.Margin = $paddingNone $pictureBanner.TabStop = $false # Label Text. $labelMessage = [System.Windows.Forms.Label]::new() $labelMessage.MinimumSize = $labelMessage.ClientSize = $labelMessage.MaximumSize = [System.Drawing.Size]::new(381, 0) $labelMessage.Margin = [System.Windows.Forms.Padding]::new(0, 10, 0, 5) $labelMessage.Padding = [System.Windows.Forms.Padding]::new(20, 0, 20, 0) $labelMessage.Anchor = [System.Windows.Forms.AnchorStyles]::None $labelMessage.Font = $Script:Dialogs.Classic.Font $labelMessage.Name = 'LabelMessage' $labelMessage.Text = $Message $labelMessage.TextAlign = [System.Drawing.ContentAlignment]::"Middle$MessageAlignment" $labelMessage.TabStop = $false $labelMessage.AutoSize = $true # Picture Icon. if ($Icon) { $pictureIcon = [System.Windows.Forms.PictureBox]::new() $pictureIcon.SizeMode = [System.Windows.Forms.PictureBoxSizeMode]::CenterImage $pictureIcon.MinimumSize = $pictureIcon.ClientSize = $pictureIcon.MaximumSize = [System.Drawing.Size]::new(64, 32) $pictureIcon.Margin = [System.Windows.Forms.Padding]::new(0, 10, 0, 5) $pictureIcon.Padding = [System.Windows.Forms.Padding]::new(24, 0, 8, 0) $pictureIcon.Anchor = [System.Windows.Forms.AnchorStyles]::None $pictureIcon.Name = 'PictureIcon' $pictureIcon.Image = ([System.Drawing.SystemIcons]::$Icon).ToBitmap() $pictureIcon.TabStop = $false $pictureIcon.Height = $labelMessage.Height } # Button Abort (Hidden). $buttonAbort = [System.Windows.Forms.Button]::new() $buttonAbort.MinimumSize = $buttonAbort.ClientSize = $buttonAbort.MaximumSize = [System.Drawing.Size]::new(0, 0) $buttonAbort.Margin = $buttonAbort.Padding = $paddingNone $buttonAbort.DialogResult = [System.Windows.Forms.DialogResult]::Abort $buttonAbort.Name = 'ButtonAbort' $buttonAbort.Font = $Script:Dialogs.Classic.Font $buttonAbort.BackColor = [System.Drawing.Color]::Transparent $buttonAbort.ForeColor = [System.Drawing.Color]::Transparent $buttonAbort.FlatAppearance.BorderSize = 0 $buttonAbort.FlatAppearance.MouseDownBackColor = [System.Drawing.Color]::Transparent $buttonAbort.FlatAppearance.MouseOverBackColor = [System.Drawing.Color]::Transparent $buttonAbort.FlatStyle = [System.Windows.Forms.FlatStyle]::System $buttonAbort.TabStop = $false $buttonAbort.Visible = $true # Has to be set visible so we can call Click on it. $buttonAbort.UseVisualStyleBackColor = $true # Button Default (Hidden). $buttonDefault = [System.Windows.Forms.Button]::new() $buttonDefault.MinimumSize = $buttonDefault.ClientSize = $buttonDefault.MaximumSize = [System.Drawing.Size]::new(0, 0) $buttonDefault.Margin = $buttonDefault.Padding = $paddingNone $buttonDefault.Name = 'buttonDefault' $buttonDefault.Font = $Script:Dialogs.Classic.Font $buttonDefault.BackColor = [System.Drawing.Color]::Transparent $buttonDefault.ForeColor = [System.Drawing.Color]::Transparent $buttonDefault.FlatAppearance.BorderSize = 0 $buttonDefault.FlatAppearance.MouseDownBackColor = [System.Drawing.Color]::Transparent $buttonDefault.FlatAppearance.MouseOverBackColor = [System.Drawing.Color]::Transparent $buttonDefault.FlatStyle = [System.Windows.Forms.FlatStyle]::System $buttonDefault.TabStop = $false $buttonDefault.Enabled = $false $buttonDefault.Visible = $true # Has to be set visible so we can call Click on it. $buttonDefault.UseVisualStyleBackColor = $true # FlowLayoutPanel. $flowLayoutPanel = [System.Windows.Forms.FlowLayoutPanel]::new() $flowLayoutPanel.SuspendLayout() $flowLayoutPanel.MinimumSize = $flowLayoutPanel.ClientSize = $flowLayoutPanel.MaximumSize = $controlSize $flowLayoutPanel.Location = [System.Drawing.Point]::new(0, $Script:Dialogs.Classic.BannerHeight) $flowLayoutPanel.AutoSize = $true $flowLayoutPanel.AutoSizeMode = [System.Windows.Forms.AutoSizeMode]::GrowAndShrink $flowLayoutPanel.Anchor = [System.Windows.Forms.AnchorStyles]::Top -bor [System.Windows.Forms.AnchorStyles]::Left $flowLayoutPanel.WrapContents = $true $flowLayoutPanel.Margin = $flowLayoutPanel.Padding = $paddingNone # Make sure label text is positioned correctly before adding it. if ($Icon) { $labelMessage.Padding = [System.Windows.Forms.Padding]::new(0, 0, 10, 0) $labelMessage.Location = [System.Drawing.Point]::new(64, 0) $pictureIcon.Location = [System.Drawing.Point]::new(0, 0) $flowLayoutPanel.Controls.Add($pictureIcon) } else { $labelMessage.Padding = [System.Windows.Forms.Padding]::new(10, 0, 10, 0) $labelMessage.Location = [System.Drawing.Point]::new(0, 0) $labelMessage.MinimumSize = $labelMessage.ClientSize = $labelMessage.MaximumSize = $controlSize } $flowLayoutPanel.Controls.Add($labelMessage) # Add in remaining controls and resume object. if ($ButtonLeftText -or $ButtonMiddleText -or $ButtonRightText) { # ButtonsPanel. $panelButtons = [System.Windows.Forms.Panel]::new() $panelButtons.SuspendLayout() $panelButtons.MinimumSize = $panelButtons.ClientSize = $panelButtons.MaximumSize = [System.Drawing.Size]::new($Script:Dialogs.Classic.Width, 39) $panelButtons.Margin = [System.Windows.Forms.Padding]::new(0, 10, 0, 0) $panelButtons.AutoSize = $true if ($Icon) { $panelButtons.Location = [System.Drawing.Point]::new(64, 0) } else { $panelButtons.Padding = $paddingNone } # Build out and add the buttons if we have any. if ($ButtonLeftText) { # Button Left. $buttonLeft = [System.Windows.Forms.Button]::new() $buttonLeft.MinimumSize = $buttonLeft.ClientSize = $buttonLeft.MaximumSize = $buttonSize $buttonLeft.Margin = $buttonLeft.Padding = $paddingNone $buttonLeft.Location = [System.Drawing.Point]::new(14, 4) $buttonLeft.DialogResult = [System.Windows.Forms.DialogResult]::No $buttonLeft.Font = $Script:Dialogs.Classic.Font $buttonLeft.Name = 'ButtonLeft' $buttonLeft.Text = $ButtonLeftText $buttonLeft.TabIndex = 0 $buttonLeft.AutoSize = $false $buttonLeft.UseVisualStyleBackColor = $true $panelButtons.Controls.Add($buttonLeft) } if ($ButtonMiddleText) { # Button Middle. $buttonMiddle = [System.Windows.Forms.Button]::new() $buttonMiddle.MinimumSize = $buttonMiddle.ClientSize = $buttonMiddle.MaximumSize = $buttonSize $buttonMiddle.Margin = $buttonMiddle.Padding = $paddingNone $buttonMiddle.Location = [System.Drawing.Point]::new(160, 4) $buttonMiddle.DialogResult = [System.Windows.Forms.DialogResult]::Ignore $buttonMiddle.Font = $Script:Dialogs.Classic.Font $buttonMiddle.Name = 'ButtonMiddle' $buttonMiddle.Text = $ButtonMiddleText $buttonMiddle.TabIndex = 1 $buttonMiddle.AutoSize = $false $buttonMiddle.UseVisualStyleBackColor = $true $panelButtons.Controls.Add($buttonMiddle) } if ($ButtonRightText) { # Button Right. $buttonRight = [System.Windows.Forms.Button]::new() $buttonRight.MinimumSize = $buttonRight.ClientSize = $buttonRight.MaximumSize = $buttonSize $buttonRight.Margin = $buttonRight.Padding = $paddingNone $buttonRight.Location = [System.Drawing.Point]::new(306, 4) $buttonRight.DialogResult = [System.Windows.Forms.DialogResult]::Yes $buttonRight.Font = $Script:Dialogs.Classic.Font $buttonRight.Name = 'ButtonRight' $buttonRight.Text = $ButtonRightText $buttonRight.TabIndex = 2 $buttonRight.AutoSize = $false $buttonRight.UseVisualStyleBackColor = $true $panelButtons.Controls.Add($buttonRight) } # Add the button panel in if we have buttons. if ($panelButtons.Controls.Count) { $panelButtons.ResumeLayout() $flowLayoutPanel.Controls.Add($panelButtons) } } $flowLayoutPanel.ResumeLayout() # Form Installation Prompt. $formInstallationPromptStartLocation = $null $formInstallationPrompt = [System.Windows.Forms.Form]::new() $formInstallationPrompt.SuspendLayout() $formInstallationPrompt.ClientSize = $controlSize $formInstallationPrompt.Margin = $formInstallationPrompt.Padding = $paddingNone $formInstallationPrompt.Font = $Script:Dialogs.Classic.Font $formInstallationPrompt.Name = 'InstallPromptForm' $formInstallationPrompt.Text = $Title $formInstallationPrompt.AutoScaleMode = [System.Windows.Forms.AutoScaleMode]::Font $formInstallationPrompt.AutoScaleDimensions = [System.Drawing.SizeF]::new(7, 15) $formInstallationPrompt.StartPosition = [System.Windows.Forms.FormStartPosition]::CenterScreen $formInstallationPrompt.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::Fixed3D $formInstallationPrompt.MaximizeBox = $false $formInstallationPrompt.MinimizeBox = $false $formInstallationPrompt.TopMost = !$NotTopMost $formInstallationPrompt.TopLevel = $true $formInstallationPrompt.AutoSize = $true $formInstallationPrompt.Icon = $Script:Dialogs.Classic.Assets.Icon $formInstallationPrompt.Controls.Add($pictureBanner) $formInstallationPrompt.Controls.Add($buttonAbort) $formInstallationPrompt.Controls.Add($buttonDefault) $formInstallationPrompt.Controls.Add($flowLayoutPanel) $formInstallationPrompt.add_Load($formInstallationPrompt_Load) $formInstallationPrompt.add_FormClosed($formInstallationPrompt_FormClosed) $formInstallationPrompt.AcceptButton = $buttonDefault $formInstallationPrompt.ActiveControl = $buttonDefault $formInstallationPrompt.ResumeLayout() # Start the timer. $installPromptTimer.Start() if ($PersistPrompt) { $installPromptTimerPersist.Start() } # Show the prompt synchronously. If user cancels, then keep showing it until user responds using one of the buttons. do { # Minimize all other windows if ($MinimizeWindows) { $null = $adtEnv.ShellApp.MinimizeAll() } # Show the Form $formResult = $formInstallationPrompt.ShowDialog() } until ($formResult -match '^(Yes|No|Ignore|Abort)$') # Return the button text to the caller. switch ($formResult) { Yes { return $ButtonRightText } No { return $ButtonLeftText } Ignore { return $ButtonMiddleText } Abort { # Restore minimized windows. if ($MinimizeWindows) { $null = $adtEnv.ShellApp.UndoMinimizeAll() } if (!$NoExitOnTimeout) { if (Test-ADTSessionActive) { Close-ADTSession -ExitCode $adtConfig.UI.DefaultExitCode } } else { Write-ADTLogEntry -Message 'UI timed out but -NoExitOnTimeout specified. Continue...' } break } } } |