Variables, Arrays, and Hash Tables

PowerShell Tutorial 7: Accumulate, Recall, and Modify Data


In this PowerShell training session we are going to discuss storing, retrieving, and manipulating data within PowerShell. PowerShell enables us to store information using the following methods:

  • Variables - allows us to store single bits of information.
  • Arrays - allows us to store information in an index.
  • Hash Table - allows us to store in key-value pairs.

Launch PowerShell and let’s get started…

PowerShell Variables

Think of a variable as an imaginary box where we store information. Two basic uses of variables are:

  • Store information that will be later utilized within a script.
  • Store information that is a result of running a script.

In PowerShell, variables can contain text strings, integers, and even objects (complete with properties and methods). Special variables exist, which are pre-defined within PowerShell. We have worked with one of these variables ($_) in a prior tutorial.

Special Variable Examples

  • $_ - Contains the current pipeline object, used in script blocks, filters, and the where statement.
  • $Args - Contains an array of the parameters passed to a function.
  • $Error - Contains objects for which an error occurred while being processed in a cmdlet.
  • $Home - Specifies the user’s home directory.
  • $PsHome - The directory where the Windows PowerShell is installed.

To view the complete list of Special Variables in PowerShell, type the following:

Get-Help about_automatic_variables<enter>

In VBScript, we have to declare variables before using them. For example:

dim strComputer
dim strUser
dim intDate
strComputer = “MyComputer”
etc…

In PowerShell, ALL variable names must start with the “$” character. Once data is assigned to a PowerShell variable, it’s automatically declared. The “=” operator is used to assign data to a variable. Here is a simple example of creating a variable in PowerShell:

$strComputer = “Computer1″<enter>

There is a “Set-Variable” cmdlet that can also be used:

Set-Variable -Name strUser -Value “John Doe”<enter>

You can use virtually any variable name you choose, names are not case sensitive. Note: there are illegal characters such as; ! @ # % & , . and spaces. PowerShell will throw an error if you use an illegal character.

I stated virtually any name as PowerShell does have a set of keywords that are reserved and cannot be used as variable names:

  • break
  • continue
  • do
  • else
  • elseif
  • filter
  • foreach
  • function
  • if
  • in
  • return
  • switch
  • until
  • where
  • while

When naming variables, I continue to use the caMel case naming convention I became accustomed to in VBScript. The first part of the name (str) reminds me that the variable I’m working with contains “text string” data. If I were working with numbers, it might look like something this “$intMegaBytes.” Again, you can use any naming convention you wish.

Let’s verify that the $strComputer variable is holding the data we assigned to it.

Write-Output $strComputer<enter>

-or just type-

$strComputer<enter>
PowerShell Tutorial - strComputer

$strComputer Variable

image 7.0

The output verifies the data in the $strComputer variable is the “Computer1″ text string. Go ahead and verify the data value for the “strUser” variable.

$strUser<enter>

Did you get John Doe for the output? Yes… great! No?… I knew you were going to skip the long version of using the “Set-Variable” cmdlet.

Note: If you use the “Set-Variable” cmdlet and specify the -Name parameter, you do not use the “$” character when defining variables. Most of the time I use ($strComputer = “computerName”) to create variables. Just be conscious of this rule when using the “Set-Variable” cmdlet.

Working with Strings

A [sting] is a “text string” data type. There are many data types that we will be working with in PowerShell:

Type Description
[int] 32-bit signed integer
[long] 64-bit signed integer
[string] Fixed-length string of Unicode characters
[char] A Unicode 16-bit character
[byte] An 8-bit unsigned character
[bool] Boolean True/False value
[decimal] An 128-bit decimal value
[single] Single-precision 32-bit floating point number
[double] Double-precision 64-bit floating point number
[xml] Xml object
[array] An array of values
[hashtable] Hashtable object

Yep, we will be discussing them all at some point…

String Concatenation

Concatenation is the process of joining together two strings. Here is an example:

$strA = “Hello “<enter>
$strB = “World!”<enter>
$strC = $strA += $strB<enter>
$strC<enter>

We used += to join together variables $strA and $strB and store the new “text string” in variable $strC. The output from $strC is Hello World!

Most of the time you will see two strings joined together by using just the “+” operator. Like so; $strC = $strA + $StrB. Both result in the same output.

Aside from joining strings we can also replace words using the -replace parameter.

$strA = “Go east young man!”<enter>
$strB = $strA -replace “east”, “west”<enter>
$strB<enter>

Go west young man!

What the heck is Interpolation?

