Category Archives: PowerShell

Could not establish trust relationship for the SSL/TLS Secure Channel – Invoke-WebRequest

I’ve recently been playing around with VMware’s REST APIs in VCSA 6.5 using PowerShell. I’ve been using a lot of Invoke-WebRequest and Invoke-RestMethod to do my work. Chris Wahl has a great primer on how to get started here.

One issue that I ran into very quickly working again my VCSA was a certificate trust relationship error. I’ve run into this error numerous times in the past.

PS F:\Code> Invoke-WebRequest -Uri -Method Post -Headers $head
Invoke-WebRequest : The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.
At line:1 char:1
+ Invoke-WebRequest -Uri ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand

The first time I ran into this error I was stumped for while finding a solution. Ultimately it comes down to using Self-Signed Certificates in vCenter, as most of us do.  In general using Invoke-WebRequest or Invoke-RestMethod against a server using a Self-Signed Certificate will cause this error, it’s not just related to vCenter.

The solution is quite simple.  I found a snippet of code some time back that I keep on hand in this situation.  It basically ignores certificate validate in PowerShell allowing you to make a connection with Invoke-WebRequest.  All you have to do it paste this code into your PowerShell session before you run Invoke-WebRequest against a server with a Self-Signed Certificate.

if (-not ([System.Management.Automation.PSTypeName]'ServerCertificateValidationCallback').Type)
$certCallback = @"
    using System;
    using System.Net;
    using System.Net.Security;
    using System.Security.Cryptography.X509Certificates;
    public class ServerCertificateValidationCallback
        public static void Ignore()
            if(ServicePointManager.ServerCertificateValidationCallback ==null)
                ServicePointManager.ServerCertificateValidationCallback += 
                        Object obj, 
                        X509Certificate certificate, 
                        X509Chain chain, 
                        SslPolicyErrors errors
                        return true;
    Add-Type $certCallback

Once you run the code you will be able to now successfully make a connection.

I’ve seen some simple one liner solutions for Self-Signed Certificates but none of them seemed to work for me.  Whereas the above snippet of code has always worked.  Obviously bypassing certificate validate is not something you want to run on a global scale in PowerShell but this code works great for your current session only.

If there is a simpler way to bypass certificate validation I’d love to hear it.

Store Multiple Pure Storage Connections In A PowerShell Array

I’ve recently been playing around with the Pure Storage PowerShell modules. I’ve found the Pure cmdlets to be quite extensive and easy to use. Quite a nice change from PowerShell Cmdlets of other traditional storage vendors. One thing, though, that I found a little annoying was that I had to store a connection for a Pure Array into a PowerShell object and constantly reference that object in each cmdlet I ran. Not a big deal normally but where I ran into an issue was wanting to connect to multiple Pure Arrays at the same time and being able to run and iterate against them all at the same time. I quickly came to realise that the cmdlets themselves are designed to run against one Pure Array at a time.

Initially I thought I could store multiple connections to a variable using the += operator. But this lead to the following error.

C:\Code>   $arrays = New-PfaArray -EndPoint purearray1 -ApiToken 'b2342442-ebb2-5673-a452-c443f562cb7' -IgnoreCertificateError

C:\Code>   $arrays += New-PfaArray -EndPoint purearray2 -ApiToken '6523ff23-32ac-2890-9843-2e4e9543672' -IgnoreCertificateError
Method invocation failed because [PurePowerShell.PureArray] does not contain a method named 'op_Addition'.
At line:1 char:1
+ $array += New-PfaArray -EndPoint purearray2 -A ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (op_Addition:String) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound

A quick inspection of the data type of the variable created using GetType shows that it is a System.Object and not an Array. By default creating a connection to a Pure Array using New-PfaArray and storing that to a variable will cast it as an object.

C:\Code>   $arrays.GetType()

IsPublic IsSerial Name                                     BaseType          
-------- -------- ----                                     --------    
True     False    PureArray                                System.Object

This is easily fixed by setting the data type for our variable to [array] when we create it.

[array]$arrays = New-PfaArray -EndPoint purearray1 -ApiToken 'b2342442-ebb2-5673-a452-c443f562cb7' -IgnoreCertificateError
[array]$arrays += New-PfaArray -EndPoint purearray2 -ApiToken '6523ff23-32ac-2890-9843-2e4e9543672' -IgnoreCertificateError

Now when we check the data type we see it’s System.Array.

C:\Code>   $arrays.GetType()

IsPublic IsSerial Name                                     BaseType      
-------- -------- ----                                     --------       
True     True     Object[]                                 System.Array    

Checking the variable again we can see we have two records.

C:\Code>   $arrays

Disposed : False
EndPoint :
UserName :
ApiVersion : 1.7
Role : StorageAdmin
ApiToken : b2342442-ebb2-5673-a452-c443f562cb7

Disposed : False
EndPoint :
UserName :
ApiVersion : 1.7
Role : StorageAdmin
ApiToken : 6523ff23-32ac-2890-9843-2e4e9543672

Using this new variable with a Pure Storage Cmdlet is just a matter of specify the line in the array representing the Pure Storage Array we want using square brackets.

C:\Code>   Get-PfaArrayId -Array $arrays[0]

version revision             array_name           id                                  
------- --------             ----------           --  
4.8.10 201705102013+977fb3c  purearray1           b2342442-ebb2-5673-a452-c443f562cb7b

Where this array we created really becomes handy is when using it with foreach loops. We can now rap our Cmdlets in a foreach loop and iterate through all our Pure Storage Arrays.

