Are your functions standalone?

Are you sure you can take a function from one script and paste it into another and it will work, or do you find that your new script fails because a variable is set to null or does not exist at all?  If this happens it’s probably because when you wrote the script you used variables that existed in the main script  inside the function but when you ‘transplanted’ the function into a new script it was not obvious that you needed to grab the lines of code that instantiated the variable values in the main script and so now the function does not work as expected if at all.  The latter is probably a better outcome as at least your know that the function needs to be fixed.  If it runs without errors then the silent failure probably means your new script is actually not working properly and you might never notice, e.g. a reporting script that does not show all the expected users because a variable is  not instantiated.   This might lead to an audit failure when it turns out users still have access but your script if failing to highlight this.

$testVariable = 10 in the main script is the same as $script:testVariable = 10

It’s easy to use variables inside a function that were instantiated in the main script and this is because variables have script scope by default when created in the main script body.  A variable instantiated line this $testVar = 10 in the main script is actually the same as typing $script:testVar = 10 and for good measure $local:testVar is of script scope too ( confusing, a little maybe).

Warning contains explicit variables 🙂

Your function can choose to reference $script:testVariable or $testVariable and sloppy coding could mean you get the wrong value if you also have a local scope variable in the function.  You really should be explicit when referencing a variable in a function.   If you want to use a script scope variable in the function you should either pass it as a parameter or use $script:testVar within the function.  If you don’t do this then you might be heading for a debug nightmare as carelessly ignoring the scope of variables will bite you one day for sure.   I guess technically we should always use the variable scope as part of the variable name, i.e. use $local:, $script: or $global: if we really want to be pedantic about it.  This may have been a useful strategy if using $local in the main script meant the variable could not be used in any of the called functions but alas this is not the case so maybe this is just too much effort for little gain.

$script:ShowDebug and $script:Padright

I spend, probably too much time, making my scripts not only look nice when reading the code but also in the debug messages look ‘readable’ 🙂  I learnt a long time ago that debugging can be painful so I now use a function to control my debug messages to screen.   My Write-Msg function can write message to screen and the eventlog and even to a log file as well as highlight particular words int eh message string.  This means that when I’m debugging, or ‘hand cranking’ the code as I like to say I can just see the information that’s important in the mass of messages as they fly by on screen.  This beats write-verbose or write-debug strategies hands down which are all one colour and you just can’t see whats important.

For neatness I also like to force a common line length to every message displayed which is a simple case of using the .padright method of a string object.  So that I can easily control the length of every message I use a variable to control this so it’s easy to change later, i.e. $padright = 150 and write-host “”.padright($padight,”-“) will draw a night delimiter across the screen 150 characters wide.    If I update the variable then every write-host command is updated as they all use $padright as the line length.

Using script scope variables in a function and setting them if they don’t exist

I use the same variable name in all my functions so that the can write debug messages in the function and I’ll either pass it as a parameter or I’ll just use the $script:padright variable.  Even better are the functions that accept the variable value as a parameter but if the parameter does no exist it not only uses the script cope variable it creates one if it does not exist.  That way if my default value in one function was 100 and in another 150 they all use the same value depending on which function was called first.

Using this strategy on any non local variables in your functions guarantees that the function is portable.

Example useage

Function Test-Params
param (
[parameter(Mandatory=$false,Position=0,HelpMessage = "Sets the debug message line    padding to be applied - Default is 150")][int]$padright
)
if ( $padright -eq 0 ) {
if ( Test-Path variable:script:padright ) { $padright = $script:padright }
else {
$padright = 150
$script:padright = $padright
}
}
if ( $showDebug ) {
Write-Host "".padright($padright,"-") -ForegroundColor Green -BackgroundColor Black }
Advertisements

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 )

Google photo

You are commenting using your Google 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 )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.