Quotes are used when working with string data, either double-quotes(” “) or single-quotes(’ ‘). What’s the difference? Glad you asked… It’s called Interpolation. As stated at the beginning of this PowerShell training session, variables are stored for later use. Interpolation occurs when a string variable is enclosed in double-quotes and does not occur when single-quoted. Let me give you an example of what this means:

$strA = “fast”<enter>
Write-Host “Tom drives a $strA car.”<enter>

By double-quoting, the output of the “Write-Host” cmdlet is - Tom drives a fast car. This is interpolation, PowerShell substitutes the value of variable $strA. Let’s see what happens when using single-quotes:

$strA = “fast”<enter>
Write-Host ‘Tom drives a $strA car.’<enter>

Output - Tom drives a $strA car.
PowerShell does not substitute the variable.

Working with Numbers

PowerShell works with a number of data types, for example integers(9) and decimals (9.9). The PowerShell engine can automatically recognize the data type assigned to a variable. For example, it knows that $x = 1 is an integer data type. It also knows that $x = “Hello World!” is a string data type.

Assigning integer and decimal values are simple:

$x = 1<enter>
$y = 1.2<enter>
$x<enter>
$y<enter>

There are those rare occasions when PowerShell may have not assigned the proper data type to a variable, causing havoc with your script. Though it is not required, it is considered good form to assign the data type of a variable. Refer to the data type table presented earlier in the tutorial. Here are some examples:

[string]$strComputer = “MyFileServer01″<enter>
[int]$x = 9<enter>
[decimal]$y = 9.9<enter>

PowerShell Operators

  • = Assigns a value to a variable.
  • + or += Addition.
  • - or -= Subtraction.
  • * or *= Multiplication.
  • / or /= Division.
  • % or %= Modulus (retrieves the remainder of a division operation).

PowerShell follows the rules of math. Equations are read from left-to-right, multiplication and division are preformed then addition and subtraction.

$x = 10 * 2 / 5 * 2 + 5 * 5<enter>
$x<enter>

What answer did you get? Hopefully 33.

What about:

$x = 10 * 2 / 5 * (2 + 5) * 5<enter>
$x<enter>

Parenthesis can be used to alter the order of the mathematical rule. O.k. enough math class.

Note: PowerShell has two additional operators that you will use frequently. Make a mental note of these operators as you will be using them often in your script writing.

  • “++” Increments a value by 1.
  • “–” Decrements a value by 1. -Hard to see, it is minus minus or (- -) without the space.

Examples:

$x = 1<enter>
$x<enter>
1
$x++<enter>
$x<enter>
2
$x++<enter>
$x<enter>
3
$x–<enter>
$x<enter>
2

We will work with more data types when the advanced PowerShell tutorials are launched.
Here are nine exercises to complete. See if you can get through them all without looking at the answers. Answers provided below the exercise:

  1. Create a variable named $strComputer and assign the files server name FSrv01.
  2. Create a variable named $x and assign the number 7.
  3. Create a variable named $y, assign the data type and number 11.
  4. Create a variable named $Pi, assign the data type and number 3.14
  5. Concatenate the following variables, strA = “This is a ” and strB = “text string.”
  6. Using two variables, subtract 5 from 9.
  7. Using two variables, add 5 and 9.
  8. Assign the number 1 to variable $x and increment by 1.
  9. Get the answer for the following equation. 5 * 2 / 10 + 7 / 3 * 2.

Answers:

  1. $strComputer = “FSrv01″
  2. $x = 7
  3. [int]$y = 11
  4. [decimal]$Pi = 3.14
  5. strA + strB -or- strA += strB
  6. $x = 9<enter> $y = 5<enter> $x - $y<enter>
  7. $y + $x<enter>
  8. $x = 1<enter> $x++<enter> $x<enter>
  9. $x = 5 * 2 / 10 + 7 / 3 * 2<enter> $x = 6


PowerShell Arrays

Variables can also store arrays which by definition are an indexed list of values. Each item is assigned a unique index number. The first item in an array is assigned the value of (0), the next item (1), then (2), and so on. One of the more popular uses of an array is to run a script against remote computers. If you’ve looked at the PowerShell scripts in the Microsoft Script Center Repository, notice that a lot of scripts only run on the local computer by using strComputer = “.” variable. “.” means the local computer the script is running on. You could run the script on a remote computer by modifying the code like this strComputer = “RemoteComputerName”. But, what if you want to run the script against multiple computers on your network? Ok… besides using a logon script! In essence a logon script still runs locally and you have limited control over when it runs. The answer is by using an array!

