Hey, Scripting Guy! How Can I Verify Input Received from the Command Line?

ScriptingGuy1

 Hey, Scripting Guy! Question

I am the script writer at my company, and I have really been enjoying your articles on Windows PowerShell. I have begun the process of converting some of our old VBScripts to Windows PowerShell, and all of my new scripts are written in Windows PowerShell. Because I am the only one who writes scripts at my company (in fact, I am the only one who even understands scripting), I write all of my scripts, whether in VBScript or in Windows PowerShell, so that they use command-line arguments. I have a problem, however, when people type in the wrong value for one of my command-line parameters. It can be as simple as they misspell the name of the target computer, but it can be more complicated than that as well. Do you have any special Scripting Guy tricks that you can share with me to help solve this problem?


— DS

Hey, Scripting Guy! AnswerHello DS,

I have some great tricks I can share with you. One of my favorite tricks when I am scuba diving is to get down real low (while ensuring that I avoid touching anything) and then when taking pictures I shoot in a more upward direction. This causes the sunlight to reflect through the water, and it brings more blue into the picture. This trick is illustrated in the following picture, which I took while scuba diving off of the coast of Little Cayman.

Image of underwater scene near Little Cayman


To verify input that is received from the command line, you can use the contains operator to examine the contents of an array of possible values. This technique is illustrated here where an array of three values is created and stored in the variable $noun. The contains operator is then used to see if the array contains “hairy-nosed wombat“. Because the $noun variable does not have an array element that is equal to the string “hairy-nosed wombat” the contains operator returns False.

PS C:> $noun = “cat”,”dog”,”rabbit”
PS C:> $noun -contains “hairy-nosed wombat”
False
PS C:>

If an array contains a match, the contains operator returns True. This is seen here:

PS C:> $noun = “cat”,”dog”,”rabbit”
PS C:> $noun -contains “rabbit”
True
PS C:>

The contains operator returns True only when there is an exact match. Partial matches return False. This is seen here.

PS C:> $noun = “cat”,”dog”,”rabbit”
PS C:> $noun -contains “bit”
False
PS C:>

The contains operator is case insensitive. Therefore, it will return True when matched, regardless of case. This is seen here:

PS C:> $noun = “cat”,”dog”,”rabbit”
PS C:> $noun -contains “Rabbit”
True
PS C:>

If you need to perform a case sensitive match, you can use the case sensitive version of the contains operator—ccontains. As seen here, it will return true only if the case of the string matches the value contained in the array:

PS C:> $noun = “cat”,”dog”,”rabbit”
PS C:> $noun -ccontains “Rabbit”
False
PS C:> $noun -ccontains “rabbit”
True
PS C:>

In the Get-AllowedComputers.ps1 script, a single command-line parameter is created that is used to hold the name of the target computer for the WMI query. The computer parameter is a string, and it receives the default value from the environmental drive. This is a good technique because it ensures the script will have the name of the local computer, which could then be used in producing a report of the results. If you set the value of the computer parameter to localhost, you never know what computer the results belong to. This is seen here:

Param([string]$computer = $env:computername)

The Get-AllowedComputer function is used to create an array of permitted computer names and to check the value of the $computer variable to see if it is present. If the value of the $computer variable is present in the array, the Get-AllowedComputer function returns true. If the value is missing from the array, the Get-AllowedComputer function returns false. The array of computer names is created by using the Get-Content cmdlet to read a text file that contains a listing of computer names. The text file, Servers.txt, is a plain ASCII text file that has a list of computer names on individual lines:

Image of the Servers.txt file


A text file of computer names is easier to maintain than a hard-coded array that is embedded in the script. In addition, the text file can be placed on a central share and can be used by many different scripts. The Get-AllowedComputer function is seen here:

Function Get-AllowedComputer([string]$computer)
{
 $servers = Get-Content -path c:fsoservers.txt
 $servers -contains $computer
} #end Get-AllowedComputer function

Because the Get-AllowedComputer function returns a Boolean value (true or false), it can be used directly in an if statement to determine if the value that is supplied for the $computer variable is on the permitted list. If the Get-AllowedComputer function returns true, the Get-WmiObject cmdlet is used to query for BIOS information from the target computer. This is seen here:

if(Get-AllowedComputer -computer $computer)
 {
   Get-WmiObject -class Win32_Bios -Computer $computer
 }

On the other hand, if the value of the $computer variable is not found in the $servers array, a string is displayed that states the computer is not an allowed computer:

Else
 {
  “$computer is not an allowed computer”
 }

The complete Get-AllowedComputer.ps1 script is seen here.

Get-AllowedComputer.ps1

Param([string]$computer = $env:computername)

Function Get-AllowedComputer([string]$computer)
{
 $servers = Get-Content -path c:fsoservers.txt
 $servers -contains $computer
} #end Get-AllowedComputer function

# *** Entry point to script ***

if(Get-AllowedComputer -computer $computer)
 {
   Get-WmiObject -class Win32_Bios -Computer $computer
 }
Else
 {
  “$computer is not an allowed computer”
 }

You are not limited to only testing for specified computer names in the Get-AllowedComputer function. All you need to do is add additional information to the text file. This is seen here:

Image of ServersAndProperties.txt file


A couple of modifications are all that are required to the Get-AllowedComputerAndProperty.ps1 script. The first is to add an additional command-line parameter to allow the user to choose which property to display. This is seen here:

Param([string]$computer = $env:computername,[string]$property=”name”)

Next, the signature to the Get-AllowedComputer function is changed to permit passing of the property name. Instead of directly returning the results of the contains operator, the returned values are stored in variables. The Get-AllowedComputer function first checks to see if the $servers array contains the computer name. It then checks to see if the $servers array contains the property name. Each of the resulting values is stored in variables. The two variables are then “anded” together and the result is returned to the calling code. When two Boolean values are anded together, only the True and True case is equal to true. This is seen here:

PS C:> $true -and $false

False

PS C:> $true -and $true

True

PS C:> $false -and $false

False

PS C:>

The revised Get-AllowedComputer function is seen here:

Function Get-AllowedComputer([string]$computer, [string]$property)
{
 $servers = Get-Content -path c:fsoserversAndProperties.txt
 $s = $servers -contains $computer
 $p = $servers -contains $property
 Return $s -and $p
} #end Get-AllowedComputer function

The if statement is used to determine if both the computer value and the property value are contained in the allowed list of servers and properties. If the Get-AllowedComputer function returns true, the Get-WmiObject cmdlet is used to display the chosen property value from the selected computer. This is seen here:

if(Get-AllowedComputer -computer $computer -property $property)
 {
   Get-WmiObject -class Win32_Bios -Computer $computer |
   Select-Object -property $property
 }

If the computer value and the property value are not on the permitted list, the Get-AllowedComputerAndProperty.ps1 script displays a message stating that there is a nonpermitted value. This is seen here:

Else
 {
  “Either $computer is not an allowed computer, `r`nor $property is not an allowed property”
 }

The complete Get-AllowedComputerAndProperty.ps1 script is seen here.

Get-AllowedComputerAndProperty.ps1

Param([string]$computer = $env:computername,[string]$property=”name”)

Function Get-AllowedComputer([string]$computer, [string]$property)
{
 $servers = Get-Content -path c:fsoserversAndProperties.txt
 $s = $servers -contains $computer
 $p = $servers -contains $property
 Return $s -and $p
} #end Get-AllowedComputer function

# *** Entry point to script ***

if(Get-AllowedComputer -computer $computer -property $property)
 {
   Get-WmiObject -class Win32_Bios -Computer $computer |
   Select-Object -property $property
 }
Else
 {
  “Either $computer is not an allowed computer, `r`nor $property is not an allowed property”
 }

DS, we hope you have enjoyed today’s article, and have found the text file trick at least as interesting as the trick of shooting up toward the surface when you are scuba diving. We have one more article to go in our series about error handling. So join us tomorrow. If you want to be among the first to be informed about everything that is happening on the Script Center, you can follow us on Twitter. We also make postings at the Scripting Guys group on Facebook. If you get stuck while you are working on a script, you can post to the Official Scripting Guys Forum. We have an excellent group of moderators and other active members who are always willing to help other scripters. See you tomorrow. Take care.

Ed Wilson and Craig Liebendorfer, Scripting Guys

 

 

0 comments

Discussion is closed.

Feedback usabilla icon