diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WriteConsoleCmdlet.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WriteConsoleCmdlet.cs index 2c0ce8f21d0..bf51fd23542 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WriteConsoleCmdlet.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WriteConsoleCmdlet.cs @@ -137,7 +137,6 @@ protected override void ProcessRecord() } this.WriteInformation(informationMessage, new string[] { "PSHOST" }); - this.Host.UI.TranscribeResult(result); } private Boolean _notAppendNewline = false; diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostUserInterfacePromptForChoice.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostUserInterfacePromptForChoice.cs index ac50c61f7c0..06dbde6c016 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostUserInterfacePromptForChoice.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostUserInterfacePromptForChoice.cs @@ -107,7 +107,7 @@ public override int PromptForChoice(string caption, string message, Collection PromptForChoice(string caption, WriteToConsole(PromptColor, RawUI.BackgroundColor, WrapToCurrentWindowWidth(choiceMsg)); ReadLineResult rlResult; - string response = ReadLine(false, string.Empty, out rlResult, true, true); + string response = ReadChoiceResponse(out rlResult); if (rlResult == ReadLineResult.endedOnBreak) { @@ -412,6 +412,19 @@ private void WriteChoiceHelper(string text, ConsoleColor fg, ConsoleColor bg, re WriteToConsole(fg, bg, trimEnd ? text.TrimEnd(null) : text); } + private string ReadChoiceResponse(out ReadLineResult result) + { + result = ReadLineResult.endedOnEnter; + return InternalTestHooks.ForcePromptForChoiceDefaultOption + ? string.Empty + : ReadLine( + endOnTab: false, + initialContent: string.Empty, + result: out result, + calledFromPipeline: true, + transcribeResult: true); + } + private void ShowChoiceHelp(Collection choices, string[,] hotkeysAndPlainLabels) { Dbg.Assert(choices != null, "choices: expected a value"); @@ -473,4 +486,3 @@ private ConsoleColor DefaultPromptColor } } } // namespace - diff --git a/src/System.Management.Automation/engine/MshCommandRuntime.cs b/src/System.Management.Automation/engine/MshCommandRuntime.cs index 90ddd5927a3..5b5b55809c1 100644 --- a/src/System.Management.Automation/engine/MshCommandRuntime.cs +++ b/src/System.Management.Automation/engine/MshCommandRuntime.cs @@ -748,8 +748,7 @@ internal void WriteInformation(InformationRecord record, bool overrideInquire = // if (null == Host || null == Host.UI) { - Diagnostics.Assert(false, "No host in CommandBase.WriteVerbose()"); - throw PSTraceSource.NewInvalidOperationException(); + throw PSTraceSource.NewInvalidOperationException("No host in CommandBase.WriteInformation()"); } CBhost.InternalUI.WriteInformationRecord(record); @@ -821,11 +820,14 @@ internal void WriteInformation(InformationRecord record, bool overrideInquire = CBhost.InternalUI.WriteLine(record.ToString()); } } - else - { - // Only transcribe informational messages here. Transcription of PSHost-targeted messages is done in the InternalUI.Write* methods. - CBhost.InternalUI.TranscribeResult(StringUtil.Format(InternalHostUserInterfaceStrings.InformationFormatString, record.ToString())); - } + } + + // Both informational and PSHost-targeted messages are transcribed here. + // The only difference between these two is that PSHost-targeted messages are transcribed + // even if InformationAction is SilentlyContinue. + if (record.Tags.Contains("PSHOST") || (preference != ActionPreference.SilentlyContinue)) + { + CBhost.InternalUI.TranscribeResult(record.ToString()); } } diff --git a/src/System.Management.Automation/engine/Utils.cs b/src/System.Management.Automation/engine/Utils.cs index 5b108a97978..9d2d9a21ab2 100644 --- a/src/System.Management.Automation/engine/Utils.cs +++ b/src/System.Management.Automation/engine/Utils.cs @@ -1496,6 +1496,7 @@ public static class InternalTestHooks internal static bool UseDebugAmsiImplementation; internal static bool BypassAppLockerPolicyCaching; internal static bool BypassOnlineHelpRetrieval; + internal static bool ForcePromptForChoiceDefaultOption; // Stop/Restart/Rename Computer tests internal static bool TestStopComputer; diff --git a/src/System.Management.Automation/resources/InternalHostUserInterfaceStrings.resx b/src/System.Management.Automation/resources/InternalHostUserInterfaceStrings.resx index b55e117bac8..a40b58cebcb 100644 --- a/src/System.Management.Automation/resources/InternalHostUserInterfaceStrings.resx +++ b/src/System.Management.Automation/resources/InternalHostUserInterfaceStrings.resx @@ -186,9 +186,6 @@ DEBUG: {0} - - INFO: {0} - The host is not currently transcribing. diff --git a/test/powershell/Modules/Microsoft.Powershell.Host/Start-Transcript.Tests.ps1 b/test/powershell/Modules/Microsoft.Powershell.Host/Start-Transcript.Tests.ps1 index 5b4b3ab233d..423c4176eaa 100644 --- a/test/powershell/Modules/Microsoft.Powershell.Host/Start-Transcript.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.Powershell.Host/Start-Transcript.Tests.ps1 @@ -16,7 +16,7 @@ Describe "Start-Transcript, Stop-Transcript tests" -tags "CI" { #Add sample text to the file $content = "This is sample text!" $content | Out-File -FilePath $outputFilePath - Test-Path $outputFilePath | Should be $true + Test-Path $outputFilePath | Should -BeTrue } try { @@ -27,16 +27,16 @@ Describe "Start-Transcript, Stop-Transcript tests" -tags "CI" { if($expectedError) { $ps.hadErrors | Should -BeTrue - $ps.Streams.Error.FullyQualifiedErrorId | Should be $expectedError + $ps.Streams.Error.FullyQualifiedErrorId | Should -Be $expectedError } else { $ps.addscript("Get-Date").Invoke() $ps.commands.clear() $ps.addscript("Stop-Transcript").Invoke() Test-Path $outputFilePath | Should -BeTrue - $outputFilePath | should FileContentMatch "Get-Date" + $outputFilePath | Should -FileContentMatch "Get-Date" if($append) { - $outputFilePath | Should FileContentMatch $content + $outputFilePath | Should -FileContentMatch $content } } } finally { @@ -53,6 +53,7 @@ Describe "Start-Transcript, Stop-Transcript tests" -tags "CI" { AfterEach { Remove-Item $transcriptFilePath -ErrorAction SilentlyContinue + [System.Management.Automation.Internal.InternalTestHooks]::SetTestHook('ForcePromptForChoiceDefaultOption', $False) } It "Should create Transcript file at default path" { @@ -122,8 +123,8 @@ Describe "Start-Transcript, Stop-Transcript tests" -tags "CI" { } } - Test-Path $transcriptFilePath | Should be $true - $transcriptFilePath | Should FileContentMatch "After Dispose" + $transcriptFilePath | Should -Exist + $transcriptFilePath | Should -FileContentMatch "After Dispose" } It "Transcription should be closed if the only runspace gets closed" { @@ -131,20 +132,144 @@ Describe "Start-Transcript, Stop-Transcript tests" -tags "CI" { $powerShellCommand = $powerShellPath + ' -c "start-transcript $transcriptFilePath; Write-Host ''Before Dispose'';"' Invoke-Expression $powerShellCommand - Test-Path $transcriptFilePath | Should -BeTrue - $transcriptFilePath | Should FileContentMatch "Before Dispose" - $transcriptFilePath | Should FileContentMatch "PowerShell transcript end" + $transcriptFilePath | Should -Exist + $transcriptFilePath | Should -FileContentMatch "Before Dispose" + $transcriptFilePath | Should -FileContentMatch "PowerShell transcript end" } It "Transcription should record native command output" { $script = { Start-Transcript -Path $transcriptFilePath hostname - Stop-Transcript } + Stop-Transcript + } + & $script - Test-Path $transcriptFilePath | Should -BeTrue + $transcriptFilePath | Should -Exist $machineName = [System.Environment]::MachineName - $transcriptFilePath | Should FileContentMatch $machineName + $transcriptFilePath | Should -FileContentMatch $machineName + } + + It "Transcription should record Write-Information output when InformationAction is set to Continue" { + [String]$message = New-Guid + $script = { + Start-Transcript -Path $transcriptFilePath + Write-Information -Message $message -InformationAction Continue + Stop-Transcript + } + + & $script + + $transcriptFilePath | Should -Exist + $transcriptFilePath | Should -Not -FileContentMatch "INFO: " + $transcriptFilePath | Should -FileContentMatch $message + } + + It "Transcription should not record Write-Information output when InformationAction is set to SilentlyContinue" { + [String]$message = New-Guid + $script = { + Start-Transcript -Path $transcriptFilePath + Write-Information -Message $message -InformationAction SilentlyContinue + Stop-Transcript + } + + & $script + + $transcriptFilePath | Should -Exist + $transcriptFilePath | Should -Not -FileContentMatch "INFO: " + $transcriptFilePath | Should -Not -FileContentMatch $message + } + + It "Transcription should not record Write-Information output when InformationAction is set to Ignore" { + [String]$message = New-Guid + $script = { + Start-Transcript -Path $transcriptFilePath + Write-Information -Message $message -InformationAction Ignore + Stop-Transcript + } + + & $script + + $transcriptFilePath | Should -Exist + $transcriptFilePath | Should -Not -FileContentMatch "INFO: " + $transcriptFilePath | Should -Not -FileContentMatch $message + } + + It "Transcription should record Write-Information output in correct order when InformationAction is set to Inquire" { + [String]$message = New-Guid + $newLine = [System.Environment]::NewLine + $expectedContent = "$message$($newLine)Confirm$($newLine)Continue with this operation?" + $script = { + [System.Management.Automation.Internal.InternalTestHooks]::SetTestHook('ForcePromptForChoiceDefaultOption', $True) + Start-Transcript -Path $transcriptFilePath + Write-Information -Message $message -InformationAction Inquire + Stop-Transcript + } + + & $script + + $transcriptFilePath | Should -Exist + $transcriptFilePath | Should -Not -FileContentMatch "INFO: " + $transcriptFilePath | Should -FileContentMatchMultiline $expectedContent + } + + It "Transcription should record Write-Host output when InformationAction is set to Continue" { + [String]$message = New-Guid + $script = { + Start-Transcript -Path $transcriptFilePath + Write-Host -Message $message -InformationAction Continue + Stop-Transcript + } + + & $script + + $transcriptFilePath | Should -Exist + $transcriptFilePath | Should -FileContentMatch $message + } + + It "Transcription should record Write-Host output when InformationAction is set to SilentlyContinue" { + [String]$message = New-Guid + $script = { + Start-Transcript -Path $transcriptFilePath + Write-Host -Message $message -InformationAction SilentlyContinue + Stop-Transcript + } + + & $script + + $transcriptFilePath | Should -Exist + $transcriptFilePath | Should -FileContentMatch $message + } + + It "Transcription should not record Write-Host output when InformationAction is set to Ignore" { + [String]$message = New-Guid + $script = { + Start-Transcript -Path $transcriptFilePath + Write-Host -Message $message -InformationAction Ignore + Stop-Transcript + } + + & $script + + $transcriptFilePath | Should -Exist + $transcriptFilePath | Should -Not -FileContentMatch $message + } + + It "Transcription should record Write-Host output in correct order when InformationAction is set to Inquire" { + [String]$message = New-Guid + $newLine = [System.Environment]::NewLine + $expectedContent = "$message$($newLine)Confirm$($newLine)Continue with this operation?" + $script = { + [System.Management.Automation.Internal.InternalTestHooks]::SetTestHook('ForcePromptForChoiceDefaultOption', $True) + Start-Transcript -Path $transcriptFilePath + Write-Host -Message $message -InformationAction Inquire + Stop-Transcript + } + + & $script + + $transcriptFilePath | Should -Exist + $transcriptFilePath | Should -FileContentMatchMultiline $expectedContent } }