Hey, Scripting Guy! What Are the Areas for Improvement You See in Scripts Submitted for the 2010 Scripting Games?
Hey, Scripting Guy! What type of errors and mistakes did you notice in the entries for the 2010 Scripting Games?
Microsoft Scripting Guy Ed Wilson here. I am a really laid back sort of guy, and I do not like the words “errors” and “mistakes.” I prefer to think in terms of opportunities for improvement. There are several themes I have seen as I was reviewing the scripts submitted for the 2010 Scripting Games.
- Thinking in terms of VBScript. It is common that you will want to transfer your knowledge of VBScript into Windows PowerShell, and that’s okay. However, Windows PowerShell has a number of features that make it much easier to work with. Here are some examples to illustrate what I am talking about.
- If I ignore the error, maybe it will go away! For example, it was common for people to have On Error Resume Next at the top of their VBScript scripts. I have seen some people try to set $ErrorActionPreference = “SilentlyContinue” in a similar vein. This was not a good idea in VBScript land, and it certainly is not a good idea in Windows PowerShell world. You should anticipate errors, and attempt to handle them, rather than mask them. This is one reason I added that little bit of fun to the troubleshooting script for Event 10.
- Using a bucket instead of turning on the pipeline. Not taking advantage of the pipeline? In VBScript you would often read the contents of something into a variable, and then you would use either For or For…Each…Next to iterate through it. In Windows PowerShell, you can still take that approach, but the problem is that it takes time to read something and to populate the variable. When you use the pipeline, you begin processing items immediately. This is often a faster approach.
- I’m going to write a letter (or two) to the host, using the Write-Host cmdlet to display information on the Windows PowerShell console. In VBScript it was common to use Wscript.Echo to display information from within the script. When people see Write-Host, they think of it as an equivalent operation. There is very little reason to use Write-Host to display information. Most objects will display information on the Windows PowerShell console without any intervention. Keep your objects intact as long as possible in your script. When you use the Write-Host, Format-Table, Format-List, etc., cmdlets, you destroy the object in the pipeline. This can complicate your attempts to add additional functionality to your script later.
- Hanging with the old string gang. In VBScript, it was common to do string manipulation to do things such as manipulate paths, munge dates, and create file names. In Windows PowerShell, there are cmdlets that will manipulate paths (Split-Path, Join-Path) and cmdlets to work with dates (Get-Date). You should use these instead of resorting to string manipulation because your code will be easier to read and more robust as well.
- Not taking advantage of the power of Windows PowerShell. Time and again I saw scripts in which the author implemented a piece of code—often at great expense of time and effort, not to mention clarity—to do something that Windows PowerShell accomplishes natively. Next year, I think I will instruct the judges to deduct 1 point for this, at least in the Advanced category. Here are some examples of what I am talking about:
- Writing Help functions when Windows PowerShell 2.0 includes help tags to allow the script or function to integrate with the Get-Help cmdlet.
- Writing a ping function using WMI’s Win32_PingStatus when Windows PowerShell 2.0 includes the Test-Connection cmdlet.
- Using WMI or .NET Framework classes to work with the registry when Windows PowerShell has a registry provider.
- Using WMI to read an event log, when Windows PowerShell has the Get-EventLog cmdlet as well as Get-WinEvent.
- Using all kinds of strange string manipulation to try to split the path into parent path and child path, instead of using the Split-Path cmdlet.
- Using string concatenation to join paths instead of using the Join-Path cmdlet.
- Using [datetime]::now instead of the Get-Date cmdlet to retrieve the current date time. This is seen in the following image.
- Spaghetti code. A good script should be easy to read. It should be well organized. Move your code into functions: My ideal function is one that accomplishes a specific unit of work. This will promote code re-use. Functions should be organized in the order in which they are called. By all means, indent sections of code, and align your code to make it easier to follow. Do not get too carried away with indenting. I saw some scripts that were tabbed over 180 spaces. I do not like to scroll when I am reading my code; I follow the out of sight, out of mind rule here, and prefer to keep within the confines of the monitor. For the Hey, Scripting Guy! Blog, I limit my lines to around 80 characters.
- Include helpful comments. Most of the scripts I saw included lots of comments, but many of them were meaningless. A good comment should tell the reader something about what the function does, assumptions made in the design, known issues, and areas for future expansion. I saw very few scripts that did that. Most of what I saw were comments telling people what they already know. You should write your comments for a person who knows at least the basics of Windows PowerShell. If you need to look up something on MSDN or you find something on the Internet, by all means add the URL to the comments. But do not do something like this:
# Now lets get a list of processes
- Thinking that longer is better. This is not true; use as much code as you need, but don’t add stuff that is unnecessary.
- Using aliases in scripts. Because this event is called the Scripting Games, it is safe to assume that the code is aimed at scripts, even if the script is a single line. Therefore, aliases and positional parameters are not appropriate because they are not assumed to be universal. Aliases can be deleted or redefined—even system aliases.
- Functions that return strings instead of objects. In general it is a best practice to return objects from your functions. This promotes code re-use. If you wish to format the data in a specific fashion, pass the object to another function to format the output, or handle the return object in your code.
BA, these are some of the main things I saw during the 2010 Scripting Games. This brings our 2010 Scripting Games Wrap-Up Week 2 to a close. Come back tomorrow for the Weekend Scripter when we will talk about…wait a minute.
If you want to know exactly what we will be looking at tomorrow, follow us on Twitter or Facebook. If you have any questions, send e-mail to us at firstname.lastname@example.org, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson and Craig Liebendorfer, Scripting Guys