To create an array, we create a variable and assign the array. Arrays are noted by the “@” symbol. Let’s take the discussion above and use an array to connect to multiple remote computers:

$strComputers = @(”Server1″, “Server2″, “Server3″)<enter>

We now have three values stored in the $strComputers variable. Note: Since I am working with string values, I’m quoting. Also each array value is separated by a comma.

How to list the values in the array:

$strComputers<enter>

List the number of items within the array using the count property.

$strComputers.Count<enter>

Now that we know there are three elements within the array, we can list an item by it’s index number. Remember, array index numbers start at 0. List values by their index number:

$strComputers[0]<enter>
$strComputers[1]<enter>
$strComputers[2]<enter>

We can also modify elements in an array. Here I’m modifying an element in an existing array by providing the index number and the new string value. This changes the item Server3 to Server4.

$strComputers[2] = “Server4″<enter>

Verify the element was modified:

$strComputers<enter>

Using the + operator, we can combine arrays:

$x = @(1, 2, 3, 4, 5)<enter>
$y = @(6, 7, 8, 9, 10)<enter>
$z = $x + $y<enter>
$z<enter>

Back to our discussion on using arrays to get information from multiple computers. Here is a typical script taken from the Microsoft Script Repository that enumerates the BIOS information on the (strComputer = “.”) local computer. Note: you don’t have to copy the following script code into a .ps1 (PowerShell) script file to run. Just copy and paste the code into the PowerShell Console; to paste in PowerShell just do a right mouse click. When the code has been copied into the shell, just hit <enter> twice to get the results. Just another cool thing you can do with PowerShell…

$strComputer = “.”

$colItems = get-wmiobject -class Win32_BIOS -namespace root\CIMV2 -comp $strComputer

foreach ($objItem in $colItems) {
write-host “BIOS Characteristics: ” $objItem.BiosCharacteristics
write-host “BIOS Version: ” $objItem.BIOSVersion
write-host “Build Number: ” $objItem.BuildNumber
write-host “Caption: ” $objItem.Caption
write-host “Code Set: ” $objItem.CodeSet
write-host “Current Language: ” $objItem.CurrentLanguage
write-host “Description: ” $objItem.Description
write-host “Identification Code: ” $objItem.IdentificationCode
write-host “Installable Languages: ” $objItem.InstallableLanguages
write-host “Installation Date: ” $objItem.InstallDate
write-host “Language Edition: ” $objItem.LanguageEdition
write-host “List Of Languages: ” $objItem.ListOfLanguages
write-host “Manufacturer: ” $objItem.Manufacturer
write-host “Name: ” $objItem.Name
write-host “Other Target Operating System: ” $objItem.OtherTargetOS
write-host “Primary BIOS: ” $objItem.PrimaryBIOS
write-host “Release Date: ” $objItem.ReleaseDate
write-host “Serial Number: ” $objItem.SerialNumber
write-host “SMBIOS BIOS Version: ” $objItem.SMBIOSBIOSVersion
write-host “SMBIOS Major Version: ” $objItem.SMBIOSMajorVersion
write-host “SMBIOS Minor Version: ” $objItem.SMBIOSMinorVersion
write-host “SMBIOS Present: ” $objItem.SMBIOSPresent
write-host “Software Element ID: ” $objItem.SoftwareElementID
write-host “Software Element State: ” $objItem.SoftwareElementState
write-host “Status: ” $objItem.Status
write-host “Target Operating System: ” $objItem.TargetOperatingSystem
write-host “Version: ” $objItem.Version
write-host
}

Now we want the same information from multiple remote computers. This time you choose which ones. Create an array with two (or more) computers, FYI - you must have local admin rights on each computer to run the script. Use notepad and change the computer names in the array. Copy and paste your new code into PowerShell.

$strComputer = @(”computer1″, “computer2″, “computer3″)

$colItems = get-wmiobject -class Win32_BIOS -namespace root\CIMV2 -comp $strComputer

