Passing named parameters to Powershell jobs

While working on a re-write of my Exchange email stats script, I was playing around with the idea of speeding it up by multi-threading the retrieval of the logs using background jobs, starting one job for each hub transport server.

I immediatly ran into problem of passing named parameters to the scriptblock of a background job. Start-Job and Invoke-Command take a -Scriptblock argument for the command you want to run, and an -Argumentlist parameter to pass arguments to that scriptblock. Note that’s “arguments” and not “paremeters”. The argument list is $args for the script block – an array of values. You can’t use named parameters in the argument list, so whatever you’re passing to in the script block has to use positional parameters.

Now, what I need to run in that background job is Get-MessageTrackingLog – a cmdlet that takes takes several parameters, and none of them are positional. Nice. And you see that same pattern frequently in the cmdlets that come with the infrastructure management modules.

I thought about creating a kind of proxy function to mirror the cmdlet parameters and making them positional, but that seemed ugly. There had to be an easier way.

Here’s what I came up with. Start with a hash table to splat the parameters you want, and fill the values using local variables.
Now, on to the code. Once I have the hash table with all the parameters I want to use, I use a simple script block that just spits out $args and splat the hash table to that. This creates -parameter value pairs, and those get used with [scritpblock]::create to generate the scriptblock that will get used as the -scrtipblock argument for the job, with all the parameters and arguments hard-wired.

$params = @{
End = $end
EventId = $event
ResultSize = 'Unlimited'
Server = $hubserver
Start = $start
}

$sb = [scriptblock]::create("get-messagetrackinglog $(&{$args} @params)")
$init_sb = {add-pssnapin Microsoft.Exchange.Management.PowerShell.E2010}
Start-Job -Name $server -ScriptBlock $sb -InitializationScript $init_sb

And that should work with any function or cmdlet.

I used the V3 ISE and my splatting add-in:

https://mjolinor.wordpress.com/2012/01/16/ps-v3-ise-add-on-for-splatting-updated/

to create quickly create the hash table I needed to splat the parameters.

If you like this idea, there’s an open Connect request to make it a “baked in” feature in the ISE and you can help by voting it up:

https://connect.microsoft.com/PowerShell/feedback/details/722513/ise-option-to-collapse-a-cmdlets-parameters-and-arguments-to-hash-for-splatting

Advertisements

3 responses to “Passing named parameters to Powershell jobs

  1. Nice. I just posted about splatting with start-job and figuring how to get the scriptblock to work. http://jkavpowershell.wordpress.com/ I know PowerGUI had a Splat add-on and I will definitely vote for one baked right into the ISE.

  2. I like the idea of making people like you create the addins and then handing it off to others 🙂
    however, i think there should be an addin folder like there is a module folder which will import ISE addins, i’d vote for that 🙂

  3. Pingback: Episode 181 – Karl Prosser on Portable PowerShell and v3 « PowerScripting Podcast

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s