Sunday, July 06, 2014

Save Command Parameters in a file.

I have not seen much about his in any blogs although all of the pieces have been blogged many times.

We may want to save the argument set for a command to use in the future however we may not want to run a different script each time we want to customize the command.  Saving a configuration and using one of many configurations is a common pattern in programming.  Saving configurations in INI, CSV and XML files is common but all have drawbacks in PowerShell.  Many time we want to have strongly types arguments like 'booleans' or script blocks and objects.  PowerShell has two file formats that can easily do this; Export-CliXML and ConvertTo-Xml

Here is a simple technique to save command parameters in a CliXml file.

We start with a simple command function that was borrowed from another project because it can be altered to demonstrate how this technique works.  Any CmdLet or advanced function can use this technique

We will start with this part of a function that has numerous parameters that we might want to apply from a file.

The Test function

function New-FileSystemWatcher{
Param(
[string]$Name='FSW',
[Parameter(Mandatory=$true)]
[string]$Path,
[bool]$IncludeSubdirectories=$false,
[string]$Filter='*.*',
[Parameter()]
[ValidateSet(
'FileName','DirectoryName','Attributes','Size',
'LastWrite','LastAccess','CreationTime','Security'
)][string[]]$NotifyFilter,
[int]$BufferSize=8192,
[scriptblock]$ChangedScript,
[scriptblock]$CreatedScript,
[scriptblock]$RenamedScript,
[scriptblock]$DeletedScript,
[scriptblock]$ErrorScript,
[switch]$AllOnChangedScript
)
}

This function has a pretty good range of parameter types and requirements.  It should help with testing.

The Splat

We can call our function with full or partial arguments like this:

New-FileSystemWatcher –Name MyTest  -Path c:\somefolder –Filter *.txt … etc

If we add one line to out test function we can see the results of our call arguments.

$PSBoundParameters

We can pass arguments and get a list of the arguments that we have passed ('bound') like this:

image

If we pass more arguments we will get them displayed.

image

Now we can splat and test.

What is a "splat"?

Here is a very simple explanation of a splat: http://technet.microsoft.com/en-us/magazine/gg675931.aspx

In simple terms a "splat" is shorthand for bundled arguments.    A splat is a hash containing our arguments:

$props=@{Name='SplatTest';Path='e:\somepath'}

image

If we take the variable named 'props' and add '@' in front we have told PowerShell to use the hash to supply the parameter arguments by name.  You can see that the output echoes the exact arguments we have supplied in the 'Splat' or @spalt.

How can we use a @Splat from a file?

Start by creating a template from the 'Param' statement and edit it to be a legal hash table  I did this here by removing all decoration and removing the $' from all parameters like this:

$param=@{
Name=[string]'Default'
Path=[string]$pwd
IncludeSubdirectories=$false
Filter='*.*'
NotifyFilter=[string[]]'LastWrite'
BufferSize=[int]8192
ChangedScript=$null
CreatedScript=[scriptblock]$null
RenamedScript=[scriptblock]$null
DeletedScript=[scriptblock]$null
ErrorScript=[scriptblock]$null
AllOnChangedScript=[bool]$null
}

.You can set any Name to an default value you find is useful or required for your template. Here I supplied some required defaults lie Name, Path and NotifyFilter.,

This is the result of test my splat template:

image

Now we save the template to an CliXML file like this:

$param | Export-CliXml FSWTemplate.clixml

We can import it and alter any parameters needed to create a custom argument set.

image
.

Now we can load a template and create custom copies by just exporting the changed hash table to a new file.  We can even create a file loaded with hash tables that can be added to and extracted by name.  We can do all of this without using XML or managing strings or custom file structures.

To find out how to build and edit files with multiple hash tables see the next blog post.