foreach ($objItem in $colItems) {
write-host “BIOS Characteristics: ” $objItem.BiosCharacteristics
write-host “BIOS Version: ” $objItem.BIOSVersion
write-host “Build Number: ” $objItem.BuildNumber
write-host “Caption: ” $objItem.Caption
write-host “Code Set: ” $objItem.CodeSet
write-host “Current Language: ” $objItem.CurrentLanguage
write-host “Description: ” $objItem.Description
write-host “Identification Code: ” $objItem.IdentificationCode
write-host “Installable Languages: ” $objItem.InstallableLanguages
write-host “Installation Date: ” $objItem.InstallDate
write-host “Language Edition: ” $objItem.LanguageEdition
write-host “List Of Languages: ” $objItem.ListOfLanguages
write-host “Manufacturer: ” $objItem.Manufacturer
write-host “Name: ” $objItem.Name
write-host “Other Target Operating System: ” $objItem.OtherTargetOS
write-host “Primary BIOS: ” $objItem.PrimaryBIOS
write-host “Release Date: ” $objItem.ReleaseDate
write-host “Serial Number: ” $objItem.SerialNumber
write-host “SMBIOS BIOS Version: ” $objItem.SMBIOSBIOSVersion
write-host “SMBIOS Major Version: ” $objItem.SMBIOSMajorVersion
write-host “SMBIOS Minor Version: ” $objItem.SMBIOSMinorVersion
write-host “SMBIOS Present: ” $objItem.SMBIOSPresent
write-host “Software Element ID: ” $objItem.SoftwareElementID
write-host “Software Element State: ” $objItem.SoftwareElementState
write-host “Status: ” $objItem.Status
write-host “Target Operating System: ” $objItem.TargetOperatingSystem
write-host “Version: ” $objItem.Version
write-host
}

For more information on building arrays to enumerate remote computers, here is a very cool article I’ve written: 3 easy steps to get information from remote computers.

Hash Tables

A Hash table is also known as a dictionary. It is an array that allows you to store data in a “key-value” pair association. The “key” and “value” entries can be any data type and length. The elements must be quoted if they contain a space.

Just like an array we designate a hash table with the @ symbol. There are differences, array elements are enclosed in parenthesis () where hash “key-value” pairs are enclosed in curly brackets {}. Hash elements are separated by the semi-colon.

Creating a hash of users associated with their employee number:

$EmpNumbers = @{”John Doe” = 112233; “Dave Davis” = 223344; “Justine Smith” = 334455}<enter>

Verify the hash table was created:

$EmpNumbers<enter>
PowerShell Trianing Hash table

Hast Table

Image 7.1

Looks like a mini-database. How would we find John Doe’s employee number?

$EmpNumbers["John Doe"]<enter>

Add a new employee record:

$EmpNumbers["Rose Jones"] = 445566<enter>

Verify the creation of new “key-value” pair.

$EmpNumbers<enter>

Delete an employee record:

$EmpNumbers.Remove(”Rose Jones”)<enter>

Verify record deletion:

$EmpNumbers<enter>

To Remove all records in the hash table, we use the clear method:

$EmpNumbers.Clear()<enter>

To recap, variables are items of information that we store for later retrieval. Arrays consist of numerous values that can be stored in a variable. Hash tables are associative arrays that use a “key-value” pairs. Since a hash table is like a dictionary, it is much easier to find values within the array (as there is an association created). Standard arrays are indexed starting from the number 0. This makes it difficult to find values, unless you’re a large brain and can tell me what value was assigned to index 245.

Thanks again for your time… In our next PowerShell training session we are going to talk about using Conditional logic. See you in the next tutorial.

Email This Page To A Friend Email This Page To A Friend

Comments

Great–keep them coming.
Clear, concise, examples!

By Lawson Dyer on March 17th, 2008 at 10:03 am

In your answers you have $strComputer = FSrv01 should it not be $strComputer = “FSrv01″. You left of the double-quotes. When do you plan to post the ADSI training session? Keep up the good work.

Ooooppps! Good catch Lawson. I am launching WMI part 3 tutorial tomorrow 3/19. I am looking to start ADSI next week, so look for it.

$x = 5 * 2 / 10 + 7 / 3 * 2 $x = 6

only comes out equal to 6 if you declare the variable as an integer
[int]$x = …

otherwise you get:

$x = 5.66666666666667

I am enjoying this material; thanks for putting it together. In your string concatenation example of $strC = $strA += $strB, you correctly state that the value of $strC is the concatenation of strings $strA and $strB. However, the += operator is not the same as the + operator. The += operator will concatenate the operand on the left side with the operand on the right and store the result in the operand on the left. A += B is shorthand for A = A + B. So in this example, after the operation, $strA also contains the concatenation of $strA and $strB. Similarly, A -= B is shorthand for A = A - B.

How can we create and initialize dynamic multidimensional arrays ?

By poiuytrez on July 25th, 2008 at 10:12 am

I love your tutorial.
Thanks a lot

Additional comment:

You say that
$strC = $strA += $strB
will cause $strC to have the value “Hello World!”

