PowerShell tips for building objects with custom properties and special formatting

 

I’ve been building a number of scripts that query information using PowerShell.

To create those, I used some PowerShell tricks to make the output look just like I wanted. This post is a compilation of these tricks.

The first few tricks are simple, but they grow increasingly complex towards the end.

The examples here are geared towards SMB Shares and Volumes, but you can apply these concepts in many, many other situations.

 

1) Using –AutoSize

 

I do not like the default way that PowerShell spaces out fields in a query. I prefer them packed on the left, which is what the AutoSize option of the Format-Table cmdlet (FT for short) does.

AutoSize, as the name implies, also adjusts to the size of the properties and avoids showing “…” at the end of the output.

 

PS C:> Get-SmbShare

Name ScopeName Path Description
---- --------- ---- -----------
ADMIN$ * C:windows Remote Admin
BackupFiles * E:Backup Project backup files
C$ * C: Default share
D$ * D: Default share
F$ * F: Default share
Images * D:Images Pictures to be used in pro...
IPC$ * Remote IPC
print$ * C:windowssystem32spool... Printer Drivers
Projects * C:Projects Recent project files

 

PS C:> Get-SmbShare | FT -AutoSize

Name ScopeName Path Description
---- --------- ---- -----------
ADMIN$ * C:windows Remote Admin
BackupFiles * E:Backup Project backup files
C$ * C: Default share
D$ * D: Default share
F$ * F: Default share
Images * D:Images Pictures to be used in projects
IPC$ * Remote IPC
print$ * C:windowssystem32spooldrivers Printer Drivers
Projects * C:Projects Recent project files

 

2) Selecting columns to show

 

Every object has a default view with a specific set of columns. If you don’t like those, you can select your own. To find out what fields you can use, you can use a “Select *” or a “Get-Member” to find out.

 

PS C:> Get-SmbShare | Select * -First 1

PresetPathAcl :
ShareState : Online
AvailabilityType : NonClustered
ShareType : FileSystemDirectory
FolderEnumerationMode : Unrestricted
CachingMode : Manual
SmbInstance : Default
CATimeout : 0
ConcurrentUserLimit : 0
ContinuouslyAvailable : False
CurrentUsers : 0
Description : Remote Admin
EncryptData : False
Name : ADMIN$
Path : C:windows
Scoped : False
ScopeName : *
SecurityDescriptor : O:SYG:SYD:(A;;GA;;;BA)(A;;GA;;;BO)(A;;GA;;;IU)
ShadowCopy : False
Special : True
Temporary : False
Volume : \?Volume{4304337d-6763-11e3-8255-806e6f6e6963}
PSComputerName :
CimClass : ROOT/Microsoft/Windows/SMB:MSFT_SmbShare
CimInstanceProperties : {AvailabilityType, CachingMode, CATimeout, ConcurrentUserLimit...}
CimSystemProperties : Microsoft.Management.Infrastructure.CimSystemProperties

PS C:> Get-SmbShare | Get-Member

   TypeName: Microsoft.Management.Infrastructure.CimInstance#ROOT/Microsoft/Windows/SMB/MSFT_SmbShare

