The 2013 Scripting Games started April 25th, and event 4 is now open for voting. As I did in the previous events, I will pick out two entries from each event and provide some learning points to highlight both good and bad practices.
Before reading my comments, you might want to download the event instructions:
The first entry I will comment on is from Beginner 4:
- Comment based help is leveraged to provide a synopsis, description and basic usage. Comment-based help and the Active Directory module which is leverage was introduced in PowerShell 2.0, thus #requires –version 2.0 could have been used to prevent users trying to run this in PowerShell 1.0 getting error messages.
- HTML-formatting (head, pre- and post-content) as well as a couple of other variables is defined (note that I have updated my previous article with more info on working with HTML in PowerShell). I would also suggest the search base to be specified as a variable rather than a hard coded path in the script. Although, this is specifically stated in the synopsis.
- The time stamp for when the report was created is included in the bottom of the report as required by the event instructions. In addition the username of the user generating the report is added, which is nice.
- The actual cmdlets generating the report is a one-liner, nicely formatted on multiple lines for readability.
- The lastlogon date property is used to determine when the users last logged on to the domain. There are ways to retrieve this information, and not all of them is accurate. For example the lastlogontimestamp property will be 9-14 days behind the current date. For more information, see this article on the “Ask the Directory Services Team” blog. To get a more accurate time stamp, you might want to query all domain controller, see this TechNet article for one example on how to accomplish this. Although I would not withdraw any points for not catching this “gotcha”, I would give a bonus point for those who did.
The second entry I have decided to comment on is from Advanced 4:
- Leveraging the #requires statement is a good practice, however, this should be separated into two lines. When the script is run “as is” in PowerShell 2.0 the following error will be returned: “Cannot process the “#requires” statement at line 1 because it is not in the correct format.”. If separating into two lines, it will work in both 2.0 and 3.0:
#Requires -Version 3.0
#Requires -Module ActiveDirectory
- Comment based help is leveraged in an excellent way, providing both help for all parameters as well as several examples.
- [CmdletBinding()] is defined in order to use [Parameter()] decorators to validate input. Although there is nothing wrong with parameterizing this as a script, I would consider to turn it into a function (a personal preference).
- The FilePath parameter is marked as mandatory, as well as positional. This is perfectly fine, but another option would be to default to a path using an environment variable (for example $env:userprofile\Documents\Report.html). The requirement of validating the filename extension (htm or html) is accomplished using a regular expression inside a ValidateScript validation.
- The Count parameter is configured with a default value of 20 as required. In addition ValidateRange is leveraged to make sure the number specified is valid. This is not necessary, as defining the parameter as an integer would perform the necessary validation:
Cannot convert value “2222222222222222″ to type “System.Int32″. Error: “Value was
either too large or too small for an Int32.
- Two additional parameters is supplied: One for overwriting the report-file if it exists (-Force) and one returning the newly created HTML file (-PassThru). These two parameters provide additional functionality not required by the instructions.
- The parameter values for ConvertTo-Html is quite large, and providing these as a hashtable and leveraging splatting makes it more readable. This also makes it possible to collapse/expand the HTML-code (the hashtable) in PowerShell ISE.
- The PSCustomObject type accelerator is used to create new objects. There are many ways to create new objects in PowerShell 3.0, but this is the easiest/preferred way in my opinion. Also, the new [ordered] type adapter in PowerShell 3.0 is leveraged to decide the order of the properties, rather than using Select-Object which will actually create new objects (more overhead).
Like the previous events, there have been many great submissions in event 4. Keep up the good work, and good luck with event 5 – “The Logfile Labyrinth”.