That’s true.

BUT… $strA will now ALSO have the value “Hello World!”

Great tutorial, tho!
What you want is $strC = $strA + $strB.

You don’t have to dim variables in VBscript unless you use the option explicit keywords.

I implement your example of -replace parameter ,in my PS script .As a result , it made my code readable and simple to maintain

I have a problem to get value from Hash:
####################
#Create hash
$App_dll=@{}
#define string
$Hyrarchy=”ABC\def”
$temp=$Hyrarchy.split(’\')
#devide the string
$App=$temp[0].split()
$dll=$temp[1].split()

#Update Hash Table
$App_dll.Add($dll,$App)

$dll
$a=”def”
$b=$App_dll.Get_Item($a)
###################################
The problem is that $b contains nothing

By Jerry Eakle on February 24th, 2009 at 8:24 pm

Variables can contain spaces, however they must be enlcosed in {}.
This is a legal variable name, {a*?,v**} although I would advice no one to ever use it….on purpose.
Sometimes you get data exported to you in a csv and the import gives you a variable name you don’t really want. But if you have to work with and have no other choice…

I’m having a problem w/ the right click code into powershell and hit enter twice part… I’m not sure if my powershell didn’t install correctly or what, but that doesnt work, nor does executing saved scripts, I wonder if you can help me figure out what I’m doing wrong, thanks

After taking a look on another box, it is still a problem so I’m sure I must be doing something wrong, or maybe I need to install something in addition to PowerShell… On the first big block of code I get this error:

Get-WmiObject : A parameter cannt be found that matches parameter name ‘Characteristics:’ . At line:1 cha:26 + $colItems = get-wmiobject <<<< -class “Win32_BIOS” -namespace “root\CIMV2?

Josh,
Nothing wrong with PowerShell. Looks like there is a formatting issue when copying text from code on this page to powershell. For some reason it is not understanding the closed quote. look at the -namespace in the error you are getting “root\CIMV2? -the question mark is the problem. It should read “root\CIMV2″ - I’ve changed the code above until I can work out the issue on the site.

huh, that seemed to work, thanks a lot. BTH this is a great site, I’m a junior studying comp science, and I just started working as a DBA on campus… I’m going to try and do some fun stuff with this and SQL Server’s Report Services

By Jesse Hamrick on March 12th, 2009 at 12:52 pm

Check out this link for working with PowerShell and SQL. http://www.idera.com/Content/Show76.aspx
Free PowerShell scripts for SQL DBAs.

wow, dang good stuff. I had another question, somewhat relating to arrays… more on the .net objects though… Thanks to your tutorials (and msdn I guess I have to give them some credit : /), I was able to make this within ~5-6 hrs of learning what powershell even was:
$date = get-date -uformat “%Y-%m-%d”
Get-WmiObject win32_LogicalDisk|Where-Object {$_.Size -gt 0}|Select-Object Name,Description,FreeSpace,Size|Export-CSV -Path “C:\serverStatusReport\dailyFiles\driveInfo $date.csv”

This works wonderfully, and I can just run an SSIS package on it to import it. Now I want to run it from my VM and collect this file from every SQL server in the building. The hickup I’m running into right now is that while get-wmiobject win32_LogicalDisk works fine, get-wmiobject win32_Logicaldisk -comp XYZ throws an error… what am I doing wrong?

The samples for working with arrays don’t seem to be completely correct?
$strComputers = “comp 1″, “comp 2″ defines an array, but $strComputers = @{”comp 1″ = “Dell”} is defining a hashtable?

Great tutorial to get up to speed in a quick and efficient way! Thanks!

By David Rogers on May 26th, 2009 at 4:43 pm

RE: “Did you get John Doe for the output? Yes… great! No?… I knew you were going to skip the long version of using the “Set-Variable” cmdlet.”

Smarty Pants! ;-)

Hi,
I’ve just started to use the PowerShell and (one of my first todos) it is really easy to create a hash from astring or a file but I hven’t found anywhere to store a hash hopefully that easy (??) into a file.
Can you add this (write hash to a file) to your hash-section, I would appreciate this!
THanks Carl

hello

pls, how i have to to wenth i save or restor variables
thnx

Hi,
About moshe’problem :
You’ve to assigne the data type to variables, like this casting :
[String]$App=$temp[0].split()
[String]$dll=$temp[1].split()

Without this you can’t Update Hash Table
$App_dll.Add($dll,$App)
-> because $dll and $App was System.Array in your first script…

 

Leave a Comment