#PowerShell: Splatting a Local Hash Table in a Remote Session

I'm sure that most people who use PowerShell on a regular basis are familiar with the Using variable scope modifier which allows for the use of local variables in a remote session. This functionality was introduced with PowerShell version 3:

1$MyVar = 'Bits', 'W32time'
2
3Invoke-Command -ComputerName DC01 {
4    Get-Service -Name $Using:MyVar
5}

using-splatting1a.jpg

A fairly simple concept, right? But wait a minute, did you know that you can also define a local hash table to be used with splatting in a remote session using this same concept?

1$MyParams = @{
2    ClassName = 'Win32_Service'
3    Filter = "Name = 'bits' or Name = 'W32time'"
4}
5
6Invoke-Command -ComputerName DC01 {
7    Get-CimInstance @Using:MyParams
8}

using-splatting2a.jpg

The previous example is a simple one, but this concept comes in handy when writing an advanced function where you've wrapped your function around PowerShell remoting like in the following example where I use a hash table from the local session to control the PassThru, WhatIf, and Confirm parameters that are taking place in the remote session:

 1#Requires -Version 3.0
 2function Start-MrAutoStoppedService {
 3
 4<#
 5.SYNOPSIS
 6    Starts services that are set to start automatically, are not currently running,
 7    excluding the services that are set to delayed start.
 8
 9.DESCRIPTION
10    Start-MrAutoStoppedService is a function that starts services on the specified
11    remote computer(s) that are set to start automatically, are not currently running,
12    and it excludes the services that are set to start automatically with a delayed
13    startup. This function requires PowerShell version 3 or higher on the machine it
14    is being run from, PowerShell version 2 or higher on the remote machine that it is
15    being run against, and PowerShell remoting to be enabled on the remote computer.
16
17.PARAMETER ComputerName
18    The remote computer(s) to check the status and start the services on.
19
20.PARAMETER Credential
21    Specifies a user account that has permission to perform this action. The default
22    is the current user.
23
24.PARAMETER PassThru
25    Returns an object representing the service. By default, this function does not
26    generate any output.
27
28.EXAMPLE
29     Start-MrAutoStoppedService -ComputerName 'Server1', 'Server2'
30
31.EXAMPLE
32     Start-MrAutoStoppedService -ComputerName 'Server1', 'Server2' -PassThru
33
34.EXAMPLE
35     'Server1', 'Server2' | Start-MrAutoStoppedService
36
37.EXAMPLE
38     Start-MrAutoStoppedService -ComputerName 'Server1', 'Server2' -Credential (Get-Credential)
39
40.INPUTS
41    String
42
43.OUTPUTS
44    None or ServiceController
45
46.NOTES
47    Author:  Mike F Robbins
48    Website: http://mikefrobbins.com
49    Twitter: @mikefrobbins
50#>
51
52    [CmdletBinding(SupportsShouldProcess)]
53    param (
54        [Parameter(Mandatory,
55                   ValueFromPipeline,
56                   ValueFromPipelineByPropertyName)]
57        [string[]]$ComputerName,
58
59        [System.Management.Automation.Credential()]$Credential = [System.Management.Automation.PSCredential]::Empty,
60
61        [switch]$PassThru
62    )
63
64    BEGIN {
65        $Params = @{}
66        $RemoteParams = @{}
67
68        switch ($PSBoundParameters) {
69            {$_.keys -contains 'Credential'} {$Params.Credential = $Credential}
70            {$_.keys -contains 'PassThru'} {$RemoteParams.PassThru = $true}
71            {$_.keys -contains 'Confirm'} {$RemoteParams.Confirm = $true}
72            {$_.keys -contains 'WhatIf'} {$RemoteParams.WhatIf = $true}
73        }
74
75    }
76
77    PROCESS {
78        $Params.ComputerName = $ComputerName
79
80        Invoke-Command @Params {
81            $Services = Get-WmiObject -Class Win32_Service -Filter {
82                State != 'Running' and StartMode = 'Auto'
83            }
84
85            foreach ($Service in $Services.Name) {
86                Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\$Service" |
87                Where-Object {$_.Start -eq 2 -and $_.DelayedAutoStart -ne 1} |
88                Select-Object -Property @{label='ServiceName';expression={$_.PSChildName}} |
89                Start-Service @Using:RemoteParams
90            }
91        }
92    }
93}

The Start-MrAutoStoppedService function shown in the previous code example can be downloaded from my PowerShell repository on GitHub.

µ