Hey, Scripting Guy! Question

Hey, Scripting Guy! I love looking at the scripts on the Script Center. I think it is amazing when a person writes you an e-mail stating they have this problem that will take like a zillion years to do manually, and you whip up a script that they can run in just a few seconds and it solves their problem. I am not sure how much you guys make, but it is not enough as far as I am concerned. There is just one thing (of course, or I would not be writing), and that nearly all of the scripts require you to open them up in Notepad or some other script editor, and make changes to the script before you run. To be perfectly honest, I do not want my help desk people opening up scripts and messing around with them.

Isn't there a way to let a script run like it was an application? I am okay with the help desk people typing the path to the script and giving it the name of a target computer, but I really don't want them fooling around with script editors. Can you help me?

- SC

SpacerHey, Scripting Guy! Answer

Hi SC,

We are completely worn out after the 2009 Summer Scripting Games. (And the new site launch. And TechEd. And...) This year was the best Scripting Games so far by nearly every metric imaginable. But you did not write and ask how the 2009 Summer Scripting Games went (don’t worry, we will post a 2009 Summer Scripting Games recap later). You are concerned about handling input for your script.

A couple of years ago while scuba diving off the coast of the island of Maui in the state of Hawaii in the United States, I (Ed) saw a beautiful raccoon butterfly fish floating along the side of a coral ledge. These fish are not exactly omnivores (I have never seen one scarfing down burgers), but they do eat a variety of food such as sponges, algae, and coral polyps. Because of the variety of food the raccoon butterfly fish eats, it must be able to sense both danger and food sources from a variety of inputs. Here's the raccoon butterfly fish I snapped that day:

Image of raccoon butterfly fish

SC, just like a raccoon butterfly fish, the possibilities are varied, and the potential combinations for input and output are many. Choosing the best input method and output destination is not always an exact science, and often the best solution might be dependent upon external factors such as limitations of network infrastructure, ease of use, or speed of development.

Reading from the command line is a traditional way to provide input to a script. It has the advantage of simplicity, which means it is easy to implement and reduces development time.

If you want the ability to alter the behavior of a script at run time and you plan to run the script in an interactive fashion, accepting input from the command line may be the best solution for you. And accepting input from the command line can be simple to implement. The biggest limitation of command-line input is the requirement for user intervention. You can circumvent the requirement of user interaction by assigning default values to the command-line parameters and by selecting default actions for script behavior.

There are several methods for receiving command-line input in a script. The simplest method is to use command-line arguments. When a Windows PowerShell script is run, an automatic variable, $args, is created. The $args variable will hold values supplied to the script when it is started.


Get-WmiObject -Class win32_bios -computername $args

The Get-Bios.ps1 script starts when you call the script and supply the name of the target computer. Because $args automatically accepts a string for the input, you do not have to place the name of the target computer in quotation marks. The period in this example is used to refer to the current directory. It is the same as typing the full path: C:\scriptingguy\get-bios.ps1 for the script. This is shown here:

PS ScriptingGuy:\> .\Get-Bios.ps1 localhost

This result of running the Get-Bios.ps1 script is seen here:

Image of result of running Get-Bios.ps1 script

Because the script accepts command-line input, you can also use the Windows PowerShell pipeline to modify the way the script runs. If you have a text file that has a listing of computer names in it, you can use the Get-Content cmdlet to read the contents of the file, pipeline it to a ForEach-Object cmdlet, and query each computer in the text file. The syntax for doing this is seen here (note that I used the foreach alias for the ForEach-Object cmdlet; this makes the command a bit easier to type and does not reduce the readability of the command):

Get-Content C:\fso\Computers.txt | foreach { C:\fso\Get-Bios.ps1 $_ }

When the command runs, this result is displayed:

Image of result displayed when command is run

If you think the previous command is too much typing, you can shorten it by the use of additional aliases. The problem with such a shortened command is it is rather difficult to read. The alias cat is used for the Get-Content cmdlet and the alias % is used for the ForEach-Object cmdlet. The shortened command would look similar to the one seen here:

cat C:\fso\Computers.txt | % { C:\fso\Get-Bios.ps1 $_ }

When you run the command, this output is displayed:

Image of output displayed when command is run

While the script is running, the value you supplied from the command is present on the Windows PowerShell variable drive. You can determine the value that was supplied to the script by querying the Windows PowerShell variable drive for the $args variable. This is seen here:

Get-Item -path variable:args

The result of running the above query is seen here:

PSPath        : Microsoft.PowerShell.Core\Variable::args
PSDrive       : Variable
PSProvider    : Microsoft.PowerShell.Core\Variable
PSIsContainer : False
Name          : args
Description   :
Value         : {localhost}
Visibility    : Public
Module        :
ModuleName    :
Options       : None
Attributes    : {}

Even though accessing the value of $args via the Windows PowerShell variable drive provides a significant amount of information, it is easier to use the Get-Variable cmdlet:

Get-Variable args

SC, we hope we have given you some useful information about gathering input for your script. Join us tomorrow as we continue with Input Week. If you want to keep up with the latest information about the Script Center, follow us on Twitter. You can also join our group on Facebook. And if you get stuck with a scripting problem, you can always post a question to the Official Scripting Guys Forum.

Ed Wilson and Craig Liebendorfer, Scripting Guys