C:\Code>   $results = foreach ($array in $arrays) {
Get-PfaArrayId -array $array

C:\Code>   $results | ft

version revision             array_name           id                                  
------- --------             ----------           --    
4.8.10 201705102013+977fb3c  purearray2           6523ff23-32ac-2890-9843-2e4e9543672
4.8.10 201705102013+977fb3c  purearray1           b2342442-ebb2-5673-a452-c443f562cb7

This is just a simple example but now we can start enumerating across all our Pure Storage arrays and easily start manipulating objects returned.

I really like the Pure Storage PowerShell modules but I really hope that a future update allows for easier working with multiple Pure Arrays. Hopefully allowing their Cmdlets to work against multiple arrays at the same time.

Cisco UCS PowerTool Suite – Part 3

In Part 3 of this series I cover a great cmdlet that’s really useful when first learning UCS PowerTool.  It’s called ConvertTo-UCSCmdlet and what it does is translate actions in the Java GUI into PowerTool commands.

If you haven’t yet checked out the previous posts in this series I recommend you do below.
Cisco UCS PowerTool Suite – Part 1
Cisco UCS PowerTool Suite – Part 2
Cisco UCS PowerTool Suite – Part 3

ConvertTo-UCSCmdlet monitors the java log file that the UCSM Java GUI creates when it’s run.  When it sees a Change Event it outputs the equivalent PowerTool command to the PowerShell console.  Using the Cmdlet is quite straight forward.  First log into the Java GUI of UCSM.

Next head over to your PowerShell / PowerTool CLI and run ConvertTo-UcsCmdlet.  You can run this cmdlet without needing to be connected to UCSM in PowerTool.

PowerTool C:\> ConvertTo-UcsCmdlet

You should see something similar to below.  ConvertTo-UcsCmdlet is now monitoring the log file of the UCSM Java GUI session you opened up and will capture any Change Events.  Leave the cmdlet running in the background.

Back in the Java GUI make a simple change.  In the below example we add a new VLAN.

We create a new VLAN ID 13 and give it a name of 13 and click OK.  If you can see your PowerTool session running in the background you will see the equivalent PowerTool command appear below the monitored log file.

Usually what you get back is a little more than you need to make a change in PowerTool.  For example ConvertTo-UcsCmdlet also provides you with all the default parameters when creating a VLAN using Add-UcsVlan.  While you could omit some of these parameters when normally working in PowerTool there’s no real harm in having them all in.

It’s also worth noting that ConvertTo-UcsCmdlet will only capture Change Events.  It will not capture basic navigation inside the UCSM GUI.

I have found this to be a great cmdlet in learning UCS PowerTool.  Especially when I don’t know how to do an equivalent command from the GUI inside PowerTool.

Cisco UCS PowerTool Suite – Part 2

In Part 1 of this series I covered the fundamentals of Cisco UCS PowerTool and how to make your first connection.  In Part 2 I expand on this and now show some of the basic commands you can use against UCSM when first learning to script with PowerTool.  With 4500+ commands, over 2300 just in the Cisco.UCSManager module alone it’s impossible to cover them all.  The intention here is not to show you them all but rather give you an idea of what’s out there and possible.

Cisco UCS PowerTool Suite – Part 1
Cisco UCS PowerTool Suite – Part 2
Cisco UCS PowerTool Suite – Part 3

In the below examples we will be working with the Cisco.UCSManager module.  We’re going to assume you’ve already made your connection to UCSM.  If you’re not sure how, checkout Part 1 of this series.

Now with our connection made one of the first commands we can try is Get-UCSChassis. This simply returns a list of all our UCS chassis’ in UCSM.

PowerTool C:\> Get-UcsChassis

AckProgressIndicator  : ack-not-in-progress
AdminState            : acknowledged
AssignedToDn          :
Association           : none
Availability          : available
ConfigState           : ok
ConnPath              : {A, B}
ConnStatus            : {A, B}
Discovery             : complete
DiscoveryStatus       : A,B
FabricEpDn            : fabric/server/chassis-6
Id                    : 6
LcTs                  : 1970-01-01T00:00:00.000
LicGP                 : 0
LicState              : license-ok
ManagingInst          : A
MfgTime               : not-applicable
Model                 : UCSC-C3X60-BASE

Above is a small extract of the output that comes back to us in list format.  This can be a little difficult to read if we have a few chassis’. We can clean this up a little by piping it to Format-Table and selecting our own columns.

PowerTool C:\> Get-UcsChassis | Format-Table RN, Id, Model, Availability, AdminState, Serial, ConfigState

Rn        Id Model           Availability AdminState   Serial ConfigState
--        -- -----           ------------ ----------   ------ -----------
chassis-3  3 UCSB-5108-AC2   unavailable  acknowledged CH29   ok
chassis-4  4 UCSC-C3X60-BASE available    acknowledged CH30   ok
chassis-5  5 N20-C6508       unavailable  acknowledged CH31   ok
chassis-6  6 UCSC-C3X60-BASE available    acknowledged CH32   ok

This now looks a little cleaner and provides us with information more relevant to what we might be after.

Next we can check what blades we have with Get-UCSBlade.  As with the previous command we can pipe it to Format-Table and select more meaningful columns.

PowerTool C:\> Get-UcsBlade | Format-Table DN, Model, NumofCPUs, NumofCores, TotalMemory

Dn                    Model            NumOfCpus NumOfCores TotalMemory
--                    -----            --------- ---------- -----------
sys/chassis-3/blade-1 UCSB-EX-M4-1             2         10       49152
sys/chassis-3/blade-3 UCSB-EX-M4-1             2         10       49152
sys/chassis-3/blade-7 UCSB-EX-M4-1             4         20       49152
sys/chassis-4/blade-1 UCSC-C3X60-SVRNB         2          8       49152
sys/chassis-4/blade-2 UCSC-C3X60-SVRNB         2          8       49152
sys/chassis-5/blade-4 UCSB-B200-M4             2          8       49152
sys/chassis-5/blade-5 UCSB-B420-M4             4         16       49152
sys/chassis-6/blade-1 UCSC-C3K-M4SRB           2          8       49152

If we have rack servers added into UCSM we can list them as well with Get-UcsRackUnit.  Or alternatively we can use Get-UcsServer to list both Blade and Rack servers in the one output display.

PowerTool C:\> Get-UcsServer | Format-Table AdminState, Model, operState, Serial, RN

AdminState Model            OperState    Serial Rn
---------- -----            ---------    ------ --
in-service UCSB-EX-M4-1     unassociated SRV72  blade-1
in-service UCSB-EX-M4-1     unassociated SRV73  blade-3
in-service UCSB-EX-M4-1     unassociated SRV75  blade-7
in-service UCSC-C3X60-SVRNB unassociated SRV76  blade-1
in-service UCSC-C3X60-SVRNB unassociated SRV77  blade-2
in-service UCSC-C220-M4S    unassociated RK32   rack-unit-1
in-service UCSC-C240-M4S    unassociated RK33   rack-unit-2
in-service UCSC-C220-M4S    unassociated RK34   rack-unit-3
in-service UCSC-C220-M4L    unassociated RK35   rack-unit-4
in-service UCSC-C220-M4L    unassociated RK36   rack-unit-5
in-service UCSC-C240-M4SX   unassociated RK37   rack-unit-6

Working with Orgs is very simple too with Get-UCSOrg.  In the below example I have just one root Org with is returned.

PowerTool C:\> Get-UcsOrg

Descr        :
Level        : root
Name         : root
PermAccess   : yes
Sacl         :
Ucs          : UCSPE-10-0-30-79
Dn           : org-root
Rn           : org-root
Status       :
XtraProperty : {}

Creating a new Org is just a matter of changing the ‘Get’ Verb to ‘Add’ using Add-UcsOrg

PowerTool C:\> Add-UcsOrg -Name Ukoticland

Descr        :
Level        : 1
Name         : Ukoticland
PermAccess   : no
Sacl         :
Ucs          : UCSPE-10-0-30-79
Dn           : org-root/org-Ukoticland
Rn           : org-Ukoticland
Status       : created
XtraProperty : {}

And you guessed it, we can remove an Org with the Remove Verb using Remove-UcsOrg

PowerTool C:\> Remove-UcsOrg -Org Ukoticland

Are you sure you want to remove UCSPE-10-0-30-79:org-root/org-Ukoticland?
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help (default is "Y"): Y

Descr        :
Level        : 1
Name         : Ukoticland
PermAccess   : yes
Sacl         :
Ucs          : UCSPE-10-0-30-79
Dn           : org-root/org-Ukoticland
Rn           : org-Ukoticland
Status       : deleted
XtraProperty : {}

Working with Service Profiles is extremely easy as well.  Get-UcsServiceProfile will display all service profiles. In the below example I have two.

PowerTool C:\> Get-UcsServiceProfile | Format-Table Name


Creating an initial Service Profile is as simple as Add-UcsServiceProfile

PowerTool C:\> Add-UcsServiceProfile -Name MyFirstSP

And removing a Service Profile as simple as Remove-UcsServiceProfile

PowerTool C:\> Remove-UcsServiceProfile -ServiceProfile MyFirstSP
Are you sure you want to remove UCSPE-10-0-30-79:org-root/ls-MyFirstSP?
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help (default is "Y"): y

Dn                       : org-root/ls-MyFirstSP
Rn                       : ls-MyFirstSP
Status                   : deleted
XtraProperty             : {}

PowerTool has the ability to perform a number of different backups using Backup-Ucs.

The most complete form is full-state. Full state creates a binary file with a snapshot of the entire system. This type of backup can then be used to perform a full system restore to the Fabric Interconnect

PowerTool C:\> Backup-Ucs -Type full-state -PathPattern 'C:\cisco\ucspe-backup.tar.gz'

The second type of backup is config-logical which backs up information like service profiles, VLANs, VSANs, pools, and policies and is saved as an XML.

PowerTool C:\> Backup-Ucs -Type config-logical -PathPattern 'c:\cisco\ucspe-config-logical.xml'

The third is config-system. This includes all system configuration settings such as usernames, roles, and locales. This is also in XML format.

PowerTool C:\> Backup-Ucs -Type config-system -PathPattern 'c:\cisco\ucspe-config-all.xml'

The last is config-all. This is a combination of config-logical and config-system and once again saved as an XML.

PowerTool C:\> Backup-Ucs -Type config-all -PathPattern 'c:\cisco\ucspe-config-all.xml'

None of the XML backups are suitable for full system restores and do not contain passwords of accounts.

Finally, XML backups can be imported back in with Import-UcsBackup.

PowerTool C:\> Import-UcsBackup -LiteralPath 'C:\cisco\ucspe-config-all.xml' -Merge

This brings us to the end of the primer on UCS PowerTool cmdlets. Everything that we covered above was just a very small taste of what’s possible with Cisco UCS PowerTool. As mentioned in the beginning the intention was to get you thinking about what’s possible. There’s a wealth of information that can be retrieved from UCS with PowerTool. It’s not really a question of what I can retrieve but how I can retrieve it.

Cisco UCS PowerTool Suite
Cisco UCS PowerTool Suite Communities Page

Cisco UCS PowerTool Suite – Part 1

I thought I would created a short blog series on a very underrated collection of PowerShell modules from Cisco called the Cisco UCS PowerTool Suite.  The UCS PowerTool Suite was released back in early 2013 and has been steadily growing and maturing since.   The current release of the PowerTool Suite, as of this blog post, is 2.2.1 which contains 5 modules and over 4500 Cmdlets!   Yes that’s right, over 4500 Cmdlets, crazy huh.

PowerTool brings PowerShell and all its goodness to Cisco UCS and allows you to script and automated your UCS management is a very powerful way.  PowerTool can connect to Cisco UCS Manager, UCS Central and UCS IMC (namely C-Series and E-Series).  PowerTool isn’t doing anything special behind the scenes.  It connects via the standard XML APIs that the Java GUI uses to connect to things like UCS Manager, as well as respecting and working with the Management Information Tree (MIT) that UCS is built on.

In Part 1 of this series I run through the basics of installing UCS PowerTool and connecting to your first UCS Manager.

Before you install the UCS PowerTool Suite you need to meet a few requirements.  PowerTool is not currently compatible with PowerShell Core so at present you will need a Windows box running the following.

  • Windows PowerShell 3.0 or higher
  • .NET Framework Version 4.5 or higher
  • PowerShell 4.0 and higher for the DSC module resources

Once you met these requirements you can download the latest version of UCS PowerTool from Cisco.  Then proceed to install from the MSI file.  The installation wizard is straight forward and will copy the modules to your C:\Program Files (x86)\WindowsPowerShell\Modules folder along with three shortcuts to your desktop.  Each shortcut, Cisco IMC PowerTool, Cisco UCS Central PowerTool, and Cisco UCS Manager PowerTool, runs a small startup script that basically loads their respective module.

We don’t need to actually use these shortcuts if we choose not to.  We can just run PowerShell as we normally would and import the modules as needed.  If we’re running Windows Server, though,  these module will actually auto load for us.

Below is what we see when we use the shortcut, Cisco UCS Manager PowerTool.

Below we will delve into connecting to our first UCS Manager, but first let’s run through a few of the basics.  First we run Get-Module -ListAvailable.  This will show us all the modules available on our system.  Below we can see the five Cisco modules we just installed.

PowerTool C:\> Get-Module -ListAvailable

    Directory: C:\Program Files (x86)\WindowsPowerShell\Modules

ModuleType Version    Name                                ExportedCommands
---------- -------    ----                                ----------------
Binary    Cisco.IMC                           {FnResetImcPowerProfile, FnTestImcLd...
Binary    Cisco.UCS.Core                      {Add-UcsHardwareProfile, Get-UcsPowe...
Manifest    Cisco.UCS.DesiredStateConfiguration {Get-UcsConnection, Get-ImcConnection}
Binary    Cisco.UCSCentral                    {Connect-UcsCentral, Disconnect-UcsC...
Binary    Cisco.UCSManager                    {Connect-Ucs, Disconnect-Ucs, Start-...
Script     1.0.1      Microsoft.PowerShell.Operation.V... {Get-OperationValidation, Invoke-Ope...
Binary    PackageManagement                   {Find-Package, Get-Package, Get-Pack...
Binary    PackageManagement                   {Find-Package, Get-Package, Get-Pack...
Script     3.4.0      Pester                              {Describe, Context, It, Should...}
Script    PowerShellGet                       {Install-Module, Find-Module, Save-M...

PowerTool C:\>

Next we run Get-Command -Module Cisco.UcsManager.  This displays all the Cmdlets inside this module, all 4500+ of them!  Once you’ve memorised them all we can move on… just kidding 🙂

PowerTool C:\> Get-Command -Module Cisco.UcsManager
Cmdlet          Set-UcsWwnInitiator                          Cisco.UCSManager
Cmdlet          Set-UcsWwnPool                               Cisco.UCSManager
Cmdlet          Start-UcsGuiSession                          Cisco.UCSManager
Cmdlet          Start-UcsKvmSession                          Cisco.UCSManager
Cmdlet          Start-UcsServer                              Cisco.UCSManager
Cmdlet          Start-UcsTransaction                         Cisco.UCSManager
Cmdlet          Stop-UcsServer                               Cisco.UCSManager
Cmdlet          Sync-UcsManagedObject                        Cisco.UCSManager
Cmdlet          Undo-UcsTransaction                          Cisco.UCSManager
Cmdlet          Update-UcsCatalogue                          Cisco.UCSManager
Cmdlet          Update-UcsFirmware                           Cisco.UCSManager
Cmdlet          Watch-Ucs                                    Cisco.UCSManager

PowerTool C:\>

To connect to our UCSM we use the Cmdlet Connect-Ucs. To find out how to do this we can use Get-Help to find example syntax.

PowerTool C:\> get-help connect-ucs


    Connects to a UCS

    Connect-Ucs [-Name] <string[]> [-Credential] <PSCredential> [-Port <ushort>] [-NoSsl]
    [-NotDefault] [-Proxy <WebProxy>] [<CommonParameters>]

    Connect-Ucs -LiteralPath <string> -Key <SecureString> [-NotDefault] [-Proxy <WebProxy>]

    Connect-Ucs -Path <string> -Key <SecureString> [-NotDefault] [-Proxy <WebProxy>]

    Connects to a UCS. The cmdlet starts a new session using the specified parameters. One can
    have more than one connections to a server. PowerTool Supports working with multiple default
    servers. This can be enabled by setting SupportMultipleDefaultUcs using

We’re now ready to make our first connection.  In the below example we connect using the Cmdlet Connect-Ucs and save the connection to the variable $handle1.  This gives us the flexibility to connect to multiple UCSM devices at the same time and run commands against them.  Something which I’ll cover more on in a future post.

PowerTool C:\> $handle1 = Connect-Ucs -Name

Running the command gives a credential request dialog box. Enter in the same credentials you normally would when connecting to your UCSM.

If we run Get-UcsPSSession we can display our current session details.  Here you can see that we’re connected to UCS UCSPE-10-1-1-11

PowerTool C:\> Get-UcsPSSession

NumPendingConfigs : 0
Ucs : UCSPE-10-1-1-11
Cookie : 1494751391/e26549b0-557a-4ba7-83a8-c1ae36468ebb
Domains : org-root
LastUpdateTime : 14-May-17 6:43:14 PM
Name :
NoSsl : False
NumWatchers : 0
Port : 443
Priv : {aaa, admin, ext-lan-config, ext-lan-policy...}
PromptOnCompleteTransaction : False
Proxy : 
RefreshPeriod : 600
SessionId : 
TransactionInProgress : False
Uri :
UserName : ucspe
Version : 3.1(2b)
VirtualIpv4Address :
WatchThreadStatus : None

Here’s where things get a little interesting.  We can export this session to an XML file, using Export-UcsPSSession, and with a secure key we can connect to our UCS in the future without providing credential details.

In the below example we export our current session to an XML file called ucspe.xml and type in a secure key.  Next using ConvertTo-SecureString we can export the key we used to a file called ucspe.key which we can use to decrypt our password in the XML file.

PowerTool C:\> Export-UcsPSSession -LiteralPath C:\cisco\ucspe.xml
cmdlet Export-UcsPSSession at command pipeline position 1
Supply values for the following parameters:
Key: ********

PowerTool C:\> ConvertTo-SecureString -String "Password" -AsPlainText -Force | ConvertFrom-SecureString | Out-File ucspe2.key

Now we can use our key file and our XML file to connect to our UCSM without being prompted for credentials.

PowerTool C:\> $key = ConvertTo-SecureString (Get-Content C:\cisco\ucspe.key)

PowerTool C:\> $handle1 = connect-ucs -Key $key -LiteralPath C:\cisco\ucspe.xml

The key file should, of course, be treated as highly sensitive.  Steps should be taken to protect unauthorized people accessing and reading this file.  I find a good way to protect it is by locking down permissions on the file and folder where the XML and key file are stored.  In my case only myself and the Scheduled Task account that requires it can access the file.

Last we should know how to cleanly disconnect from our UCSM session.  This simply requires the use of Disconnect-Ucs.  In the below example we also reference our session in the variable $handle1 which is good practice if we are connecting to multiple UCSM devices.

PowerTool C:\> Disconnect-Ucs -Ucs $handle1

In Part 1 of this series I cover the minimum requirements you need on your system before install PowerTool.  I then go through the fundamental basics of making your first connection to a UCS Manager. Then taking it one step further and showing how we can future connect without providing credentials. Finally I show how to disconnect from the UCSM. In Part 2 of this series I will run through the basics of querying information from UCSM via some of the 4500+ Cmdlets.

Cisco UCS PowerTool Suite – Part 1
Cisco UCS PowerTool Suite – Part 2
Cisco UCS PowerTool Suite – Part 3

Cisco UCS PowerTool Suite
Cisco UCS PowerTool Suite Communities Page

Make PowerShell As Cool As You. Modify Your Default Profile.

Do you feel that PowerShell just isn’t as cool as you?  Do you wish that you could make it cool like yourself?  Me too!

So how do we do this?  By modifying the default PowerShell profile.  The default profile is just a standard ps1 file that runs each time you launch a PowerShell Console.  A quick search online and you’ll find there are five different locations this profile can live -crazy huh.   There’s All Users, ISE, Personal.  The best one to modify I found is the one that lives in your WindowsPowerShell folder in your User Profile path (C:\Users\{Username}\Documents\WindowsPowerShell\).  By default the file probably doesn’t exist but you can easily create it by making a file called profile.ps1 and placing in this path.

One of the quickest ways to enhance the PowerShell prompt is to add a little ASCII art to PowerShell when the console is first loaded.   I originally got the idea from a session I went to by Chris Wahl.  Chris used a simple one line piece of ACSII art showing his venting of emotion flipping a table.  You can find a lot of this art at  The issue I found was using the extended ASCII character set was difficult to use.  Most of the time it didn’t translate well using Write-Host in PowerShell.

This gave me the idea of using a here-string to create a multi-line string.  It opens the door to creating large ACSII art images using the standard character set which makes it much more compatible on-screen.  A good starting place for this art is

So how can we achieve this?  As mentioned above we create a profile.ps1 file in ‘C:\Users\{Username}\Documents\WindowsPowerShell\’.  Then paste our art between @” and “@ characters and save it to a variable.  In the below example we call it $block.

We can print it out on the screen using Write-Host which also allows us to change the foreground color using -ForegroundColor.

$block = @"

.     .       .  .   . .   .   . .    +  .
  .     .  :     .    .. :. .___---------___.
       .  .   .    .  :.:. _".^ .^ ^.  '.. :"-_. .
    .  :       .  .  .:../:            . .^  :.:\.
        .   . :: +. :.:/: .   .    .        . . .:\
 .  :    .     . _ :::/:               .  ^ .  . .:\
  .. . .   . - : :.:./.                        .  .:\
  .      .     . :..|:                    .  .  ^. .:|
    .       . : : ..||        .                . . !:|
  .     . . . ::. ::\(                           . :)/
 .   .     : . : .:.|. ######              .#######::|
  :.. .  :-  : .:  ::|.#######           ..########:|
 .  .  .  ..  .  .. :\ ########          :######## :/
  .        .+ :: : -.:\ ########       . ########.:/
    .  .+   . . . . :.:\. #######       #######..:/
      :: . . . . ::.:..:.\           .   .   ..:/
   .   .   .  .. :  -::::.\.       | |     . .:/
      .  :  .  .  .-:.":.::.\             ..:/
 .      -.   . . . .: .:::.:.\.           .:/
.   .   .  :      : ....::_:..:\   ___.  :/
   .   .  .   .:. .. .  .: :.:.:\       :/
     +   .   .   : . ::. :.:. .:.|\  .:/|
     .         +   .  .  ...:: ..|  --.:|
.      . . .   .  .  . ... :..:.."(  ..)"
 .   .       .      :  .   .: ::/  .  .::\


Write-Host $block -ForegroundColor Green

We don’t stop here though.  There’s a few other things we can do.  Most of my code lives in a specific folder.  So we can modify the default folder path that PowerShell opens to by added the below code to the bottom of the profile.ps1 file.  The next time PowerShell opens its defaults to this path.

Set-Location 'C:\Folder\Code'

Let’s now fix that crappy Title Bar and change it to something more inspirational.

$host.ui.RawUI.WindowTitle = 'Know yourself and you will win all battles.'

Finally let’s fix that bland prompt and give it a little color.

function Prompt
    $promptString = "PS " + $(Get-Location) + "&gt;"
    Write-Host $promptString -NoNewline -ForegroundColor Cyan
    return " "

Let’s see what our PowerShell Console now looks like.  Much better!  We can now show people how cool we really are.  When people see our console they will tremble in our PowerShell skillz 😛

Putting it all together, let’s see what the code looks like.

$block = @"

.     .       .  .   . .   .   . .    +  .
  .     .  :     .    .. :. .___---------___.
       .  .   .    .  :.:. _".^ .^ ^.  '.. :"-_. .
    .  :       .  .  .:../:            . .^  :.:\.
        .   . :: +. :.:/: .   .    .        . . .:\
 .  :    .     . _ :::/:               .  ^ .  . .:\
  .. . .   . - : :.:./.                        .  .:\
  .      .     . :..|:                    .  .  ^. .:|
    .       . : : ..||        .                . . !:|
  .     . . . ::. ::\(                           . :)/
 .   .     : . : .:.|. ######              .#######::|
  :.. .  :-  : .:  ::|.#######           ..########:|
 .  .  .  ..  .  .. :\ ########          :######## :/
  .        .+ :: : -.:\ ########       . ########.:/
    .  .+   . . . . :.:\. #######       #######..:/
      :: . . . . ::.:..:.\           .   .   ..:/
   .   .   .  .. :  -::::.\.       | |     . .:/
      .  :  .  .  .-:.":.::.\             ..:/
 .      -.   . . . .: .:::.:.\.           .:/
.   .   .  :      : ....::_:..:\   ___.  :/
   .   .  .   .:. .. .  .: :.:.:\       :/
     +   .   .   : . ::. :.:. .:.|\  .:/|
     .         +   .  .  ...:: ..|  --.:|
.      . . .   .  .  . ... :..:.."(  ..)"
 .   .       .      :  .   .: ::/  .  .::\


Write-Host $block -ForegroundColor Green

Set-Location 'C:\Folder\Code'

$host.ui.RawUI.WindowTitle = 'Know yourself and you will win all battles.'

function Prompt
    $promptString = "PS " + $(Get-Location) + "&gt;"
    Write-Host $promptString -NoNewline -ForegroundColor cyan
    return " "

Pretty simple right.  A few small additions and we’ve brought our console to life.  When all is said and done though, none of this will actually make us better scripters.  But when your spending all day at a console prompt why not bring a little of you into it?  I’d love to know what you do?

Streaming Datasets – PowerShell | PowerCLI | Power BI

A large part of my day is spent scripting in PowerShell, specifically with PowerCLI.  One of the strongest areas of PowerCLI, obviously, is being able to retrieve information.  It’s one of the key use cases, in my opinion, for using PowerCLI in a VMware environment, it’s ability to retrieve information for Capacity planning and reporting.

Recently I’ve been looking at how to consume all that information.  You can obviously export it to a CSV, push it into a database, or something that I’ve been playing around with recently, stream it into Power BI.  Now if you haven’t tried it out yet, PowerBI is an analytics service from Microsoft.  At its core it’s a data warehouse for business intelligence.  But putting all those fancy words aside, I use it to create fancy reports.

Exporting information out of a vCenter environment with PowerCLI is dead simple.  I have dozens of scheduled tasks running all the time doing this.  Where I’ve fallen down, is taking that information and trending it over time.  This is where the Streaming Datasets functionality of Power BI comes in.  Using PowerCLI I can get an Object and Value from vCenter and then Post that directly into Power BI, using their API, and have it instantly graphed in a report.  I can then share that report out to anyone I want.  Power BI lets me do this over and over, almost as fast as I can pull the information out of vCenter.

In the example below I show how to create a trend report over time that displays Total and Available Storage of a vCenter Cluster.  Rather simple, I know, but can easily be adapted to show things like number of running VMs running, reserved resources used, etc, etc.  The skies the limit really.

Before we do any scripting the first thing we do is log into Power BI.  If you don’t have an account, don’t worry, the basic version is free.  Hit the Sign Up link and make sure you select Power BI and not Power BI Desktop for Windows, we want the cloud version.

Once logged in we click on Streaming Datasets in the bottom left under the Datasets category.  This is where we create our initial dataset schema so that it can accept streaming input.  We click on ‘Add streaminig dataset’ in the top right.

Then select the source of data, which will be API and click next.

We give our New Streaming Dataset a name and define a few values.  In this example we will define a Date, Total Storage, and Available Storage value, turn on Historic Data Analysis and click Create.  Make note of your data type to the right of the value.  Date is DateTime and the other two are Numbers.

We’ve now created our schema and are provided with a Push URL address and sample code in a few different formats (we want PowerShell).  If you look carefully we are using an Invoke-RestMethod to Post to Power BI.  This sample code has just provided us the template and hardest part of our PowerShell / PowerCLI script.  Click over the code and copy / pasta it out to use in our script (Paste it at the bottom of the script as it will be the last thing that runs).

Now we actually start on the PowerShell / PowerCLI script.  To keep it as concise as possible.  I’ve skip the process I use to actually connect to the vCenter and retrieve the information out using PowerCLI in the code below.  The real goal here is just to retrieve some values and get that into Power BI.  Line 6 is basically retrieving all shared VMFS datastores in Cluster1.  The important lines to note, though, are 4, 8, and 9 where I store my key values in three variables.  One for Date, one for TotalStorage, and one for AvailableStorage.

Import-Module VMware.VimAutomation.Core
Connect-VIServer -Server host.mydomain.local

$date = Get-Date

$datastore = Get-Cluster -Name Cluster1 | Get-Datastore | Where-Object {$_.Type -eq 'VMFS' -and $_.Extensiondata.Summary.MultipleHostAccess}

$TotalStorage = ($datastore | Measure-Object -Property CapacityMB -Sum).Sum / 1024
$AvailableStorage = ($datastore | Measure-Object -Property FreeSpaceMB -Sum).Sum / 1024 

The additional lines below from 11 onward is the important code.  This is our pasted sample code from Power BI that we will slightly modify to push our values up to Power BI.  Don’t copy mine, as your URL and key will be different.  On lines 13, 14, and 15 we will remove the example values and replace it with our three variables, $Date, $TotalStorage, and $AvailableStorage.

Import-Module VMware.VimAutomation.Core
Connect-VIServer -Server -user "mydomain\username"

$date = Get-Date

$datastore = Get-Cluster -Name Cluster1 | Get-Datastore | Where-Object {$_.Type -eq 'VMFS' -and $_.Extensiondata.Summary.MultipleHostAccess}

$TotalStorage = ($datastore | Measure-Object -Property CapacityMB -Sum).Sum / 1024
$AvailableStorage = ($datastore | Measure-Object -Property FreeSpaceMB -Sum).Sum / 1024 

$endpoint = ""
$payload = @{
"Date" = $Date
"Total Storage" = $TotalStorage
"Available Storage" = $AvailableStorage
Invoke-RestMethod -Method Post -Uri "$endpoint" -Body (ConvertTo-Json @($payload))

Disconnect-VIServer * -Confirm:$false

On the last line I disconnect  from my vCenter and close any sessions.  This helps if running as a scheduled task.  Finally save the script.

And that’s it for the scripting part.  Assuming everything is correct, no connection issues, correct values being retrieved.  All we have to do is run the script and it will send a POST request using Invoke-RestMethod with our three values.  We can now run this script as many times as we want and it will continue to post the current date and time along with Total Storage and Available Storage.  At this point, if we wish, we can turn the script into a scheduled task or just continue to run manually to suit our needs.

We now go back to Power BI and report on what we have.  Back on our Streaming Datasets browser window we click the Create Report icon under actions.  Now this part is going to be very subjective to the end user who wants the report.  But the key data we want is under RealTimeData on the far right.  Select all three values and we get presented with a default view of our data.  Under Visualizations select line chart and now we start to see a more visual representation of our capacity over time.  Under the Analytics section add a trend line and see a basic view of available capacity over time.  Finally hit save and you have a self updating report from streaming data.

For the report to start to look anything like below it will take time and a few sample datasets.  In the below image I’ve mocked up some numbers over time as an example.

Once you have a working script and it’s streaming data to PowerBI it’s really up to you on how to report on it.  The above example, as simple as it is, lays the ground work to more customized and complex reporting that you might not be able to get out of traditional monitoring and reporting software.  The ability is there to even share out the report.

Streaming datasets, as you might have noticed in the UR, is still in beta.  As great as I have found it to be it does have some quirks.  For one you can’t easily modify data you have already streamed up to Power BI.  So if you send incorrect data / values up to Power BI in a streaming dataset it will remain their.  At which point you will have to consider Filters to exclude it in reports.

In summary I think Power BI is a very underrated free tool from Microsoft.  I’ve only just started to scratch the surface of what’s possible with it.  The simplicity of capturing data with PowerShell and sending it to Power BI is well worth the time and effort to try at least once.  So what are you waiting for?

PowerShell on Linux

The big news out of Microsoft last month making headlines is the open sourcing of PowerShell.  Along with this comes the ability to now run PowerShell not just in Windows but also Linux and Mac OS X.  For people close to the PowerShell community this wasn’t unexpected, but make no mistake this is huge news.

I’m really liking this new Microsoft.  They are really embracing this open source stuff.  On first thought it’s not obvious how Microsoft will make money with PowerShell going open source.  But Microsoft isn’t stupid, this is no doubt part of a larger master plan.  With PowerShell so tightly linked to their products they are opening the door to a whole new demographic of users.  I can see PowerShell going open source being a key to getting a new mix of Linux Developers working in Azure.  Something close to my heart is VMware have also announced plans to port over PowerCLI to work with PowerShell for Linux.  As a PowerCLI tragic myself I’ve seen first hand how frustrated Mac users have been that they can’t manage their VMware infrastructure using PowerShell / PowerCLI directly from a Mac.

Microsoft have made it clear this is very early stages of an Alpha release on GitHub.  They are looking for community help to further develop and refine using PowerShell on Linux.  There’s a large number of bug fixes, growing by the day, that they need to work through before we get anywhere close to a production release.

I decided to try it out myself and i’m impressed, the future looks awesome.  Apart from Windows currently the open source version is limited to Ubuntu 14.04 /16.04, CentOS 7, and Mac OS X 10.11.

I had an Ubuntu 14.04 Linux VM that I used testing.  The first thing is to download the appropriate package over at GitHub.

Once downloaded and depending on what OS you’re running you may need to install a few additional libraries first.  In my case it was libnuwind8 and libicu52 using apt-get. After which i was able to install the PowerShell Debian package. 

[email protected]:~/Downloads$ sudo apt-get install libunwind8 libicu52
[email protected]:~/Downloads$ sudo dpkg -i powershell_6.0.0-alpha.9-1ubuntu1.14.04.1_amd64.deb

Believe it or not that’s all that is required.  Whatever your Shell of choice is just type ‘powershell

[email protected]:~/Downloads$ powershell
Copyright (C) 2016 Microsoft Corporation. All rights reserved.

PS /home/mukotic/Downloads> 

So what can we do.  Well, it’s still early days.  The first thing i did was just check the version.  I can see we’re running the .Net Core release of PowerShell which comes with Nano Server.

PS /home/mukotic/Downloads> $psversiontable 

Name Value 
---- ----- 
PSVersion 6.0.0-alpha 
PSEdition Core 
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...} 
GitCommitId v6.0.0-alpha.9 
WSManStackVersion 3.0 
PSRemotingProtocolVersion 2.3 

Looking at what’s available to us it’s still limited to a handful of modules.

PS /home/mukotic/Downloads> Get-Module -ListAvailable 

 Directory: /opt/microsoft/powershell/6.0.0-alpha.9/Modules

ModuleType Version Name ExportedCommands 
---------- ------- ---- ---------------- 
Manifest Microsoft.PowerShell.Archive {Compress-Archive, Expand-Archive} 
Manifest Microsoft.PowerShell.Host {Start-Transcript, Stop-Transcript} 
Manifest Microsoft.PowerShell.Management {Add-Content, Clear-Content, Clear-ItemProperty, Join-Path...} 
Manifest Microsoft.PowerShell.Security {Get-Credential, Get-ExecutionPolicy, Set-ExecutionPolicy, ConvertFrom-SecureString...
Manifest Microsoft.PowerShell.Utility {Format-List, Format-Custom, Format-Table, Format-Wide...} 
Binary PackageManagement {Find-Package, Get-Package, Get-PackageProvider, Get-PackageSource...} 
Script 3.3.9 Pester {Describe, Context, It, Should...} 
Script PowerShellGet {Install-Module, Find-Module, Save-Module, Update-Module...} 
Script 0.0 PSDesiredStateConfiguration {StrongConnect, IsHiddenResource, Write-MetaConfigFile, Get-InnerMostErrorRecord...} 
Script 1.2 PSReadLine {Get-PSReadlineKeyHandler, Set-PSReadlineKeyHandler, Remove-PSReadlineKeyHandler, G...

So those traditional Windows cmdlets will now work against the local Linux box.  Things like Get-Process will return the local running Linux processes.

PS /home/mukotic/Downloads> Get-Process

Handles NPM(K) PM(K) WS(K) CPU(s) Id SI ProcessName 
------- ------ ----- ----- ------ -- -- ----------- 
 0 0 0 0 0.400 1331 549 accounts-daemon 
 0 0 0 0 0.350 1111 111 acpid 
 0 0 0 0 0.000 2248 205 at-spi-bus-laun 
 0 0 0 0 0.040 2264 205 at-spi2-registr 
 0 0 0 0 0.000 147 0 ata_sff

Another thing that’s also worth checking out is Visual Studio Code.  This is another great open source project Microsoft has going.  If you’ve used PowerShell ISE in Windows, think of a stream lined version of that, just more powerful leveraging extensions.  Head over to and download the package.

Installation was also super simple.

PS /home/mukotic/Downloads> sudo dpkg -i code_1.4.0-1470329130_amd64.deb.deb

Then run by typing ‘code’

PS /home/mukotic/Downloads> code

Ubuntu 14.04 - VMware Workstation-000296

I recommend getting the PowerShell extension right off the bat.  Click the Extensions icon on the left, search for PowerShell, and click Install

Ubuntu 14.04 - VMware Workstation-000297

Now we have all the wonders of Intellisense that we are use to in the Windows PowerShell ISE.  I really see Visual Studio Code becoming a future replacement for the Windows PowerShell ISE, which while still in development, has been quite stagnated in recent years.

So there you have it.  Jeffrey Snover, a Technical Fellow, in the Microsoft Enterprise Cloud Group has a great post and video discussing PowerShell going open source that should be checked out.

The next thing I’m hanging out for is PowerCLI on Linux.  A demo is shown in a video in the above link running inside a Docker container.  Expect to soon see a VMware Fling release for us to try out.

Meetups, PowerShell, Expanding My Horizons


I’m not sure what it’s like in other major cities around the world.  But currently Melbourne is going through an IT meetup boom.  On any given week you can find at least one if not multiple meetups going on somewhere in Melbourne.  A big change of years past where we would have only a couple major conferences a year to look forward to.  It’s really quite an exciting period for meetups we’re going through.

So what is going on with all these meetups  —Meetup being the new buzz word we’re seeing slowly replacing the traditional User Group we’re all probably use to.  I think it’s in small part to do with the website  Sure, many of these User Groups have existed well before became a thing.  But to find them you had to be part of the right Facebook group, follow the right twitter user, or just learn of it through some word of mouth.  I lost count before on how many User Group meetings I missed by learning about it the next day.

We now have a common place we can visit to find all these User Groups and meetups.  Type in DevOps, PowerShell, VMware and dozens of meetups pop up in your local area.  RSVP and see all the other local users also going, not sure what the meetup is about, post a quick question and receive an answer right back.  There’s an update to a meeting, receive an email notification immediately.  I see it as a symbiotic relationship between a globally accepted meetup site and the user group.  We at the Melbourne VMware User Group have even started using it in conjunction with the traditional VMUG website to extend our community base.


This is how I found out about the recent PowerShell meetup I attended in Melbourne.  With all the scripting I’ve recently been doing in PowerCLI and PowerShell I wanted to expand my horizons a little further and find out how the wider PowerShell community works.  The group has only existed since the start of the year and this was their fourth meetup held in the offices.  The setting for the meetup was very casual and devoid of any advertising or marketing.  That is if you can overlook the office seek logos all over the place.  But considering the worst seek can actually do is find me a new job I’m more than happy to tolerate this 🙂   Of course there was the obligatory Beer and Pizzas which we all know elevates a good meetup to an awesome meetup.

sccm2012A found the format and atmosphere of this PowerShell meetup very appealing.  Heavy on practical content & demos and light on PowerPoint slides.  The setting around a large boardroom table with beer and pizza in hand also lead to a more comfortable environment to engage with community and presenters.  The meetup tended to have a slant towards DevOps practices using PowerShell rather than using PowerShell.  So less about how to connect to this server or use that cmdlet and more around processes and integration.  I was also lucky enough to receive a copy of the book, Learn System Center Configuration Manager in a Month of Lunches, from its author James Bannan.

Due to work commitments of the organiser, the PowerShell meetup was pushed out a day which turned out conflicted with an Azure meetup on the same night.  With so many IT meetup groups current listed and running in Melbourne.  There’s bound to be a small culling, a kind of survival of the fittest, happen.  So whether this PowerShell meetup group succeeds or not only time will tell.  I certainly hope it does and they continue to find that DevOps centric content it aims for.

Until the next meetup…

Melbourne VMUG Meetup Group

Get-View | Show-Object

I was recent watching a PowerShell presentation where they mentioned a cool module called PowerShellCookbook and in particular discussed a cmdlet in it called Show-Object by Lee Homes.  I instantly knew how perfect and powerful it would be with VMware’s PowerCLI Get-View.

Bare with me for a minute while I lay the ground work with Get-View.  If you’ve ever used Get-View in PowerCLI you’ll know that it brings back a ridiculous wealth of information.  When you run a cmdlet like Get-VMHost it’s really only bringing back a small subset of information back on that object.  Sometimes this is fine but sometimes we need that little bit extra to reach our objective.

For example you can run Get-VMHost esxi01.ukoticland.local

Windows PowerShell ISE-000282

What you get is a default formatted table view displaying only a few key values.  A trick some of us do is then pipe this out to a list.  Get-VMHost esxi01.ukoticland.local | Format-List

Windows PowerShell ISE-000283

Heaps more information right, but it’s still not the full picture.  There’s still a lot of information on this object that we’re missing.  Take the original cmdlet we ran above and this time let’s pipe it to Get-View.  Let’s also store it in a variable called $myHost, just so we can work with it.

$myHost = Get-VMHost esxi01.ukoticland.local | Get-View

Windows PowerShell ISE-000284

Okay, on first glance it doesn’t look like much.  But all those values that start with VMware.Vim are properties that can be drill down into.  For example $myHost.Config and $myHost.Config.Capabilities

Windows PowerShell ISE-000288

So it’s pretty cool right.  We can now start retrieving a huge amount of new information that wasn’t available to use before.  But this is like finding a needle in a haystack.  I know I’ve wasted so much time typing $something dot something dot something in the hopes of finding a value I can work with.

Well finally this brings us to Show-Object.  This is an awesome cmdlet that will let you display the object retrieved with Get-View in a grid view window that you can navigate through similar to a directory in File Explorer.  Using it is as simply as piping our variable to Show-Object.

$myHost | Show-Object

Windows PowerShell ISE-000287

Now we can explore and click around at everything available to us.  As you navigate the object in the top pane for results you’ll get member data in the bottom pane.  I see this becoming a great reference tool to help find what you’re looking for.  Not only that but it will give you the syntax to retrieve the information selected in the view pane.

So how do you get Show-Object?  Well, it’s not in PowerShell by default but can easily be obtained from the PowerShell Gallery, which, if new to you, is basically a public repository for PowerShell content.  If you’re using Windows 10 you’re half way there.  If not go get yourself the Windows Management Framework (WMF) 5. This will give you the latest version of the PowerShellGet module.  Then it’s just a matter of typing Install-Module -Name PowerShellCookbook.

Once the module is installed from the PowerShell Gallery, Show-Object is now available to use.  It’s worth noting that PowerShellCookbook comes with a huge array of extra cmdlets also worth exploring.

Finally if you do try out Show-Object and like it, there’s a “jacked up” version of it over at PoshCode by Justin Rich