How to change default output Formatting of Powershell to use Format-Table -autosize? - powershell

How can I enforce powershell to use
Format-Table -auto
as a default formatting when writing a returned array of objects to the console?
Thanks

If you are OK calling the cmdlet every time and if you have at least PowerShell v3.0 then you can set a $PSDefaultParameterValues which you can read more about at about_Parameters_Default_Values.
The syntax that would satisfy your need would be:
$PSDefaultParameterValues=#{"<CmdletName>:<ParameterName>"="<DefaultValue>"}
So we add in the switch by setting it to $true.
$PSDefaultParameterValues = #{"Format-Table:Autosize"=$true}
To remove this you would have to do it much the same as you would a hashtable element
$PSDefaultParameterValues.Remove("Format-Table:Autosize")
From the aforementioned article here is some pertinent information as to how to deal with these.
$PSDefaultParameterValues is a preference variable, so it exists only in the session
in which it is set. It has no default value.
To set $PSDefaultParameterValues, type the variable name and one or more key-value pairs
at the command line.
If you type another $PSDefaultParameterValues command, its value replaces the original
value. The original is not retained.
To save $PSDefaultParameterValues for future sessions, add a $PSDefaultParameterValues
command to your Windows PowerShell profile. For more information, see about_Profiles.
Outside of that I am not sure as it would be difficult to change in a dynamic sense. You would want to be sure that data sent to the stream appears on screen in the same way that format-table -auto does but you would have to make sure that it does not affect data so that you could not capture it or send it down the pipe.
You are looking at creating custom output format files, like Frode F. talks about, then you would need to consider looking at about_Format.ps1xml but you would need to configure this for every object that you would want to display this way.
FileSystem.format.ps1xml, for example, would govern the output from Get-ChildItem. Format-Table is more dynamic and I don't think you can say just use Format-Table in that file.

Related

Powershell how to use Get-command to display specific columns?

I need to use 'Get-Command" to display three specific columns of information. Name, CommandType, and Module. I am new to PowerShell and have been searching for hours to find an answer but have not been able to find any documentation that explains how to do this specifically.
I need to use 'Get-Command" to display three specific columns of information. Name, CommandType, and Module
Since your intent is to display the columns of interest, in tabular format, you can use Format-Table:
Get-Command | Format-Table -Property Name, CommandType, Module
For quick interactive use, you can shorten the command, by using aliases and positional parameter binding:
gcm | ft name, commandtype, module
However, note that Format-* cmdlets are only suited to for-display formatting, not for outputting data suitable for later programmatic processing - see this answer and the Select-Object solution below.
By contrast, if you need to construct new objects that have only a subset of the properties of the input objects (while possibly adding new properties / transforming or renaming existing ones via calculated properties[1]), you can use the Select-Object cmdlet:
Get-Command | Select-Object -Property Name, CommandType, Module
Note: If you print this command's output to the console (host), it will result in the same display output as the Format-Table call above, because PowerShell implicitly uses Format-Table formatting for objects that have 4 or fewer (public) properties.[2]
However, for explicit control of display formatting - such as if you want 5-property objects to be shown in tabular format too - Format-* cmdlets must be used.
[1] You may also use calculated properties with Format-Table, among other cmdlets.
[2] 5 or more properties result in Format-List formatting; Generally, this implicit formatting applies only to .NET types that do not have predefined formatting data associated with them; if they do, that data controls the default view and other aspects - see this answer.
Try piping it to select object
get-command|select-object -expandpoperty Name, CommandType, and Module

How do I run multiple lines of code in PowerShell? [duplicate]

