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).

#Requires -Version 3.0
function New-MrCimSession {
<#
.SYNOPSIS
    Creates CimSessions to remote computer(s), automatically determining if the WSMAN
    or Dcom protocol should be used.
.DESCRIPTION
    New-MrCimSession is a function that is designed to create CimSessions to one or more
    computers, automatically determining if the default WSMAN protocol or the backwards
    compatible Dcom protocol should be used. PowerShell version 3 is required on the
    computer that this function is being run on, but PowerShell does not need to be
    installed at all on the remote computer.
.PARAMETER ComputerName
    The name of the remote computer(s). This parameter accepts pipeline input. The local
    computer is the default.
.PARAMETER Credential
    Specifies a user account that has permission to perform this action. The default is
    the current user.
.EXAMPLE
     New-MrCimSession -ComputerName Server01, Server02
.EXAMPLE
     New-MrCimSession -ComputerName Server01, Server02 -Credential (Get-Credential)
.EXAMPLE
     Get-Content -Path C:\Servers.txt | New-MrCimSession
.INPUTS
    String
.OUTPUTS
    Microsoft.Management.Infrastructure.CimSession
.NOTES
    Author:  Mike F Robbins
    Website: http://mikefrobbins.com
    Twitter: @mikefrobbins
#>
    [CmdletBinding()]
    param(
        [Parameter(ValueFromPipeline)]
        [ValidateNotNullorEmpty()]
        [string[]]$ComputerName = $env:COMPUTERNAME,

        [System.Management.Automation.Credential()]$Credential = [System.Management.Automation.PSCredential]::Empty
    )

    BEGIN {
        $Opt = New-CimSessionOption -Protocol Dcom

        $SessionParams = @{
            ErrorAction = 'Stop'
        }

        If ($PSBoundParameters['Credential']) {
            $SessionParams.Credential = $Credential
        }
    }

    PROCESS {
        foreach ($Computer in $ComputerName) {
            $SessionParams.ComputerName  = $Computer

            if ((Test-WSMan -ComputerName $Computer -ErrorAction SilentlyContinue).productversion -match 'Stack: ([3-9]|[1-9][0-9]+)\.[0-9]+') {
                try {
                    Write-Verbose -Message "Attempting to connect to $Computer using the WSMAN protocol."
                    New-CimSession @SessionParams
                }
                catch {
                    Write-Warning -Message "Unable to connect to $Computer using the WSMAN protocol. Verify your credentials and try again."
                }
            }

            else {
                $SessionParams.SessionOption = $Opt

                try {
                    Write-Verbose -Message "Attempting to connect to $Computer using the DCOM protocol."
                    New-CimSession @SessionParams
                }
                catch {
                    Write-Warning -Message "Unable to connect to $Computer using the WSMAN or DCOM protocol. Verify $Computer is online and try again."
                }

                $SessionParams.Remove('SessionOption')
            }
        }
    }
}

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:

([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:

New-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:

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

new-mrcimsession4.png

Update:

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

µ