2

Running the command help firewall | Select-Object Category. The result is one column blank Category.

The strange thing is that the empty rows number represent the amount of rows that help firewall would result without calling piping it to Select-Object

Or I'm trying to filter the output of help firewall to return only rows with Name that starts with "Get". Running help firewall | Where-Object Name -like "Get" just returns nothing.

Why aren't these pipes on help working? They are working perfectly on other commands.

Powershell Version 5.1 and using default windows console.

  • 2
    So, `help` is an alias for `Get-Help`. But not in a standard way (try using `help help` and you'll see that there's no aliases provided). Strangely enough, when I use original one (`Get-Help`) it's behaving as expected. BTW. `-like` parameter uses wildcards. So in this situation it'd be `Where-Object Name -like "Get*"` – Karolina Ochlik May 26 '21 at 13:10
  • 1
    I forgot to include the wildcard in this post. But I figured out that help returns a string, and `Name` or `Category` are not proprites of a string. And that `get-help` behaves as expected is very confusing indeed. – Filip Kowalczyk May 26 '21 at 13:14
  • 1
    It's done like that on purpose. That's why when you run one, the full help shows, vs the other one only showing parts of it first before pressing a key to continue. – Abraham Zinala May 26 '21 at 13:19

2 Answers2

3

To complement Zilog80's helpful answer with background information:

Get-Command help reveals that help is not a mere alias of the Get-Help cmdlet, but a (built-in) function (submit $function:help to see its definition).

As you've noticed yourself:

  • while Get-Help outputs an object ([pscsustomobject]) with properties that reflect help-topic metadata such as Category, which is then rendered as display text by PowerShell's output-formatting system,

  • the help function returns strings - a stream of text lines representing the rendered help topic - of necessity.

You can observe the difference in output type by piping to the Get-Member cmdlet (help firewall | Get-Member vs. Get-Help firewall | Get-Member)

The purpose of the help function is to wrap Get-Help with interactive paging, to allow convenient navigation through lengthy help topics that don't fit onto a single console (terminal) screen.

This paging is provided via an external program (by default, more.com on Windows, and less on Unix-like platforms, configurable via $env:PAGER, but only in PowerShell (Core) 7+), and since PowerShell only "speaks text" when communicating with external programs, help must send a stream of strings (lines for display) to them, which it does via
Out-String -Stream.

Note:

  • When the external paging programs find that their stdout stream isn't connected to a console (terminal), they take no action other than simply passing the input through (in Unix terms, they then behave like cat).

  • Hypothetically, the help function itself could determine this condition and then (a) not pipe to the paging program and (b) relay the object output by Get-Help as-is.[1] However, determining a command's output target from inside that command, using PowerShell code, may not even be possible.


[1] The function actually already takes this action when a custom pager defined via $env:PAGER is found to be a PowerShell command rather than an external program.

mklement0
  • 382,024
  • 64
  • 607
  • 775
  • 1
    Very nice and well redacted answer. To add a funny note, if `help` is a built-in function, `man` is an alias for `help` ^^ – Zilog80 May 26 '21 at 14:00
  • Thanks, @Zilog80. Re `man` :) I'd never noticed that. Note that it _isn't_ an alias on Unix-like platforms, so as not to shadow the standard `man` utility there. – mklement0 May 26 '21 at 14:02
  • This give me the following idea: `New-Alias more Select-Object`, and now `help firewall` will behave like `Get-Help` :D – Zilog80 May 26 '21 at 14:04
  • 1
    @Zilog80 :) It's actually even simpler: `New-Alias help Get-Help`, which relies on [aliases having higher precedence than functions](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_Command_Precedence). – mklement0 May 26 '21 at 14:08
2

Check the feedback from help help in PowerShell :

    You can also type `help` or `man`, which displays one screen of text at a
    time. Or, ` -?`, that is identical to `Get-Help`, but only
    works for cmdlets.

The helpcommand display "screen of text" which means it is outputting [System.String] objects, not [PSCustomObject] objects.

Only -? will behave identically to Get-help and will provide [PSCustomObject] objects.

To see what's going on, check the different output from :

help firewall | %{ $_.GetType() }

And

Get-help firewall | %{ $_.GetType() }

And, for cmdlet,

Select-Object -? | %{ $_.gettype() }
Zilog80
  • 2,534
  • 2
  • 15
  • 20