Behind the PowerShell Pipeline logo

Behind the PowerShell Pipeline

Subscribe
Archives
June 4, 2024

CimSession PowerShell Scripting

Last week, I was working on updates to the [PSScriptTools](https://github.com/jdhitsolutions/PSScriptTools) module. I am adding new functions based on `Get-CimClass`. As I was working, I ended up diving deeper into how the CIM cmdlets work and realized I could write more efficient functions with the results of my research and testing. Normally, whenever I write a PowerShell function that wraps around `Get-CimInstance`, I always try to have parameter sets so that the user can specify a computer name or an existing CIMSession.

Function Get-CimOS {

    [CmdletBinding(DefaultParameterSetName = 'ClassNameComputerSet')]

    Param(

        [Parameter(

            Position = 0,

            ParameterSetName = 'CimInstanceSessionSet',

            Mandatory,

            ValueFromPipeline

        )]

        [Microsoft.Management.Infrastructure.CimSession[]]$CimSession,

        [Parameter(

            Position = 0,

            ParameterSetName = 'ClassNameComputerSet',

            ValueFromPipeline

        )]

        [Alias('CN', 'ServerName')]

        [string[]]$ComputerName = $env:Computername,

        [Alias('OT')]

        [uint32]$OperationTimeoutSec

    )

    Begin {

        Write-Verbose "Starting $($MyInvocation.MyCommand)"

        $PSBoundParameters.Add('Namespace', 'Root\CimV2')

        $PSBoundParameters.Add('ClassName', 'Win32_OperatingSystem')

        $PSBoundParameters.Add('ErrorAction', 'Stop')

        $PSBoundParameters.Add('Property', @('CSName','Caption','Version','BuildNumber','InstallDate','OSArchitecture'))

        Write-Verbose ($PSBoundParameters | Out-String)

    } #begin

    Process {

        Write-Verbose "Using parameter set $($PSCmdlet.ParameterSetName)"

        Try {

            Get-CimInstance @PSBoundParameters |

            Select-Object @{Name = 'Computername'; Expression = { $_.CSName } },

            @{Name = 'Name'; Expression = { $_.Caption } },

            Version, BuildNumber,InstallDate, OSArchitecture

        }

        Catch {

            Write-Warning $_.Exception.Message

        }

    } #process

    End {

        Write-Verbose "Ending $($MyInvocation.MyCommand)"

    } #end

} #end function Get-CimOS
I like having the flexibility.
PS C:\> Get-CimOS

Computername   : PROSPERO

Name           : Microsoft Windows 11 Pro

Version        : 10.0.22631

BuildNumber    : 22631

InstallDate    : 5/12/2022 9:01:53 AM

OSArchitecture : 64-bit

PS C:\> Get-CimSession -ComputerName dom1 | Get-CimOS

Computername   : DOM1

Name           : Microsoft Windows Server 2019 Standard Evaluation

Version        : 10.0.17763

BuildNumber    : 17763

InstallDate    : 3/27/2024 11:21:54 AM

OSArchitecture : 64-bit
Sometimes, I'll include a parameter for the `ComputerName` parameter set to allow the user to specify a credential. In the function, I then create a CIMSession. Internally, the function then always uses the CIMSession. Either the one passed by the user or the one created by the function. This means extra work as I also have to clean up the temporary CIMSession. However, other native PowerShell cmdlets also take this approach. Consider the syntax for `Get-Volume`. This command has a parameter that allows you to specify a computer name or CIMSession.
Get-Volume CIMSession parameter
figure 1
I always wondered how this worked, and after some digging, I have a better understanding. While I typically encourage PowerShell scripters to use cmdlets wherever possible and avoid using the .NET Framework directly, there are performance benefits with the latter. And if you subscribe to this newsletter, I'm assuming you are looking for ways to take that next step. Let's see what we can do.
Get a premium subscription for full article and archive access

Last week, I was working on updates to the PSScriptTools module. I am adding new functions based on Get-CimClass. As I was working, I ended up diving deeper into how the CIM cmdlets work and realized I could write more efficient functions with the results of my research and testing.

Normally, whenever I write a PowerShell function that wraps around Get-CimInstance, I always try to have parameter sets so that the user can specify a computer name or an existing CIMSession.

Function Get-CimOS {
    [CmdletBinding(DefaultParameterSetName = 'ClassNameComputerSet')]
    Param(
        [Parameter(
            Position = 0,
            ParameterSetName = 'CimInstanceSessionSet',
            Mandatory,
            ValueFromPipeline
        )]
        [Microsoft.Management.Infrastructure.CimSession[]]$CimSession,

        [Parameter(
            Position = 0,
            ParameterSetName = 'ClassNameComputerSet',
            ValueFromPipeline
        )]
        [Alias('CN', 'ServerName')]
        [string[]]$ComputerName = $env:Computername,

        [Alias('OT')]
        [uint32]$OperationTimeoutSec
    )

    Begin {
        Write-Verbose "Starting $($MyInvocation.MyCommand)"
        $PSBoundParameters.Add('Namespace', 'Root\CimV2')
        $PSBoundParameters.Add('ClassName', 'Win32_OperatingSystem')
        $PSBoundParameters.Add('ErrorAction', 'Stop')
        $PSBoundParameters.Add('Property', @('CSName','Caption','Version','BuildNumber','InstallDate','OSArchitecture'))
        Write-Verbose ($PSBoundParameters | Out-String)
    } #begin

    Process {
        Write-Verbose "Using parameter set $($PSCmdlet.ParameterSetName)"

        Try {
            Get-CimInstance @PSBoundParameters |
            Select-Object @{Name = 'Computername'; Expression = { $_.CSName } },
            @{Name = 'Name'; Expression = { $_.Caption } },
            Version, BuildNumber,InstallDate, OSArchitecture
        }
        Catch {
            Write-Warning $_.Exception.Message
        }
    } #process

    End {
        Write-Verbose "Ending $($MyInvocation.MyCommand)"
    } #end

} #end function Get-CimOS
Want to read the full issue?
GitHub Bluesky LinkedIn About Jeff
Powered by Buttondown, the easiest way to start and grow your newsletter.