PowerShell Function to Create CimSessions to Remote Computers with Fallback to Dcom

I've found myself writing the same code over and over in my PowerShell scripts where I'm performing a task that requires me to create a CimSession to one or more computers without knowing what version of PowerShell is installed on the remote computers or if PowerShell is even installed on the remote computers.

While it is possible to create a CimSession to a remote computer in any of those scenarios I just described, it's a fair amount of code to add to multiple scripts and then the same redundant code ends up being in multiple files which creates a nightmare if you ever find an issue with the code and need to update it for any reason.

I decided to turn the code I would use to create these CimSessions into a function which is shown below and add it to a script module so I could just call the function from the PowerShell script that needed the CimSessions created before the script performs its task(s).

 1#Requires -Version 3.0
 2function New-MrCimSession {
 3<#
 4.SYNOPSIS
 5    Creates CimSessions to remote computer(s), automatically determining if the WSMAN
 6    or Dcom protocol should be used.
 7.DESCRIPTION
 8    New-MrCimSession is a function that is designed to create CimSessions to one or more
 9    computers, automatically determining if the default WSMAN protocol or the backwards
10    compatible Dcom protocol should be used. PowerShell version 3 is required on the
11    computer that this function is being run on, but PowerShell does not need to be
12    installed at all on the remote computer.
13.PARAMETER ComputerName
14    The name of the remote computer(s). This parameter accepts pipeline input. The local
15    computer is the default.
16.PARAMETER Credential
17    Specifies a user account that has permission to perform this action. The default is
18    the current user.
19.EXAMPLE
20     New-MrCimSession -ComputerName Server01, Server02
21.EXAMPLE
22     New-MrCimSession -ComputerName Server01, Server02 -Credential (Get-Credential)
23.EXAMPLE
24     Get-Content -Path C:\Servers.txt | New-MrCimSession
25.INPUTS
26    String
27.OUTPUTS
28    Microsoft.Management.Infrastructure.CimSession
29.NOTES
30    Author:  Mike F Robbins
31    Website: http://mikefrobbins.com
32    Twitter: @mikefrobbins
33#>
34    [CmdletBinding()]
35    param(
36        [Parameter(ValueFromPipeline)]
37        [ValidateNotNullorEmpty()]
38        [string[]]$ComputerName = $env:COMPUTERNAME,
39
40        [System.Management.Automation.Credential()]$Credential = [System.Management.Automation.PSCredential]::Empty
41    )
42
43    BEGIN {
44        $Opt = New-CimSessionOption -Protocol Dcom
45
46        $SessionParams = @{
47            ErrorAction = 'Stop'
48        }
49
50        If ($PSBoundParameters['Credential']) {
51            $SessionParams.Credential = $Credential
52        }
53    }
54
55    PROCESS {
56        foreach ($Computer in $ComputerName) {
57            $SessionParams.ComputerName  = $Computer
58
59            if ((Test-WSMan -ComputerName $Computer -ErrorAction SilentlyContinue).productversion -match 'Stack: ([3-9]|[1-9][0-9]+)\.[0-9]+') {
60                try {
61                    Write-Verbose -Message "Attempting to connect to $Computer using the WSMAN protocol."
62                    New-CimSession @SessionParams
63                }
64                catch {
65                    Write-Warning -Message "Unable to connect to $Computer using the WSMAN protocol. Verify your credentials and try again."
66                }
67            }
68
69            else {
70                $SessionParams.SessionOption = $Opt
71
72                try {
73                    Write-Verbose -Message "Attempting to connect to $Computer using the DCOM protocol."
74                    New-CimSession @SessionParams
75                }
76                catch {
77                    Write-Warning -Message "Unable to connect to $Computer using the WSMAN or DCOM protocol. Verify $Computer is online and try again."
78                }
79
80                $SessionParams.Remove('SessionOption')
81            }
82        }
83    }
84}

This function will create a CimSession to a remote computer(s) using the WSMAN protocol if the stack version is 3.0 or higher:

new-mrcimsession3.png

The following regular expression matches any version that is 3.0 or higher:

1([3-9]|[1-9][0-9]+)\.[0-9]+
  • [3-9] Numbers three through nine.
  • | or
  • [1-9] Numbers one through nine. 
  • [0-9] Followed by numbers zero through nine.
  • + One or more times.
  • \. A "dot" is a special character so it must be escaped with a backslash.
  • [0-9]+  Numbers zero through nine. One or more times.

I'll use this function to create a CimSession to servers named SQL01 and SQL03:

1New-MrCimSession -ComputerName SQL01, SQL03

new-mrcimsession1.png

Notice in the previous example that one CimSession was created with the WSMAN protocol and the other one with DCOM. Believe it or not, SQL03 is a Windows 2008 Server (non-R2) that does NOT have PowerShell installed at all:

new-mrcimsession2.png

The previously created CimSessions can be used to query information from WMI on the remote computers regardless of which underlying protocol is used for communication:

1Get-CimInstance -CimSession (Get-CimSession) -ClassName Win32_OperatingSystem |
2Select-Object -Property PSComputerName, Caption

new-mrcimsession4.png

Update:

The most recent version can be downloaded from my PowerShell repository on GitHub.

µ