diff --git a/src/System.Management.Automation/engine/InitialSessionState.cs b/src/System.Management.Automation/engine/InitialSessionState.cs index ba5021082..f8dcd5e0d 100644 --- a/src/System.Management.Automation/engine/InitialSessionState.cs +++ b/src/System.Management.Automation/engine/InitialSessionState.cs @@ -4177,10 +4177,36 @@ param( } elseif ($help -ne $null) { + $customPagerCommand = """" + $customPagerCommandArgs = """" + $customPagerCommandLine = """" + + if ($env:PAGER) + { + $customPagerCommandLine = $env:PAGER + + # Split the command line into tokens, respecting quoting. + $customPagerCommand, $customPagerCommandArgs = & { Write-Output -- $customPagerCommandLine } + + # See if the first token refers to a known command (executable), + # and if not, see if the command line as a whole is an executable path. + $cmds = Get-Command $customPagerCommand, $customPagerCommandLine -ErrorAction Ignore + if (-not $cmds) { + # Custom command is invalid; ignore it, but issue a warning. + Write-Warning ""Ignoring invalid custom-paging utility command line specified in `$env:PAGER: $customPagerCommandLine"" + $customPagerCommand = $null # use default command + } + elseif ($cmds.Count -eq 1 -and $cmds[0].Source -eq $customPagerCommandLine) { + # The full command line is an unquoted path to an existing executable + # with embedded spaces. + $customPagerCommand = $customPagerCommandLine + $customPagerCommandArgs = $null + } + } + # Respect PAGER, use more on Windows, and use less on Linux - $moreCommand,$moreArgs = $env:PAGER -split '\s+' - if ($moreCommand) { - $help | & $moreCommand $moreArgs + if ($customPagerCommand) { + $help | & $customPagerCommand $customPagerCommandArgs } elseif ($IsWindows) { $help | more.com } else { diff --git a/test/powershell/engine/Help/HelpSystem.Tests.ps1 b/test/powershell/engine/Help/HelpSystem.Tests.ps1 index 54f6b7771..f1cf27f8b 100644 --- a/test/powershell/engine/Help/HelpSystem.Tests.ps1 +++ b/test/powershell/engine/Help/HelpSystem.Tests.ps1 @@ -513,3 +513,34 @@ Describe "Help failure cases" -Tags Feature { { & $command foobar -ErrorAction Stop } | Should -Throw -ErrorId "HelpNotFound,Microsoft.PowerShell.Commands.GetHelpCommand" } } + +Describe 'help renders when using a PAGER with a space in the path' -Tags 'CI' { + BeforeAll { + $fakePager = @' + param( + [Parameter] + $customCommandArgs, + + [Parameter(ValueFromPipelineByPropertyName)] + $Name + ) + + $b = [System.Text.Encoding]::UTF8.GetBytes($Name) + return [System.Convert]::ToBase64String($b) +'@ + $fakePagerFolder = Join-Path $TestDrive "path with space" + $fakePagerPath = Join-Path $fakePagerFolder "fakepager.ps1" + New-Item -ItemType File -Path $fakePagerPath -Force > $null + Set-Content -Path $fakePagerPath -Value $fakePager + + $SavedEnvPager = $env:PAGER + $env:PAGER = $fakePagerPath + } + AfterAll { + $env:PAGER = $SavedEnvPager + } + + It 'help renders when using a PAGER with a space in the path' { + help Get-Command | Should -Be "R2V0LUNvbW1hbmQ=" + } +}