I'm getting unexpected results when executing two PowerShell commands separated by a semicolon. The output of the second command changes. If I run them in reverse order, I don't see the second command output.
Here I'm simply trying to get a time stamp and a list of groups a user belongs to in AD, as a one-liner.
If I run this line, i get the following output:
Get-ADPrincipalGroupMembership username | Select-Object name
name
----
Domain Users
CL-Inventory-Group
...
However if I run the following, this behavior changes:
get-date; Get-ADPrincipalGroupMembership username | Select-Object name
Wednesday, April 3, 2019 2:31:35 PM
name : Domain Users
name : CL-Inventory-Group
...
Stranger yet, If i run the in reverse, meaning i say get-date after the first command, the date stamp never shows up after the groups are listed.
Am I improperly separating commands?
tl;dr:
Submitting multiple ;-separated commands at the prompt (interactively) still sends their output to a single pipeline (you can think of each command line submitted as an implicit script file).
In short: in your case, the first command output's automatic display formatting also determined the display formatting for the 2nd command, so which command comes first matters:
get-date; Get-ADPrincipalGroupMembership username | Select-Object name
locked in implicit use of Format-List for all output following Get-Date, which explains the each-property-on-its-own line output from the Get-ADPrincipalGroupMembership ... command.
If i run the reverse, meaning i say get-date after the first command, the date stamp never shows up after the groups are listed.
Select-Object output instances of type [pscustomobject], which, due to their having just 1 property in this case, locked in tabular display, i.e., implicit use of Format-Table, with the selected property as the only column, i.e., just Name here. Since the [datetime] type output by Get-Date doesn't have a Name property, Get-Date's output was effectively invisible.
Read on for background information and the complete rules.
PowerShell's default display formatting is optimized for objects of the same type, as that is the typical case.
If a pipeline contains a mix of types, the specific formatting that results by default depends on:
the order of objects in the pipeline
and their default formatting behavior
See the next section for details.
You can use explicit Format-* calls to control the formatting; in your case, you can use Format-Table on your 2nd command to force tabular output:
Get-Date; Get-ADPrincipalGroupMembership username | Select name | Format-Table
Caveat: The output from Format-* cmdlets are formatting instructions rather than the original data, which makes this output unsuitable for further programmatic processing.
How PowerShell formats objects of different types in the same pipeline for display:
In the absence of explicit formatting commands (Format-Table, Format-List, ...), PowerShell automatically chooses a suitable display format, based on a given object's type:
If present for a given type, PowerShell uses predefined formatting instructions (see Get-Help about_Format.ps1xml)
In their absence:
If the type is a primitive type (see below): the object's .ToString() representation is output.
Otherwise: the format style is chosen based on the following simple rules: 4 or fewer properties? -> Format-Table; 5 or more? -> Format-List.
Note: Primitive is used loosely here to refer to:
all primitive CLR types - those for which .IsPrimitive returns $true, namely [Boolean], [Byte], [SByte], [Int16], [UInt16], [Int32], [UInt32], [Int64], [UInt64], [IntPtr], [UIntPtr], [Char], [Double], [Single]
types [decimal], [bigint], and [securestring]
[string] (strings always print as themselves, in full)
any other property-less types.
If all objects in a pipeline are of the same type, the above by definition applies to all of them.
By contrast, if there is a mix of types in the pipeline, the following logic applies:
Any instances of primitive types always print and always print the same, namely as a representation of the single value that they are (not an as an object with properties), obtained via a call to their .ToString() method; e.g., 12 or 3.0 or hi; primitive types have no bearing on the formatting of subsequent objects in the pipeline.
The first non-primitive object in the pipeline:
is itself printed based on either its predefined formatting instructions or the default rules stated above (based on the number of properties).
locks in the format style - list vs. table - for all remaining non-primitive objects:
If the object itself implicitly uses Format-Table or Format-List, so will all remaining non-primitive objects.
If the object implicitly uses Format-Custom (e.g, in the case of Get-Date, via predefined formatting), it is Format-List that is locked in.
All subsequent non-primitive objects then use the locked-in format style.
Caveat: If Format-Table is locked in, the first non-primitive object alone determines the set of properties displayed as table columns:
If the first non-primitive object has no formatting data associated with it - which notably applies to [pscustomobject] - it
can cause subsequent non-primitive objects to seemingly disappear if they don't have these properties - such objects are still in the output stream, however, they're just not displayed - see this answer for a demonstration.
GitHub issue #7871 proposes at least issuing a warning when that happens.
If the first non-primitive object has formatting data associated with it (as reported by Get-FormatData), all subsequent non-primitive objects of a different type are formatted with Format-List. That is, you'll get a mix of tabular and list-style output.
On a side note: Since PSv5, implicit use of Format-Table results in asynchronous behavior that may be surprising; see this answer.
If it is Format-List that is locked in, no information is "lost", as each object's properties are then listed individually, on their own lines.
When the powershell console formatter sees objects of multiple types, it will default to outputting based on the first element output. For Date it output as a list, for the custom object output from Select-Object, it's a table. How the output is formatted depends on the type of the object itself (see help About Format.ps1xml). You can force the output of Select-Object to be a table using Format-Table:
get-date; Get-ADPrincipalGroupMembership username | Select-Object name | Format-Table

Is there an easy way to have Powershell always show the actual value?

