Category Archives: Stupid Draft

My Write-Verbose Best Practice

If you’ve read this post, and perhaps the ones before it, then you know that my advanced function templates have always used Write-Verbose statements for logging purposes. Anytime you want to log something using my template, it’s using Write-Verbose whether you know it or not. There’s multiple places you can log, and it’s all based on the value of the Log parameter (in 2.0 and greater). As of the 2.x versions, you can use … -Log ToScreen, … -Log ToScreenAndFile, and … -Log ToFile. Again, regardless of which way you choose to log, it’s Write-Verbose that’s doing the work. Okay fine, it’s really Out-File if you’re writing to a file, although my nested function is still called Write-Verbose. That said, there actually was a time when it was all Write-Verbose, even when writing to a file.

So, I’ve always had a specific way to write my logging statements. There’s no agreed upon best practice for Write-Verbose statements, but for me there is, and that’s why I’m writing again today. Maybe it’ll make sense to use this model for yourself, as well.

In the instance where something is about to happen (think, happens right after the current logging statement ends), I strive to use an “ing” word. From what I remember about my grade school years, I remember this as a present progressive. Here’s a few examples.

Write-Verbose -Message "$BlockLocation Setting required variables."
Write-Verbose -Message "$BlockLocation Checking if the current time zone is $DesiredTimeZone."
Write-Verbose -Message "$BlockLocation Collecting Forest FSMO Roles."
Write-Verbose -Message "$BlockLocation Displaying all FSMO Roles."
Write-Verbose -Message "$BlockLocation Downloading $Application installer from S3."
Write-Verbose -Message "$BlockLocation Installing $Application silently."
Write-Verbose -Message "$BlockLocation Invoking user is ""$env:USERDOMAIN\$env:USERNAME"" on the ""$env:COMPUTERNAME"" computer."

In my experience I tent to use an “ing” words about 80 – 90% of the time. There is, however, one other verb form I find myself using, and that’s the past tense verb form. Sometimes, it makes sense to indicate that something has completed even when a new logging, “ing” statement would indicated the previous logging topic had ended. Here’s a few examples from some of my functions.

Write-Verbose -Message "$BlockLocation Determined the time zone is not correctly set for $DesiredTimeZone."
Write-Verbose -Message "$BlockLocation Unhandled exception ($($Error[0].Exception.GetType().FullName))."
Write-Verbose -Message "Connected to Exchange Server: $ExchServ."

While looking for other worthy examples, I did find a few Write-Verbose statements that didn’t include either an “ing,” or “ed” verb. These are very rare for me, but they have been included at times to indicate information to whomever is reading the logging statements.

Notice, however, that they come just before a statement that uses “ing.” They probably shouldn’t be there, and wouldn’t be there if I was writing that tool today. Then again, they might be, as now that I think about it, and look over this older code, the logging differed because of its audience. In this case, having indicated the key and value already existed, did not exist, or did exist and needed correction, was important enough to convey. So much so, the “ing” word didn’t feel as though it was enough.

