Hey, Scripting Guy! What Are the Areas for Improvement You See in Scripts Submitted for the 2010 Scripting Games?

Hey, Scripting Guy! What Are the Areas for Improvement You See in Scripts Submitted for the 2010 Scripting Games?

  • Comments 3
  • Likes


Bookmark and Share

 

Hey, Scripting Guy! Question

Hey, Scripting Guy! What type of errors and mistakes did you notice in the entries for the 2010 Scripting Games?

-- BA

 

Hey, Scripting Guy! Answer

Hello BA,

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.

                     Image of using Get-Date cmdlet 

  • 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

Get-Process

  • 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 scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

 

Ed Wilson and Craig Liebendorfer, Scripting Guys

 

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • This is a very interesting blogpost. I read a lot of things that I can use to improve my code. One thing that I noticed is that you mentioned the Test-Computer cmdlet. But that doesn't exist. You probably have to change this into the Test-Connection cmdlet.

  • Great advice, a solid list, but I take issue with one point.  The use of the Foreach-Object cmdlet is by far more efficient from a keystrokes perspective, but the Foreach statement IS faster. I would argue that when scripting performance is more important.  Hence the use of the Foreach language statement is the best practice. It is not only easier to read a Foreach loop as the variable is named and can be given context (I know what $file is $_ could be anything), but it IS much faster. Unfortunately there are times when using Foreach requires you to breakup you're code, and results in something that is hard to read.... I'm not trying to make a blanket statement.  The truth is you should try BOTH, and use what ever works best for you're situation.

    Don't get me wrong the pipeline is a fantastic thing, but it can be abused. Another example of this would be using where-object to filter results on a cmdlet that supports filtering (Get-WMIObject,Get-ChildContent,etc)!  

    I really like the idea of deducting points for reinventing the wheel. Anyways, keep up the great work, look forward to next year!

    ~Glenn

  • Great article, as usual, but I DO take issue with one point: "Functions should be organized in the order in which they are called."

    My preference, and it is no more than that, is to put functions in alpha order.  This way, I can always find them and am not forced to go back and re-arrange entries when I change my logic.

    Just a thought...