These things drive me nuts:
Is there an easy way to have Powershell just show me the empty string and the list with an empty string in it?
For a while I am maintaining a ConvertTo-Expression which converts an (complex) object into a PowerShell expression which eventually can be used to rebuild most objects. It might useful in situations as comparing test results but also to reveal objects. For details see: readme.
Source and installation
The ConvertTo-Expression script can be installed from the PowerShell Gallery:
Install-Script -Name ConvertTo-Expression
As it concerns a standalone script, installation isn't really required. If you don't have administrator rights, you might just download the script (or copy it) to the required location. You might than simply invoke the script using PowerShell dot sourcing:
. .\ConvertTo-Expression.ps1
Example
The following command outputs the same expression as used to build the object:
$Object = [Ordered]#{
'Null' = $Null
'EmptyString' = ''
'EmptyArray' = #()
'SingleItem' = ,''
'EmptyHashtable' = #{}
}
ConvertTo-Expression $Object
Note the comment from #Mathias there's no functional difference between "one string" and "an array of one string", the pipeline consumes 1 string either way. PowerShell is not node which is described here: PowerShell enumerate an array that contains only one inner array. Some objects might be really different than you expect.
See also: Save hash table in PowerShell object notation (PSON)
This is PowerShell, not Node. So it's not JavaScript or JSON. Also, PowerShell is not Bash or CMD any other regular text-based shell. PowerShell works with objects. .NET objects, in particular. And how objects are represented as text is ... quite a matter of taste. How to represent null? Of course: nothing. How to represent an empty string? Nothing, either. An empty array ... you get my point.
All pipeline output is by default send to Out-Default. In general, the way objects are represented can be controlled by format files: about_Format.ps1xml and about_Types.ps1xml. From PowerShell 6 upwards, the default formats are compiled into the source code, but you can extend them. How you do so, depends on your personal taste. Some options were already mentioned ConvertTo-Json "", ConvertTo-Json #("")), but this would be veryyy JSON-specific.
tl;dr Don't care too much about how objects are represented textually. As you see, there are many possible ways to do so, and also some others. Just make sure your scripts are always object-oriented.
You mean like Python's repr() function? A serialization? "Give me a canonical representation of the object that, when property evaluated, will return an object of the type originally passed?" No, that's not possible unless you write it yourself or you serialize it to XML, JSON, or similar. That's what the *-CliXml and ConvertTo-*/ConvertFrom-* commands are for.
On Powershell 7:
PS C:\> ''.Split(',') | ConvertTo-Json -Compress -AsArray
[""]
PS C:\> '1,2,3,,5'.Split(',') | ConvertTo-Json -Compress -AsArray
["1","2","3","","5"]
The closest would be the ToString() common method. However, that's intended for formatting output and typecasting, not canonical representations or serializations. Not every object even has a string representation that can be converted back into that object. The language isn't designed with that in mind. It's based on C#, a compiled language that favors binary serializations. Javascript requires essentially everything to have a string serialization in order to fulfill it's original design. Python, too, has string representations as fundamental to it's design which is why the repr() function is foundational for serialization and introspection and so on.
C# and .Net go the other way. In a .Net application, if you want to specify a literal empty string you're encouraged to use String.Empty ([String]::Empty in Powershell) because it's easier to see that it's explicit. Why would you ever want a compiled application to tell the user how the canonical representation of an object in memory? You see why that's not a useful thing for C# even if it might be for Powershell?

What is the purpose of putting Class after your variable like this ($_.Class)?

What is the purpose of this string? I am still new to PowerShell and have seen this come up quiet a bit.
$_.Class
Here is an example of how I have seen it used:
$R.AllElements|?{$_.Class -eq "table"}|select innerText
Does this meant that we are applying a class on the $R variable? Or is there a "Class" already for that variable that we are searching for the string "table"? I have looked around but cannot find any explanation.
Here's an example for you to understand the purpose of $_.xxxxx
$Obj = Get-Item -Path 'C:\Program Files'
This would put any information gathered by the Get-Item command and store it in $Obj. If you then show what's in the variable, it will look something like this
If you would then do $obj.xxx where xxx is one of the property names shown above, it will show you the values under that property like this
Another way to get the values of said properties is how you have shown in your post. If you pipe the variable into a where statement like below, it is especially helpful when trying to filter out some text inside a particular variable. This example is looking for the text prog in the Name property of all the items inside of $Obj2
I wish I had time to give more details, I hope this helps you some! PowerShell is one of the best tools for Automation and Administration in a Windows environment so keep on learnin!
Bonus: Here is a link to documentation on PowerShell's pipelines and how it works, I referred to it as 'pipe' in my wordage above

Why is the output format changed when running two PowerShell commands in one line?