Name MemberType Definition
---- ---------- ----------
Clone Method System.Object ICloneable.Clone()
Dispose Method void Dispose(), void IDisposable.Dispose()
Equals Method bool Equals(System.Object obj)
GetCimSessionComputerName Method string GetCimSessionComputerName()
GetCimSessionInstanceId Method guid GetCimSessionInstanceId()
GetHashCode Method int GetHashCode()
GetObjectData Method void GetObjectData(System.Runtime.Serialization.SerializationInfo info, Sys...
GetType Method type GetType()
ToString Method string ToString()
CATimeout Property uint32 CATimeout {get;set;}
ConcurrentUserLimit Property uint32 ConcurrentUserLimit {get;set;}
ContinuouslyAvailable Property bool ContinuouslyAvailable {get;set;}
CurrentUsers Property uint32 CurrentUsers {get;set;}
Description Property string Description {get;set;}
EncryptData Property bool EncryptData {get;set;}
Name Property string Name {get;}
Path Property string Path {get;}
PSComputerName Property string PSComputerName {get;}
Scoped Property bool Scoped {get;}
ScopeName Property string ScopeName {get;}
SecurityDescriptor Property string SecurityDescriptor {get;set;}
ShadowCopy Property bool ShadowCopy {get;}
Special Property bool Special {get;}
Temporary Property bool Temporary {get;}
Volume Property string Volume {get;}
AvailabilityType ScriptProperty System.Object AvailabilityType {get=[Microsoft.PowerShell.Cmdletization.Gen...
CachingMode ScriptProperty System.Object CachingMode {get=[Microsoft.PowerShell.Cmdletization.Generate...
FolderEnumerationMode ScriptProperty System.Object FolderEnumerationMode {get=[Microsoft.PowerShell.Cmdletizatio...
PresetPathAcl ScriptProperty System.Object PresetPathAcl {get=$acl = Get-Acl ($this.PSBase.CimInstancePr...
ShareState ScriptProperty System.Object ShareState {get=[Microsoft.PowerShell.Cmdletization.Generated...
ShareType ScriptProperty System.Object ShareType {get=[Microsoft.PowerShell.Cmdletization.GeneratedT...
SmbInstance ScriptProperty System.Object SmbInstance {get=[Microsoft.PowerShell.Cmdletization.Generate...

 

PS C:> Get-SmbShare | FT Name, Path, Special, AvailabilityType -AutoSize

Name Path Special AvailabilityType
---- ---- ------- ----------------
ADMIN$ C:windows True NonClustered
BackupFiles E:Backup False NonClustered
C$ C: True NonClustered
D$ D: True NonClustered
F$ F: True NonClustered
Images D:Images False NonClustered
IPC$ True NonClustered
print$ C:windowssystem32spooldrivers False NonClustered
Projects C:Projects False NonClustered

 

3) Selecting rows to show

 

You can restrict the items to show based on any of its properties. You need to learn to use the many types of operators like equal (-eq), not equal (-ne), greater than (-gt), like (-like), not like (-not like) and many others.

The cmdlet used is Where-Object, but it can be abbreviated as Where or simply a question mark. There is a simple form for querying just one property and also a more complex form for using expressions.

For instance, to show all shares that are not special, you can one of these:
Get-SmbShare | Where-Object {$_.Special –ne $true}
Get-SmbShare | ? Special –ne $true

If you use the form with the expression in {}, you must specify $_.property, where $_ means “the current item we’re processing”. The simpler form without {} can be used with only one property.

Here’s a more complex example to show all shares that are not special and with a description starting with the letter P:
Get-SmbShare | ? { $_.Special -ne $true -and $_.Description -like "P*" }

 

PS C:> Get-SmbShare | Where-Object {$_.Special –ne $true} | FT -AutoSize

Name ScopeName Path Description
---- --------- ---- -----------
BackupFiles * E:Backup Project backup files
Images * D:Images Pictures to be used in projects
print$ * C:windowssystem32spooldrivers Printer Drivers
Projects * C:Projects Recent project files

PS C:> Get-SmbShare | ? Special –ne $true| FT -AutoSize

Name ScopeName Path Description
---- --------- ---- -----------
BackupFiles * E:Backup Project backup files
Images * D:Images Pictures to be used in projects
print$ * C:windowssystem32spooldrivers Printer Drivers
Projects * C:Projects Recent project files

PS C:> Get-SmbShare | ? Special | FT -AutoSize

Name ScopeName Path Description
---- --------- ---- -----------
ADMIN$ * C:windows Remote Admin
C$ * C: Default share
D$ * D: Default share
F$ * F: Default share
IPC$ * Remote IPC

PS C:> Get-SmbShare | ? { $_.Special -ne $true -and $_.Description -like "P*" } | FT -AutoSize

Name ScopeName Path Description
---- --------- ---- -----------
BackupFiles * E:Backup Project backup files
Images * D:Images Pictures to be used in projects
print$ * C:windowssystem32spooldrivers Printer Drivers

 

4) Creating custom columns

 

In addition to the ability to select which columns to show, you can also create custom tables with any expression. This is useful for creating new calculated columns based on the existing ones.

You can also use this same process to rename existing properties (if you don’t like their default names) or customize the alignment/size of the column.

As with the full form of the “Where” filters, the expressions here must be enclosed in {} and references to existing properties must be preceded with $_.

The syntax uses a hash table, which is little unusual. You should include at least a “Label” (or “Name”) and an “Expression” item in the hash table. You can also specify “Alignment” (or “Align”) and “Width”.

Here’s an example to rename the “Path” property to “Folder”:
Get-SmbShare | FT Name, @{ Label=”Folder”; Expression={$_.Path} }, Description –AutoSize

Here’s another example showing only the drive letter of the path:
Get-SmbShare | FT Name, Description, @{ Name=”Drive”; Expression={$_.Path.Substring(0,1)}; Alignment=”Center” } –AutoSize

Lastly, a more complex example showing that shares ending with $ are hidden:
Get-SmbShare | FT Name, Path, @{ Align="Center"; Expression={If ($_.Name –like “*$”) {“Yes”} else {“No”} }; Label=”Hidden” } –AutoSize

It’s a lot of curly braces, I know. Just make sure you keep good track of them.

 

PS C:> Get-SmbShare | FT Name, @{ Label=”Folder”; Expression={$_.Path} }, Description –AutoSize

Name Folder Description
---- ------ -----------
ADMIN$ C:windows Remote Admin
BackupFiles E:Backup Project backup files
C$ C: Default share
D$ D: Default share
F$ F: Default share
Images D:Images Pictures to be used in projects
IPC$ Remote IPC
print$ C:windowssystem32spooldrivers Printer Drivers
Projects C:Projects &nb