private/output/Add-InputProviders.ps1
|
function Add-InputProviders { <# .SYNOPSIS Configures all input providers for AsyncExecutor. InputProvders map legacy console input (Read-Host, Get-Credential, PromptForChoice) to WPF dialog equivalents. #> [CmdletBinding()] param( [Parameter(Mandatory)] [object]$Executor, [System.Windows.Window]$Window, [scriptblock]$ClearHostAction, [switch]$DebugEnabled ) $isDebug = $DebugEnabled # Input Provider for Read-Host $Executor.InputProvider = { param($PromptText) if ($isDebug) { [Console]::WriteLine("[DEBUG] Read-Host invoked - Prompt='$PromptText'") } # Suspend topmost so the dialog isn't trapped behind a pinned output window $wasPinned = $Window -and $Window.Topmost if ($wasPinned) { $Window.Topmost = $false # Brief delay lets pending UI work flush before the modal dialog takes over Start-Sleep -Milliseconds 500 } # Detect native Pause command (calls Read-Host with this exact prompt) $isPause = $PromptText -eq 'Press Enter to continue...' -or $PromptText -eq 'Press any key to continue . . .' if ($isPause) { if ($isDebug) { [Console]::WriteLine('[DEBUG] Detected Pause pattern') } Show-UiMessageDialog -Title 'Paused' -Message 'Press OK to continue...' -Buttons OK -Icon Info | Out-Null if ($wasPinned) { $Window.Topmost = $true } return '' } $msg = if (![string]::IsNullOrWhiteSpace($PromptText)) { $PromptText } else { 'The running script is requesting input.' } $result = Show-UiInputDialog -Title 'Script Input Required' -Prompt $msg if ($isDebug) { [Console]::WriteLine("[DEBUG] Read-Host returned: $(if ($result) { '<value>' } else { '<empty>' })") } if ($wasPinned) { $Window.Topmost = $true } return $result }.GetNewClosure() # Secure Input Provider for Get-Credential password prompts $Executor.SecureInputProvider = { param($PromptText) if ($isDebug) { [Console]::WriteLine("[DEBUG] Read-Host -AsSecureString - Prompt='$PromptText'") } $wasPinned = $Window -and $Window.Topmost if ($wasPinned) { $Window.Topmost = $false Start-Sleep -Milliseconds 500 } $msg = if (![string]::IsNullOrWhiteSpace($PromptText)) { $PromptText } else { 'Script is requesting a password.' } $secureInput = Show-UiInputDialog -Title 'Secure Input Required' -Prompt $msg -Password if ($wasPinned) { $Window.Topmost = $true } if ($secureInput) { if ($isDebug) { [Console]::WriteLine('[DEBUG] Secure input received') } # -Password now returns SecureString directly if ($secureInput -is [System.Security.SecureString]) { return $secureInput } return ConvertTo-SecureString $secureInput -AsPlainText -Force } if ($isDebug) { [Console]::WriteLine('[DEBUG] Secure input cancelled/empty') } return [System.Security.SecureString]::new() }.GetNewClosure() # Choice Provider for -Confirm prompts and ShouldProces $Executor.ChoiceProvider = { param($Caption, $Message, $Choices, $DefaultChoice) if ($isDebug) { [Console]::WriteLine("[DEBUG] PromptForChoice invoked - Caption='$Caption', Choices=$($Choices.Count), Default=$DefaultChoice") } $wasPinned = $Window -and $Window.Topmost if ($wasPinned) { $Window.Topmost = $false Start-Sleep -Milliseconds 500 } $result = Show-UiChoiceDialog -Caption $Caption -Message $Message -Choices $Choices -DefaultChoice $DefaultChoice if ($isDebug) { [Console]::WriteLine("[DEBUG] PromptForChoice returned: $result") } if ($wasPinned) { $Window.Topmost = $true } return $result }.GetNewClosure() # Credential Provider for Get-Credential $Executor.CredentialProvider = { param($Caption, $Message, $UserName, $TargetName) if ($isDebug) { [Console]::WriteLine("[DEBUG] Get-Credential invoked - UserName='$UserName', Target='$TargetName'") } $wasPinned = $Window -and $Window.Topmost if ($wasPinned) { $Window.Topmost = $false Start-Sleep -Milliseconds 500 } $result = Show-UiCredentialDialog -Caption $Caption -Message $Message -UserName $UserName -TargetName $TargetName if ($isDebug) { [Console]::WriteLine("[DEBUG] Get-Credential returned: $(if ($result) { 'PSCredential' } else { '<cancelled>' })") } if ($wasPinned) { $Window.Topmost = $true } return $result }.GetNewClosure() # Prompt Provider for multi-field prompts $Executor.PromptProvider = { param($Caption, $Message, $Descriptions) if ($isDebug) { [Console]::WriteLine("[DEBUG] Prompt invoked - Caption='$Caption', Fields=$($Descriptions.Count)") } $wasPinned = $Window -and $Window.Topmost if ($wasPinned) { $Window.Topmost = $false Start-Sleep -Milliseconds 500 } $result = Show-UiPromptDialog -Caption $Caption -Message $Message -Descriptions $Descriptions if ($isDebug) { [Console]::WriteLine("[DEBUG] Prompt returned: $(if ($result) { "$($result.Count) values" } else { '<cancelled>' })") } if ($wasPinned) { $Window.Topmost = $true } return $result }.GetNewClosure() # ReadKey Provider for "Press any key to continue" patterns $Executor.ReadKeyProvider = { param($Options) if ($isDebug) { [Console]::WriteLine('[DEBUG] ReadKey invoked') } $wasPinned = $Window -and $Window.Topmost if ($wasPinned) { $Window.Topmost = $false Start-Sleep -Milliseconds 500 } Show-UiMessageDialog -Title 'Continue' -Message 'Press OK to continue...' -Buttons OK -Icon Info if ($isDebug) { [Console]::WriteLine('[DEBUG] ReadKey acknowledged') } if ($wasPinned) { $Window.Topmost = $true } }.GetNewClosure() # ClearHost Provider for Clear-Host cmdlet if ($ClearHostAction) { $Executor.ClearHostProvider = { if ($isDebug) { [Console]::WriteLine('[DEBUG] Clear-Host invoked') } & $ClearHostAction }.GetNewClosure() } else { $Executor.ClearHostProvider = { }.GetNewClosure() } } |