I'm getting unexpected results when executing two PowerShell commands separated by a semicolon. The output of the second command changes. If I run them in reverse order, I don't see the second command output.
Here I'm simply trying to get a time stamp and a list of groups a user belongs to in AD, as a one-liner.
If I run this line, i get the following output:
Get-ADPrincipalGroupMembership username | Select-Object name
name
----
Domain Users
CL-Inventory-Group
...
However if I run the following, this behavior changes:
get-date; Get-ADPrincipalGroupMembership username | Select-Object name
Wednesday, April 3, 2019 2:31:35 PM
name : Domain Users
name : CL-Inventory-Group
...
Stranger yet, If i run the in reverse, meaning i say get-date after the first command, the date stamp never shows up after the groups are listed.
Am I improperly separating commands?
tl;dr:
Submitting multiple ;-separated commands at the prompt (interactively) still sends their output to a single pipeline (you can think of each command line submitted as an implicit script file).
In short: in your case, the first command output's automatic display formatting also determined the display formatting for the 2nd command, so which command comes first matters:
get-date; Get-ADPrincipalGroupMembership username | Select-Object name
locked in implicit use of Format-List for all output following Get-Date, which explains the each-property-on-its-own line output from the Get-ADPrincipalGroupMembership ... command.
If i run the reverse, meaning i say get-date after the first command, the date stamp never shows up after the groups are listed.
Select-Object output instances of type [pscustomobject], which, due to their having just 1 property in this case, locked in tabular display, i.e., implicit use of Format-Table, with the selected property as the only column, i.e., just Name here. Since the [datetime] type output by Get-Date doesn't have a Name property, Get-Date's output was effectively invisible.
Read on for background information and the complete rules.
PowerShell's default display formatting is optimized for objects of the same type, as that is the typical case.
If a pipeline contains a mix of types, the specific formatting that results by default depends on:
the order of objects in the pipeline
and their default formatting behavior
See the next section for details.
You can use explicit Format-* calls to control the formatting; in your case, you can use Format-Table on your 2nd command to force tabular output:
Get-Date; Get-ADPrincipalGroupMembership username | Select name | Format-Table
Caveat: The output from Format-* cmdlets are formatting instructions rather than the original data, which makes this output unsuitable for further programmatic processing.
How PowerShell formats objects of different types in the same pipeline for display:
In the absence of explicit formatting commands (Format-Table, Format-List, ...), PowerShell automatically chooses a suitable display format, based on a given object's type:
If present for a given type, PowerShell uses predefined formatting instructions (see Get-Help about_Format.ps1xml)
In their absence:
If the type is a primitive type (see below): the object's .ToString() representation is output.
Otherwise: the format style is chosen based on the following simple rules: 4 or fewer properties? -> Format-Table; 5 or more? -> Format-List.
Note: Primitive is used loosely here to refer to:
all primitive CLR types - those for which .IsPrimitive returns $true, namely [Boolean], [Byte], [SByte], [Int16], [UInt16], [Int32], [UInt32], [Int64], [UInt64], [IntPtr], [UIntPtr], [Char], [Double], [Single]
types [decimal], [bigint], and [securestring]
[string] (strings always print as themselves, in full)
any other property-less types.
If all objects in a pipeline are of the same type, the above by definition applies to all of them.
By contrast, if there is a mix of types in the pipeline, the following logic applies:
Any instances of primitive types always print and always print the same, namely as a representation of the single value that they are (not an as an object with properties), obtained via a call to their .ToString() method; e.g., 12 or 3.0 or hi; primitive types have no bearing on the formatting of subsequent objects in the pipeline.
The first non-primitive object in the pipeline:
is itself printed based on either its predefined formatting instructions or the default rules stated above (based on the number of properties).
locks in the format style - list vs. table - for all remaining non-primitive objects:
If the object itself implicitly uses Format-Table or Format-List, so will all remaining non-primitive objects.
If the object implicitly uses Format-Custom (e.g, in the case of Get-Date, via predefined formatting), it is Format-List that is locked in.
All subsequent non-primitive objects then use the locked-in format style.
Caveat: If Format-Table is locked in, the first non-primitive object alone determines the set of properties displayed as table columns:
If the first non-primitive object has no formatting data associated with it - which notably applies to [pscustomobject] - it
can cause subsequent non-primitive objects to seemingly disappear if they don't have these properties - such objects are still in the output stream, however, they're just not displayed - see this answer for a demonstration.
GitHub issue #7871 proposes at least issuing a warning when that happens.
If the first non-primitive object has formatting data associated with it (as reported by Get-FormatData), all subsequent non-primitive objects of a different type are formatted with Format-List. That is, you'll get a mix of tabular and list-style output.
On a side note: Since PSv5, implicit use of Format-Table results in asynchronous behavior that may be surprising; see this answer.
If it is Format-List that is locked in, no information is "lost", as each object's properties are then listed individually, on their own lines.
When the powershell console formatter sees objects of multiple types, it will default to outputting based on the first element output. For Date it output as a list, for the custom object output from Select-Object, it's a table. How the output is formatted depends on the type of the object itself (see help About Format.ps1xml). You can force the output of Select-Object to be a table using Format-Table:
get-date; Get-ADPrincipalGroupMembership username | Select-Object name | Format-Table