#region Create Registy Key(s) and add value (if necessary).
If (-Not($Exists)) {
	Write-Verbose -Message "$BlockLocation Registry key and value do not yet exist."
	Write-Verbose -Message "$BlockLocation Creating new Registry key and value."
	[System.Void](New-Item $RegKey -Force | New-ItemProperty -Name $RegName -Value $RegValue -Force)
	$CheckChange = $true
	$FixType = 'changed'

} ElseIf ((Get-ItemProperty -Path $RegKey -Name $RegName -ErrorAction SilentlyContinue).$RegName -ne $RegValue) {
	Write-Verbose -Message "$BlockLocation Registry key and value already exist, but the value is not correct."
	Write-Verbose -Message "$BlockLocation Correcting the Registry value."
	[System.Void](New-Item $RegKey -Force | New-ItemProperty -Name $RegName -Value $RegValue -Force)
	$CheckChange = $true
	$FixType = 'corrected'

} Else {
	Write-Verbose -Message "$BlockLocation Registry key and value already exist, and the value is correct."

So, there’s that: My Write-Verbose best practice. While it wasn’t a stupid draft so much, there’s one less in the drafts!

Learning from Failure

I wrote a recent blog post that went from being a longtime draft, to finally being a published post. The idea was twofold: get a post out of my drafts already, and in doing so, teach by highlighting my failure. It’s weird, but it works.

It shouldn’t be too surprising that it works, however. Much of what we know can likely be attributed to either our own failure, or the failure of someone else, whether we know it or not. It’s not often we learn something new without some sort of mistake along the way. It’s just that the failure portion — how we potentially got to where we are, which ought to be success — isn’t always recognized, or acknowledge, or put forth as something from which others can learn, and actually see for themselves.

After my first, stupid draft turned post, post, I received the below Twitter comment. This was someone that noticed that through my failure, I was able to teach; I was ultimately able to succeed at potentially teaching those that read the post, by sharing what I had learned by failing.

For as long as I can, I’ll keep looking over my drafts to see what else we can collectively learn by my failure. It’s how we get better at everything, because it’s not often that we understand everything the first time we learn it — depending on what it is of course. Accept failure, and learn from it. I’ll do the same and see what else I can share from which we can both learn something new.

An Alias and Function Change

At current, my site has 230 published posts. It’s 231 when this one goes live. Those are all written by me since mid 2014. I’m not sure of my per month average, but I can say for sure that I’ve never missed a month.

Outside of those 230 published posts, are 40 some drafts. Those are posts I started and never finished for one reason or another. Sometimes, I realized what I thought worked really didn’t, and therefore wasn’t able to complete the post. Well, in an effort to clean up the drafts, I’m publishing my first stupid draft turned post. Here’s goes… It’s learning from my failure — enjoy.

For just about as long as I can remember, I’ve always created an alias for my functions, just before the function is defined. This is of course when a function is defined outside of a module, such as when it’s defined in my $PROFILE script. In the below example, I do just that. After the alias is created, I define the function for which my alias can be used to invoke the function.

Set-Alias -Name saw -Value Show-AWord
Function Show-AWord {
    '!! A Word !!'

PS > saw
!! A Word !!

There’s another way to do this, as well. You can create the alias after the function’s been defined. You just swap the commands.

Function Show-EWord {
    '** E Word **'
Set-Alias -Name sew -Value Show-EWord

PS > sew
** E Word **

And here’s where the post went stupid.

I’ve always been mildly annoyed that I needed to have the code outside of the function, whether it’s before, or after, the function definition. I always wished there was a way to create aliases from inside the function.

Well there is, and there’s always been. I’ve just never given it much thought until about five minutes ago. This might be why I started this post; I didn’t think about it long enough. Here’s nearly the same function as above; however, now we’ll create the alias for the function, within the function. Because the Set-Alias cmdlet has a scope parameter, we can create a global alias from inside the function.

Function Show-GWord {
    Set-Alias -Name sgw -Value Show-GWord -Scope Global
    '$$ G Word $$'

PS > sgw
PS > # Nothing

Here’s about the time, I realized my problem. If you create an alias inside the function (using the Global scope [that’s how it “works”]), the alias is not going to exist until after the function has been invoked for the first time. Therefore, the function would have to be run like the below example. I pretty much removed a line outside the function, put it into the function, and then added another line outside the function. Ugh, not what I was after all.

PS > Show-GWord | Out-Null
PS > sgw
$$ G Word $$

So yeah, this post didn’t go as planned. No wonder it made its home in my drafts. It makes you wonder though. Why isn’t there a way to run some code inside a function when the function is being defined? Maybe because functions belong in modules and modules give you this ability when they’re imported, via their module manifest, and potentially, their ScriptsToProcess.

There you have it. A stupid draft I published.