113
PowerShell Tutorials PowerShell Tutorial for beginners. Windows PowerShell instruction thought-out for those new to PowerShell. In the next few weeks I will be posting a series of PowerShell basics that will provide a good start for a solid foundation. Here is what I have slated: The Windows PowerShell Console - Configuration and Customization. PowerShell Basics - Cmdlets, Parameters, Command Types, Command Information, etc… Output using the PowerShell Format command. Engaging the Windows File System. WMI and .NET primer (real basic) Variables in PowerShell Taking what you have learned and applying it. The initial lessons are concentrated around PowerShell as a Command Shell. The commands and syntaxes you learn will be utilized in script writing. An enormous feature of PowerShell is the ability to build and test code at the command prompt. If you have experience in VBScript you understand. VBScript doesn’t have a command line, you write the script, test it, and make adjustments. With PowerShell you can test functionality within the command line before writing it to your script, very powerful! Windows PowerShell Console PowerShell Tutorial 1: Configuring the PowerShell Console PowerShell is required for tutorials on this site. If PowerShell is not installed on the system, please do so before moving on. A page on this site has been provided to assist in installing PowerShell. It can be found at Categories -> PowerShell Downloads -> Download PowerShell 1.0.

PowerShell Tutorials

  • Upload
    jackbab

  • View
    827

  • Download
    3

Embed Size (px)

Citation preview

Page 1: PowerShell Tutorials

PowerShell Tutorials

PowerShell Tutorial for beginners. Windows PowerShell instruction thought-out for those new to PowerShell. In the next few weeks I will be posting a series of PowerShell basics that will provide a good start for a solid foundation.Here is what I have slated:

The Windows PowerShell Console - Configuration and Customization. PowerShell Basics - Cmdlets, Parameters, Command Types, Command

Information, etc… Output using the PowerShell Format command. Engaging the Windows File System. WMI and .NET primer (real basic) Variables in PowerShell Taking what you have learned and applying it.

The initial lessons are concentrated around PowerShell as a Command Shell.  The commands and syntaxes you learn will be utilized in script writing. An enormous feature of PowerShell is the ability to build and test code at the command prompt. If you have experience in VBScript you understand. VBScript doesn’t have a command line, you write the script, test it, and make adjustments. With PowerShell you can test functionality within the command line before writing it to your script, very powerful!

Windows PowerShell Console

PowerShell Tutorial 1: Configuring the PowerShell Console

PowerShell is required for tutorials on this site. If PowerShell is not installed on the system, please do so before moving on. A page on this site has been provided to assist in installing PowerShell. It can be found at Categories -> PowerShell Downloads -> Download PowerShell 1.0.

This tutorial is an introduction to PowerShell, PowerShell concepts, and exercises in customizing the PowerShell Console.

PowerShell Intro…PowerShell is a new… ok how many times have you read that already? PowerShell is a new command shell from Microsoft and yes it is a command prompt and scripting environment, it can even be both at the same time. But what does PowerShell really mean for a systems administrator? What are the benefits in learning PowerShell? If you manage resources with VBScript you already know the answers. Active Directory domains are becoming larger and more complex. For those administrators that are still

Page 2: PowerShell Tutorials

chained to GUI tools and the Microsoft Management Console, PowerShell will set you free!!!It has become a daunting task to manage resources in large domains, GUI just won't DUI anymore. For example, take the recent DST (Daylight Savings Time) change. Microsoft was slow to respond (in my opinion) but did supply hot fixes for XP and Windows 2003. Windows 2000 was a different story, system admins had to rely on a manual edit using tzedit.exe (unless you had a premier contract). Am I bringing back any nightmares? Here was my nightmare; the boss asked, "How do we know that the DST hot fixes and the manual tzedit actually worked?" Gulp! Thank god I was already working on the answer to that question. I found a KB Article posted on the Microsoft web site listing the new DST registry entries and their locations. So with VBScript I enumerated the registry settings, based on operating system version, and created a report. I found a 25% failure rate after applying hot fixes and tzedit. So, I wrote another script that would edit the registry settings with the proper configuration. Thankfully, all of my Server Systems (300+) sprung ahead to the proper DST settings. Ok, so now you are thinking "why are we talking about VBScript? This is a PowerShell tutorial!!!" My point is, I know a lot of IT workers that had to manually update the registry when the clocks didn't roll forward, message boards and forums were full of postings. What would you rather do, logon to each server and manually fix the problem or run a script to fix the issue for you? PowerShell would have been a great tool for this situation; I was just more familiar with VBScript at the time.I've read and been asked the following, "VBScript is still a viable tool… so why should I learn PowerShell?" I have a couple of simple answers for that:

1. PowerShell was designed for .NET objects; VBScript does not support a method for communicating or interacting with .NET. We will talk more about .NET in later tutorials.

2. Learning PowerShell will further advance your career. Trust me, it will.

This Introduction was not based on what PowerShell is but what PowerShell, as a Shell and a Scripting Language, can do for you. The DST example is only the tip of the iceberg when is comes to the power of scripting languages. What PowerShell "is" you will discover as you continue learning. What's great about PowerShell, you will be able to use it right out of the gate to complete simple tasks. As your knowledge grows you will be able to take on more complex tasks.PowerShell ConceptsPowerShell is object-based not text-basedThis concept will take a little time grasp for dos/cmd.exe and batch script writers. Those using VBScript and other programming languages already understand the concept. The basic difference, traditional command prompt output is text-based while output in PowerShell is not. It looks like text but it is actually an object. Why is this powerful? Because the output of a PowerShell command (the object) can be piped into another command without additional programming. With traditional scripting, if you wanted to use the output of one command in another, additional programming would be required to manipulate the data in a format the second command could understand. What is an object? This should sound familiar to the Windows Administrators out there…

Page 3: PowerShell Tutorials

"Everything in an Active Directory Domain is an object." Servers, Computers, Printers, Shares, Organizational Units, Security Groups, Group Policy Objects, Users, etc… With PowerShell we can interact with these objects to enumerate information (object-properties) and/or create, modify, or delete objects and/or object-properties (object-methods).PowerShell Commands are customizablePowerShell commands are referred to as Cmdlets. With the installation of PowerShell there are over a hundred cmdlets for you to get up close and personal with. The PowerShell team, in their infinite wisdom, created aliases to allow us to use the traditional commands we have become accustomed to (dir, cd, del, copy, etc…). Even the UNIX guys get a break with provided aliases (ls, man, etc…). PowerShell allows you to create your own aliases as well as creating your own cmdlets. Yep, unlike dos/cmd and reskit exe's, PowerShell provides a method to create your own PowerShell cmdlets.PowerShell is a Command line interpreter and a scripting environmentIn a nutshell you have the best of both worlds within PowerShell. DOS was a command line interpreter, enter command get output. Sure you could use batch files, but in reality a batch file just entered the commands for you. VBScript utilizes WSH (Windows Scripting Host); you can't enter VBScript code in a command prompt. With PowerShell not only can you enter commands, you can build script-blocks from the PowerShell command line. You will be doing this in later tutorials. Windows PowerShell ConsoleLet's take a look at the Windows PowerShell Console. Go to Start -> Programs -> Windows PowerShell 1.0 -> Windows PowerShellYou can also launch PowerShell from a command prompt or in start -> run by simply typing powershell

You will notice the command prompt PS U:\>PS signifies that you are running PowerShell, U: is the drive letter of my home directory. Yours may be different.Exercise 1: Customize a shortcut to point to a home directoryAs you have noticed my prompt points to U: Drive. I like to organize my scripts in one location where I can access them quickly. U: is a drive mapping to my home directory on a file server. I've chosen my file server as it is backed up nightly. In this exercise we configure the PowerShell Console to open in a directory called "MyScripts."

Page 4: PowerShell Tutorials

1. Create the following directory - C:\MyScripts.2. Create a PowerShell shortcut on your desktop.3. Right-Click on the shortcut and choose Properties.4. Under the Shortcut tab locate the Start in: text box. Type in the path to the

folder created in step 1. C:\MyScripts5. Click Ok.6. Launch PowerShell from the desktop shortcut.

 PowerShell starts in the directory path we've chosen:

Feel free to choose the directory path of your choice. If your path has a space in it, don't forget to double-quote it. Example: "C:\Program Files\MyScripts." I will be working from the C:\MyScripts directory path throughout the tutorials.Exercise 2: Customizing color and text-sizeRemember the DOS prompt with the blue background and yellow text? Ok, I'm dating myself but at least I didn't say monochrome. I'm going to change the shortcut to those colors.

1. Right-click on the shortcut and choose Properties.2. Choose the Colors tab.3. You will see four radio buttons; Screen text, Screen background, Pop-up

text, and Pop-up background. The Screen buttons are self-explanatory; the Pop-up buttons are for colors used in the History Buffer.

4. Set Screen text to yellow, Screen background to blue.5. Launch PowerShell from the desktop shortcut.

PowerShell runs in the colors we've chosen:

  Next I'm going to make the text larger so I don't have to squint.

1. Close the PowerShell Console by typing exit.2. Right-Click the PowerShell shortcut and choose Properties.3. From the Fonts tab, choose 12 x 16. Click OK.4. Launch PowerShell from the shortcut.

Do you see the following? I mean can you really see it now?

Page 5: PowerShell Tutorials

Take a few minutes and play around with all the options in the shortcut's properties. Customize the shell to your preference. If you want to go back to the default text-size it is 8 x 12. You can also get to properties by clicking on the PowerShell icon in the upper left-hand corner. Just be aware that when you click "OK" you will be prompted to change the settings of the current window or to modify the shortcut.Exercise 3: Editing Features in the PowerShell ConsoleIn the last exercise of this tutorial I want to introduce some editing features. I'm just going to list them and ask that you play around in the console until you are comfortable with how they work.First, enter the following commands at the command prompt (for this exercise, what the code does is not important):get-acl <enter>

get-alias <enter>

get-command <enter>

get-date <enter>

Locate and type the keys below on the keyboard, watch what happens.

Page Up - Jumps to the first command in the history buffer. Page Down - Jumps to the last command in the history buffer. Up Arrow - goes back one command in the history buffer. Down Arrow - goes forward one command in the history buffer. Home - Jumps to the beginning of the command line. End - Jumps to the end of the command line. Ctrl+LeftArrow - goes to the left one word at a time. (In the console type -

PowerShell tutorial lesson 1) Ctrl+RightArrow - goes to the right on word at a time. (In the console type -

PowerShell tutorial lesson 1) Tab - Completes input (in the console type get-c and press tab, press tab

again…). F7 - Shows history buffer (use the up and down arrow keys to navigate the

buffer).

Windows PowerShell Cmdlet

PowerShell Tutorial 2: PowerShell Commands - Cmdlet

The concepts in this tutorial have come from my readings of Bruce Payette's book - Windows PowerShell in Action. Bruce is a founding member of the PowerShell team and is a co-designer of the PowerShell language. His book is highly recommended and has been made available from this site. Who better to learn about PowerShell than from the designer himself!

Page 6: PowerShell Tutorials

There are four categories of PowerShell commands: Cmdlet (Command-Let), PowerShell Functions, PowerShell Scripts, and native Windows commands. Each category will be examined in tutorials on this site. Lesson 2 focuses on the PowerShell cmdlet, so let's get started…cmdlet - naming conventionThere are over a hundred new PowerShell commands to learn, but no need to panic. Unlike most other command-line interfaces, PowerShell commands have been standardized using a "verb-noun" naming convention know as a cmdlet. This standard simplifies the learning curve and provides a better description of what the cmdlet does. To see a list of cmdlets available in PowerShell type the following cmdlet:get-command <enter>

Note: <enter> denotes typing the Enter/Return key on your keyboard.

Image 2.1 The "Name" column lists the cmdlets in the "verb-noun" naming convention.Next, let's list all the commands that use a specific verb. The following command yields all cmdlets that use the verb "Get."get-command -Verb Get <enter>

Image 2.2

Page 7: PowerShell Tutorials

Play around with the -Verb parameter, try finding commands that use the verbs; Add, Clear, New, and Set.Getting commands that use specific nouns is just as easy. Type the following command to see which cmdlets use the noun "Service."get-command -Noun Service <enter>

Image 2.3 Just as it sounds, the verb describes an action and the noun describes the "what" to take the action against. One thing I want to mention before moving forward, the PowerShell command line is not case-sensitive. In PowerShell - "get-service" or "Get-Service" or even "GeT-SerVIce" is the same command.Getting helpIn learning new technologies, it is important to find information quickly and easily. Get-Help cmdlet has been designed for that purpose; this will be the most utilized cmdlet until you become more proficient.Get-Help Examples: Information about Get-Help cmdlet. Includes description, syntax, and remarks.Get-Help

Information about all available help topics.Get-Help *

Information about a specific cmdlet.Get-Help Get-Service

Two other forms of the Get-Help cmdlet exist, the noun "Help" and the "-?" parameter. Help, by itself provides the same info as Get-Help *. Use Help with a cmdlet as follows, Help Get-Service. With the help parameter, Get-Service -?. The Scripting Guys created a graphical Help file which is available on this site. Located in the Categories -> PowerShell Downloads -> PowerShell Graphical Help File. The Graphical Help file is great tool for learning and reference, I recommend downloading it.Using cmdletsIn this section I will be using Service to demonstrate cmdlets. Image 2.3 lists eight cmdlets associated with the noun Service: Get-Service, New-Service, Restart-Service, Set-Service, Start-Service, Stop-Service, and Suspend-Service. Not only will we be running cmdlets from the PowerShell command line, I'm also going to explain it graphically. O.k. that sounds kind of graphic… what I mean is I'm going to describe the equivalent action taken when working in GUI tools. I find this a tremendous help when attempting to understand new concepts.

Page 8: PowerShell Tutorials

What services are on the computer? Type the following cmdlet:get-service <enter>

Image 2.4 You should now have a list of services on the computer as well as their status, similar to the list above. Which GUI tool gives us the same information? The Services MMC (Microsoft Management Console). Launch the Services MMC from Start -> Programs -> Administrative Tools -> Services. If Administrative Tools are hidden from the Programs Menu, you can launch it by typing services.msc from the PowerShell command-line. As stated earlier, one of the PowerShell command categories is "native windows commands." This is how we are able to launch services.msc from the PowerShell command-line.

Image 2.5 Exercise 1: Stopping and Starting a Service.For this exercise I will be using both the Stop-Service and Start-Service cmdlets. To demonstrate, I have chosen the "Computer Browser" service for this example. The

Page 9: PowerShell Tutorials

current status of the Computer Browser service is "Started" and the "Status Type" is "Automatic." For this exercise it is important that you choose a service that has a status type of either automatic or manual. If you choose a service with a status type of disabled, this exercise will not work.The following syntax stops a service: Stop-Service [-name] or Stop-Service [-displayName]. This is not the complete syntax for the Stop-Service cmdlet. If you want to see the full syntax, use the Get-Help cmdlet as discussed earlier. To begin, let's show the status of the Browser Service. Then Stop it using the Stop-Service cmdlet. Lastly check the status. Type the following cmdlets:Get-Service -name Browser <enter>Stop-Service -name Browser <enter>Get-Service -name Browser <enter>

Image 2.6 Note: When you run the Stop-Service cmdlet there is no indication that the service has actually stopped. This is why I ran the Get-Service command to verify the status changed to "Stopped." We should see the same change in the Services.msc GUI. In the GUI a Status of "Blank" means "Stopped."

Page 10: PowerShell Tutorials

Image 2.7 The following syntax will start a service: Start-Service [-name] or Start-Service [-displayName]. Look familiar? Again, let's check the status, start the service, and verify the status has changed.Get-Service -name Browser <enter>Start-Service -name Browser <enter>Get-Service -name Browser <enter>

Image 2.8 Check the GUI, the status of Browser should be "Started" (make sure to refresh the view).This exercise should give you an indication of the benefits of using PowerShell. With just a couple of cmdlets we were able to stop and start a service. Traditionally, an Administrator would launch the GUI, select the service, and then either stop or start it. Doesn't seem like a big deal until you are asked to stop a service on multiple computers. Through PowerShell Scripting you will be able to start, stop, and change status types of a service on multiple computers without much effort. Write a script, run-it, and then kick you feet up on the desk.

Page 11: PowerShell Tutorials

This tutorial has introduced the PowerShell naming convention, cmdlets, getting help, and an example of using the Service cmdlet. As stated before, there are over a hundred cmdlets in PowerShell. This should be enough to keep you busy for awhile. See you in the next tutorial where we will be covering PowerShell Aliases.

Windows PowerShell Aliases

PowerShell Tutorial 3: PowerShell AliasesAliasing in PowerShell allows for the use of commands we become accustomed to. Windows users can utilize commands like dir, move, type, cls, etc… PowerShell also provides a set of aliases for Linux; ls, pwd, mv, man, cat, etc… PowerShell Aliases are provided for the purpose of allowing new users the ability to quickly interact with the shell. An alias is an alternative name assigned to a cmdlet. For example, “dir” is an alias for “Get-ChildItem.” This tutorial presents two types of aliases:

Built-in Aliases - Predefined alternative names for Windows, Unix, and PowerShell cmdlets.

User-defined Aliases - Custom alternative names created by the user.

Launch your PowerShell Console and let’s get started.Built-In PowerShell AliasesAs previously described, built-in aliases are predefined. Use the following cmdlet to get a list of PowerShell Aliases:Get-Alias <enter>

Image 3.1While browsing through the list, notice that there are multiple Aliases for the “Get-ChildItem” cmdlet. Windows “dir” command, Unix “ls” command, and a PowerShell alias “gci” command. No matter which alias you have chosen to use, typing any one of the aliases will result in the running of the “Get-ChildItem” cmdlet. Let’s test this out, type the following:dir <enter>ls <enter>gci <enter>Get-ChildItem <enter>

Page 12: PowerShell Tutorials

Image 3.2Listed in Image 3.2, we can verify that each command resulted in the same output. In essence, we just ran “Get-ChildItem” four times. There is really not much more to built-in aliases. They exist to assist you while working in the shell, until you become more familiar with the cmdlets. User-Defined aliases require a little more attention.User-Defined PowerShell AliasesSet-Alias alias command - Simple syntax, not much to it. Let’s say I want to create a User-Defined alias for the “Get-Service” cmdlet:Set-Alias gs Get-Service <enter>

Test your new Alias:gs <enter>

Page 13: PowerShell Tutorials

Image 3.3That was easy, so why does a user-defined alias need a little more attention? User-defined aliases only last while the PowerShell session is active. As soon a you quit the session, your alias is gone forever. Close your PowerShell session and re-launch PowerShell. Attempt to use the “gs” alias, you will receive the following error: “The term ‘gs’ is not recognized as a cmdlet, function, operable program, or script file. Verify the term and try again.” O.k. - Recognize the term by creating the alias again:Set-Alias gs Get-Service

So, we have created a User-defined PowerShell alias and don’t want to lose it when we quit the session, what do we do? There are two options to explore:

Import/Export the PowerShell alias. User-defined Aliases using PowerShell Profiles.

Import/Export User-Defined PowerShell AliasesThe purpose of Importing and Exporting is to make user-defined aliases available to multiple machines. Say you wrote a script that uses custom aliases. If you attempted to run your script on another machine, it would fail. The remote PowerShell session is not aware of the custom aliases you have created. Unless, you export the aliases to a text file in which the remote computer could import.Go ahead and export the “gs” alias using the “Export-Alias” cmdlet:Export-Alias -Path Aliases.txt <enter>

Since I am running from my home directory “C:\MyScripts” the Aliases.txt file will be created there. Use the “-Path” parameter to set the desired location. One option is to save the export file to a UNC path so that it is available from a network share. Open “Aliases.txt” in notepad:PS C:\MyScripts>notepad Aliases.txt <enter>

Do you notice anything odd about the text file?

Page 14: PowerShell Tutorials

Export-Alias

Image 3.4Not only did it export the “gs” user-defined alias we created, it exported ALL PowerShell aliases. Is this an issue? If we attempt to import the Aliases.txt file, PowerShell will report an error for each alias that already exists. Import the Aliases.txt file using the “Import-Alias” cmdlet:Import-Alias -Path Aliases.txt <enter>

Page 15: PowerShell Tutorials

Image 3.5That looks ugly… but, if the alias does not exist, it will get imported. There is actually a better way to do this. The example above was shown to make you aware of a potential problem when you are importing and exporting aliases. By using the -Name parameter, you can export only the aliases you choose. So with our “gs” alias let’s attempt the following:Export-Alias -Path Alias.txt -Name gs <enter>notepad Alias.txt <enter>

Image 3.6That looks much better… What do you think would happen if you attempted to import this file? If your PowerShell Session is still active, you should get the import error because the “gs” alias still exists in the current session. Exit your PowerShell session and re-launch PowerShell.Let’s import the Alias.txt file:Import-Alias -Path Alias.txt <enter>gs <enter>

Page 16: PowerShell Tutorials

Image 3.7No error reported when importing the Alias.txt file and entering the “gs” alias provides us with the output expected.Importing and Exporting allows for the use of user-defined aliases on local and multiple systems. What if you just wanted to use custom aliases on your local system and don’t want to be burdened with importing a file each time you launch PowerShell? PowerShell profiles allow you to customize the PowerShell environment at launch time. The last section of this tutorial introduces the PowerShell profile. We are only going to discuss profiles as it pertains to user-defined aliases. With Profiles, there are many options to customize your PowerShell environment, which will be covered in this series.User-Defined Aliases using PowerShell ProfilesWhat is a PowerShell Profile? In simplest terms, a profile is a script that runs at session startup. The location of the Profile is stored in the $Profile variable, which by default is “My Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1″To verify the location of your profile type:$Profile <enter>

Image 3.8In image 3.8 you can see the path to my profile, which happens to be were “My Documents” are stored. As already mentioned, the profile is a script which is denoted by the “.ps1″ extension. All PowerShell scripts are identified by this extension. Since the profile is a PowerShell script we will need to edit it. You can use any PowerShell editor, in this tutorial I will be using Notepad. Before editing the file we need to check the PowerShell execution policy.When PowerShell is first installed the default execution policy is “Restricted.” This means PowerShell will not run scripts or configuration files. Here is a list of policy levels:

Restricted - We know what this means. AllSigned - All scripts and configuration files must be signed by a trusted

publisher. RemoteSigned - All scripts and configuration files downloaded from the

Internet must be signed by a trusted publisher.

Page 17: PowerShell Tutorials

Unrestricted - All scripts and configuration files will run. Scripts downloaded from the Internet will prompt for permission before running.

Use the “Get-ExecutionPolicy” cmdlet to verify policy level:Get-ExecutionPolicy <enter>

What is your policy set at? By definition, since the profile is a script file, the execution policy should be set to anything other than “Restricted.” For this exercise you will set your policy to “Unrestricted.” Here is how to set that policy:Set-ExecutionPolicy Unrestricted <enter>

Now that the policy is set to run scripts, let’s create a profile by following the steps below:Step 1. Verify existence of a profile. test-path $Profile <enter>

If the result = False. No profile exists (continue to step2).If the result = True. Profile exists (skip steps 2 & 3). Unless you want to create a new profile, which will delete the current profile.Step 2. Create a new profile.New-Item -Path $Profile -ItemType file -Force <enter>

Step 3. Verify new profile was created.Repeat step 1. Result should equal “True.”Let’s open our new profile in notepad:notepad $Profile <enter>

Image 3.9Isn’t that great! We have a blank page! The important thing to note: We have a script file called “Microsoft.PowerShell_profile.ps1″This script file will be called using the $Profile variable each time a PowerShell session is launched. What goes into the script file will be up to you, how you decide to configure your PowerShell environment. For now, let’s have our profile load our custom user-defined PowerShell alias. Edit and Save the profile as shown below:

Page 18: PowerShell Tutorials

Image 3.10After you have saved the profile, close notepad, and exit the PowerShell session.Launch a new PowerShell session and verify that your custom alias is functional:gs <enter>

Viola! your profile has loaded successfully and your alias is working. Use “Get-Alias” cmdlet to verify the existence of your new alias:Get-Alias <enter>

-or- a more refined search:Get-Alias -Name gs <enter>

PowerShell Parameters, Objects, and Formatting

PowerShell Tutorial 4: Using Cmdlet OptionsWelcome back! Continuing with your PowerShell Training, the goal of this tutorial is to introduce PowerShell parameters, objects, and formatting output. I’m excited about this tutorial as we begin to define and discover the power of working with objects in PowerShell. By the end of this PowerShell training session you should have a good understanding of what an object is, how we gather information, and how changes are made in the environment.Launch PowerShell and let’s get started…Common Parameters (options for cmdlets)As mentioned before, the standardization of the PowerShell syntax has reduced the learning curve. Cmdlets follow a standard “Verb-Noun” naming convention and also use common parameters. Note: not all cmdlets use these parameters. However, because the PowerShell engine interprets the parameter (not the cmdlet), each common parameter is enacted in the same fashion. Below is a list of the Common Parameters:

-whatif - Cmdlet is not actually executed, provides information about “what would happen” if executed.

-confirm - Prompt user before executing cmdlet. -Verbose - Provides more detail. -debug - Provides debugging information. -ErrorAction - Instructs cmdlet to perform an action when errors occur.

Such as: continue, stop, silently continue, and inquire.

Page 19: PowerShell Tutorials

-ErrorVariable - Use a specific variable to hold error information. This is in addition to the standard $error variable.

-OutVariable - Variable used to hold output information. -OutBuffer - Hold a certain number of objects before calling the next

cmdlet in the pipeline.

To view common and other parameters available to the “Set-ExecutionPolicy” cmdlet, type the following at the command prompt:Set-ExecutionPolicy -<tab>

You can cycle through available parameters, for a cmdlet, by continually pressing the “tab” key. Make sure you are using the dash “-” before pressing tab. Note: not only will you see common parameters but, other parameters that are available as well. Use the “Get-Help” cmdlet for information on parameters available to a cmdlet. Continuing to use the “Set-ExectutionPolicy” cmdlet, let’s get-help:Get-Help Set-ExecutionPolicy -Full<enter>

In the “Parameters” section, which provides information on parameters available to the cmdlet, there is a list of the common parameters the cmdlet supports.Examples:1. In this example, let’s use the -whatif parameter to see “what would happen” if we used the “Set-ExecutionPolicy” cmdlet:Set-ExecutionPolicy Unrestricted -whatif<enter>

You are presented with the following: Performing operation “Set-ExecutionPolicy” on Target “Unrestricted”.This is really cool… before you commit any changes you can verify that the cmdlet is going to do what’s expected. Would have been great if “Format C:” had a -whatif parameter.2. Using the same cmdlet, choose the -confirm parameter to prompt before executing:Set-ExecutionPolicy Unrestricted -confirm<enter>

Are you sure you want to perform this action?

[Y] Yes (Default is “Y”) [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help

Note: Suspend? This option is very useful. Let’s say you are not sure you want to execute the cmdlet because you are not sure what the “ExecutionPolicy” is set to. You can verify the “ExecutionPolicy” before committing the change:Set-ExecutionPolicy Unrestricted -confirm<enter> Are you sure you want…S<enter> (places the prompt in suspend mode as denoted by “>>”).

Page 20: PowerShell Tutorials

>>Get-ExecutionPolicy<enter>Resricted (or whatever the policy is set to).>>exit<enter> (Typing “exit” leaves suspend mode and returns to the original command)Are you sure you want…Y<enter> (Confirms “Yes” and sets the ExecutionPolicy to “Unrestricted”).

We’ve covered a few examples of what you can do with parameters. Since you know how to “Get-Help” for a cmdlet, it’s easy to discover which parameters are available to any cmdlet. Do some exploring and experimentation before moving on to the “Objects” section.Introduction to ObjectsAs discussed in an earlier PowerShell tutorial, PowerShell is object-based not text-based. Since we are working with objects, more information exists than what’s presented (by default) on the command line. That information may not be initially visible; by using PowerShell cmdlets, parameters, and script blocks we can interact with an object to provide us with the information we require.What is an Object?An “Object” is something we can gather information from and/or perform an action upon. An object, in PowerShell, consists of properties (information we can gather) and methods (actions we can perform).I don’t remember where I herd the following explanation but it’s one that sticks with me. As an example, let’s look at a “light bulb.” The object should be obvious, it’s a light bulb. The properties of a light bulb could be color, wattage, and type (florescent, incandescent, or halogen). Methods are the actions we can perform on the object such as; turn on the light bulb and turn off the light bulb. Pretty simple right! Let’s look at an object’s properties and methods.Ingrain this cmdlet in you head, you will use it constantly: “Get-Member.” This cmdlet is used to examine what properties and methods are available to an object.Example 1. Properties and Methods of the “Get-Service” cmdlet.Type the following to view the properties and methods of the “Get-Service” cmdlet. In this example, the output of “Get-Service” (object) is piped into the “Get-Member” cmdlet.Get-Service | Get-Member<enter>

Page 21: PowerShell Tutorials

Get-Member Results

Image 4.1You should see something similar to Image 4.1. We have identified which properties and methods are available in the “Get-Service” cmdlet. At this point in your PowerShell training if you are not familiar with what’s in the definition column, you are looking at “Data Types.” For example, the “CanStop” property returns a Boolen “Type.” My guess is that the value would either be “True” or “False.” Don’t be concerned with this right now, we will be covering “Types” in another PowerShell tutorial. Just make a mental note that the “Get-Member” cmdlet also returns “data types.”

Page 22: PowerShell Tutorials

Example 2. Getting Properties of the “Get-Service” cmdlet.In this example we refine our search to display only properties by using the -MemberType parameter.Get-Service | Get-Member -MemberType Property<enter>

Example 3. Getting Methods of the “Get-Service” cmdlet.Get-Service | Get-Member -MemberType Method<enter>

For a systems administrator, objects are the “Holy Grail” in managing your environment. Why? Because everything in Windows PowerShell is an object. Let me go off the page here for a second to explain. Since we connect to objects and gather information (properties), we are able to compile a report from practically any request our boss throws at us. If the boss requests that a change (method) is made, we are able to make those changes to one or more objects in the environment.Here’s an example: Overnight, someone has placed a large number of files on the file server that has taken up 50% of the remaining free space. I know, unrealistic right?!? Just follow me on this one. The boss wants a report of all files that were created in the last day. Your answer… “No Problem.”Get-ChildItem -Path C:\ -Recurse | Where-Object {$_.LastWriteTime -gt “08/25/2007″}<enter>

Let’s dissect what the command is doing:

1. We call the “Get-ChildItem” cmdlet because we want to enumerate the file system.

2. -Path parameter points to the root of C:\ drive as the starting point. The -Recurse parameter means we want all subdirectories and files enumerated.

3. The object returned from the “Get-ChildItem” cmdlet is piped into a script block.

4. Where-Object is a looping statement which finds each object that matches the criteria we are looking for.

What I would like you to notice, what is “LastWriteTime”? Type the following command:Get-ChildItem | Get-Member<enter>

Do you see a property called “LastWriteTime”? We told the command to find each object with the “LastWriteTime” property that has a value greater than 08/25/2007. “-gt” is an operator that means greater than, we talk more about operators in a later tutorial. I mentioned “Types” before as well, the Definition column states that the “LastWriteTime” property is a “System.DateTime” Type. This means it returns values of this type, which is why we used the “DateTime” type “08/25/2007.” Again, we will discuss “Types” in a later PowerShell tutorial.Did the method “Turn light bulb On” work? I’m hoping that this discussion on objects is starting to paint the big picture for you. Can you think of what type of properties and methods are associated with user objects in Active Directory? If the boss asks for a report of all disabled users; at this point you should recognize that “user” is an object,

Page 23: PowerShell Tutorials

more than likely it has a property which returns the status of the account, and a method to either enable or disable it. How about properties and methods associated with computers, printers, and security groups. We are going to get into how we can connect to these objects and enumerate/modify them when we discuss WMI, COM objects, and .NET. But for now, the boss wants us to format the report we gave him in the earlier example.Formatting outputWhen we execute a cmdlet we are relying on PowerShell to display results. The “Format-” cmdlets allow us to choose which format to display results in. To get a list of formatting options, type the following command:Get-Command Format-*<enter>

Format-CustomFormat-ListFormat-TableFormat-WideFormat-Table“Format-Table” cmdlet displays data in rows and columns, similar to what you would see in an Excel spreadsheet. By default, PowerShell attempts to format the view, but doesn’t always display the best results. For example let’s format the output of the “Get-ChildItem” cmdlet for the “C:\Windows” directory.Get-ChildItem C:\Windows | Format-Table<enter>

I like the table format, but there seems to be too much white space (spaces) between the columns for my taste. Fortunately, there is a parameter -AutoSize to assist us with white space issues.Get-ChildItem C:\Windows | Format-Table -AutoSize<enter>

O.k. maybe that wasn’t what you were looking for either. As shown from a previous example, use the <tab> key to cycle through the available parameters for the “Format-table” cmdlet. Expierment with each available parameters to see how format is manipulated.Format-List“Format-List” cmdlet displays data in… of course, a list. For example:Get-ChildItem C:\Windows | Format-List<enter>

By default, we get the following properties: Name, CreationTime, LastWriteTime, and LastAccessTime. The boss looks at the list and requests the full path to the files. Use the -Property parameter to list the “FullName” property. Reminder: use “Get-Member” cmdlet to list the available properties:Get-ChildItem C:\Windows | Format-List -Property FullName<enter>

If your boss is like mine, I usually hear something like… “that’s great, but now I want the full path to all files and subdirectories, creation date, and last time a file was modified.” Your answer… “No Problem!” To enumerate multiple properties, just separate each property with a comma (,) as shown in this example:Get-ChildItem C:\Windows -Recurse | Format-List -Property FullName,CreationTime,LastWriteTime<enter>

Page 24: PowerShell Tutorials

Note: You can also use the -Property parameter with the “Format-Table” cmdlet to build tables, with each property as a header.Format-Wide“Format-Wide” cmdlet compresses results of a list, to fit the screen:Get-ChildItem C: | Format-Wide<enter>

The results are in list format sorted by column, similar to the old “dir /D” command. You can customize the number of columns using the -Column number parameter:Get-ChildItem C: | Format-Wide -Column 3<enter>

Group-ObjectThe “Group-Object” cmdlet allows us to format output information based on groups. For example, there is a property call “Company” for the object returned by the “Get-Process” cmdlet. Let’s assign the “Company” property to a group:Get-Process | Group-Object Company<enter>

The output groups the information as follows:

Name - Name provided by the Company property of the Get-Process object.

Count - The number of process running from each Company. Group - A truncated list of the processes running.

Here is another example of how to use the “Group-Object” cmdlet. You want to discover which Event IDs are present in the system log:Get-EventLog System | Group-Object eventid<enter>

Note: The Name column is the Event ID, even though it’s not labeled as such. By default, “Group-Object” places the property you specify in the “Name” column.Sort-ObjectFrom the example above we are presented with a “Count” column. This indicates the number of occurrences per each Event ID. Just as it sounds, the “Sort-Object” cmdlet provides a mechanism to sort results. In this example, I’m going to further build on the command above to sort from most occurrences to least:Get-EventLog System | Group-Object eventid | Sort-Object Count -descending<enter>

The results are now sorted from most to least number of occurrences. Couple of things to notice here:

I sorted on the “Count” column. You could also sort by “Name” or any column you choose.

As shown above you can pipe results from one cmdlet to another and then another, etc…

Convertto-HTMLI love this cmdlet. It’s not the best html conversion, sometimes the output looks great, sometimes not. It’s just fast and I don’t have to write any code to convert results, like I did in VBScript. Let’s send the results of “Get-Process” to html.

Page 25: PowerShell Tutorials

Get-Process | ConvertTo-html<enter>

Well, the cmdlet preformed the conversion but I want the result saved to an html file. I’m going to use the “Out-File” cmdlet to redirect the results into a file. This is similar to using the redirect symbol “>” in the old dos command shell.Get-Process | ConvertTo-html | out-file “Processes.html”<enter>

To open the .html file use the “Invoke-Item” cmdlet. This is equivalent to clicking on a file where the file type determines which application is launched.Invoke-Item Processes.html<enter>

The default browser is launched presenting the results saved in the html file. Like I said, doesn’t always look great… But it is fast and the html code can be edited (to look pretty) if desired.Export-CSVThis is another formatting cmdlet that you are going to love. It takes results and converts it to a csv file. In the following examples we are going to Export the processes and open the file in a spreadsheet. You must have Excel or some other type of spreadsheet installed on the system.1. Export results to a .csv file”Get-Process | Export-CSV Processes.csv<enter>

2. Open the spreadsheet:Invoke-Item Processes.csv<enter>

Page 26: PowerShell Tutorials

Process CSV

Image 4.2As shown, you can use the “Export-CSV” cmdlet to quickly document and/or create reports. Much more simple that what was required to create the same report in VBScript.Alright, we got through PowerShell Parameters, Objects, and Formatting. We just hit the tip of the iceberg, we will continue utilizing these cmdlet options as we work in later PowerShell tutorials. Obviously, there are more cmdlet options and parameters we have not covered. PowerShell provides the tools (Get-Help and Get-Member) to explore and learn, so snoop around and get your feet wet.

Page 27: PowerShell Tutorials

Hope I was able to shed some light on the advantage objects provide over traditional shell “text string” output. As Objects are the heart of PowerShell and PowerShell scripting, we will be working in depth with objects as we continue our PowerShell training. If you have any comments or questions please use the comment section bellow. See you in the next PowerShell tutorial…

PowerShell Providers

PowerShell Tutorial 5: Windows PowerShell ProvidersPowerShell Providers are .NET programs that allow us to work with data stores as if they were mounted drives. This simplifies accessing external data outside the PowerShell environment. For example, we can access the registry as if it were a file system. This translates to being able to use the same cmdlets as working with files and folders, which are shown in the table below.Cmdlet Alias Cmd Commands DescritptionGet-Location gl pwd Current Directory.Set-Location sl cd, chdir Change current directory.Copy-Item cpi copy Copy Files.Remove-Item ri del Removes a File or directory.Move-Item mi move Move a file.Rename-Item rni rn Rename a file.

New-Item ni n/aCreates a new empty file or folder.

Clear-Item cli n/a Clears the contents of a file.Set-Item si n/a Set the contents of a file.Mkdir n/a md Creates a new directory.

Get-Content gc typeSends contents of a file to the output stream.

Set-Content sc n/a Set the contents of a file.Take a look at the “about file” for more information:Get-Content $PSHOME\about_Provider.help.txt<enter>

SHORT DESCRIPTIONWindows PowerShell providers provide access to data and components thatwould not otherwise be easily accessible at the command line. The datais presented in a consistent format that resembles a file system drive.LONG DESCRIPTIONWindows PowerShell providers are .NET programs that make the data in aspecialized data store available in Windows PowerShell so that you caneasily view and manage it.The data that a provider exposes appears in a drive, much like a hard drive.You can use any of the built-in cmdlets that the provider supports to manage

Page 28: PowerShell Tutorials

the data in the provider drive, in addition to custom cmdlets that aredesigned especially for the data.The providers can also add “dynamic parameters” to the built-in cmdlets.These are parameters that are available only when using the cmdlet with theprovider data.A Provider is also called a “snap-in” which is a dynamic link library (.dll) built into PowerShell. A library is code that instructs PowerShell to preform an action when we execute a command. What this means is that we no longer have to write code, as we did in VBScript, to connect to the registry. The code is provided for us, simplifying our efforts. New and Custom Providers can be written, but this goes beyond the scope of this tutorial. The PowerShell Software Developers Kit provides documents should you wish to build your own Providers.List Providers available in PowerShellUsing the “Get-PSProvider” cmdlet, we obtain a list of available PowerShell Providers:Get-PSProvider<enter>

PowerShell Providers

Image 5.0Here is the list of the PoweShell Providers available:

Alias Environment FileSystem Function Registry Variable Certificate

PowerShell Drive “PSDrive”We connect to PowerShell Providers by mounting the Providers PowerShell Drive(PSDrive). Most Providers have only one PSDrive, the exceptions are the FileSystem Provider(depends on the number of drives on the system) and the Registry Provider(HKLM and HKCU). Here is how to get a list of the available PowerShell Drives:Get-PSDrive<enter>

Page 29: PowerShell Tutorials

PS Drives

Image 5.1The “Name” column reveals the PSDrives available on the system. We connect to each Provider using the PSDrive appended with a colon (:). Note: The example in image 5.1 shows the PSDrives without the (:) so you have to remember to use it when mounting a PSDrive.Let’s use this PowerShell training session to explore each of these providers.The PowerShell Alias ProviderWe discussed what an Alias “is” in PowerShell tutorial 3. The Alias Provider enables access to all the aliases in PowerShell. To mount a PSDrive we use the “Set-Location” cmdlet. In this example, we want to mount the “Alias:” PSDrive. Don’t Forget the colon(:).Set-Location Alias:<enter>

Set Alias Drive

Image 5.2As shown in image 5.2, we are now connected to the “Alias:” PSDrive. Just a quick note, PSDrives are only available in the PowerShell environment. You would not able to access the “Alias:” drive from a legacy windows command shell.Now that we are mapped to the Alias: PSDrive we can use the same cmdlets as working with files and folders.Eample 1. View a list of all aliases.Get-ChildItem<enter>

Page 30: PowerShell Tutorials

All Aliases

Image 5.2Example 2. List the properties and methods.Get-ChildItem | Get-Member<enter>

Properties and Methods

Image 5.3Example 3. Use the -Name parameter to list all Aliases that start with the letter “R”. PowerShell supports the use of wild cards(*) to filter the results.Get-ChildItem -Name R*<enter>

Page 31: PowerShell Tutorials

Name Parameter

Image 5.4Example 4. Building on example 3; instead of using a parameter to filter results, let’s filter using the “name” property of the Alias object.Get-ChildItem | Where-Object {$_.name -like “R*”}<enter>

Where-Object Filter

Image 5.5We have worked a lot with aliases in a previous tutorial, so I’m going to move along to the next Provider. Feel free to use the commands listed in the table (above) and experiment with the Alias Provider.The PowerShell Environment ProviderYou may already be familiar with what the Environment Providers is, it is equivalent to running the “set” command in a windows CMD command shell. It provides a listing of all the environment variable defined on the system. Graphically, you can view the environment variables by going to System Properties -> Advanced Tab -> Click the “Environment Variables” button.

Page 32: PowerShell Tutorials

ENV Variables

Image 5.6Example 1. List Environment Variables

1. Get list of available PowerShell Providers.

Get-PSDrive<enter>

2. Map PSDrive to Environment Provider.

Set-Location env:<enter>

3. Get listing of Environment Variables.

Get-ChildItem<enter>

Page 33: PowerShell Tutorials

List Variables

Image 5.7Example 2. Obtain the value of an Environment Variable

1. Output the value of the “OS” variable.

Get-ChildItem OS<enter>

2. Output all properties for the “OS” variable.

Get-ChildItem OS | Format-List *<enter>

Example 3. Create a new Environment Variable

1. Create a new variable using the “New-Item” cmdlet. Let’s call the new variable “MyVariable” and give it a value of “This is my new variable.” The Path argument will be a dot (.) meaning current location, which would be “env:”

Page 34: PowerShell Tutorials

New-Item -Path . -Name MyVariable -Value “This is my new variable”<enter>

Create Variable

Image 5.8Use “Get-ChildItem” cmdlet to verify that the new variable exists.Example 4. Renaming the Environment Variable

1. Let’s rename the “MyVariable” variable to “MyRenVar.”

Rename-Item -Path env:MyVariable -NewName MyRenVar<enter>

2. Now use the “Get-ChildItem” cmdlet to verify the change.

Get-ChildItem<enter>

Example 5. Removing the Environment Variable

1. To remove the “MyRenVar” variable we us the “Remove-Item” cmdlet.

Remove-Item MyRenVar<enter>

2. Use “Get-ChildItem” to verify the variable has been removed.

Get-ChildItem<enter>

PowerShell File System ProviderBy default, the File System Provider is accessed when PowerShell is launched. The File System Provider allows you to create, retrieve, and remove files and folders. Also, the File System Provider allow you to modify files by either appending or overwritting data. This section of the PowerShell Providers tutorial explains how to do this.Example 1. Listing Files and Directories

1. Connect to the File System Provider. Close and re-launch PowerShell -or- connect to the File System Provider using the “Set-Location” cmdlet. Use the backslash (\) character to connect to the root of C: Drive

Page 35: PowerShell Tutorials

Set-Location C:\<enter>

2. List Files and Directories under the root of C: Drive.

Get-ChildItem<enter>

3. List Files and Directories including sub-direcories.

Get-ChildItem -Recurse<enter>

If your file system is large, the command in step 3 may take awhile. Use “Ctrl + C” to stop processing commands in PowerShell, just like you did in CMD command shell.What is the “Mode” column? 5 bits of information you need to know.

First entry is either “d” (indicates item is a directory) or “-” (indicates item is a file).

The last 4 entries present the properties of a File and/or Directory (a r h s). “a” = archive bit is set, “r” = read only, “h” = hidden, and “s” = system. A “-” in any of these entries means the bit is not set.

Mode

Image 5.9Note: By default, “Get-ChildItem” cmdlet or an Alias does not show hidden files and Directories. To show hidden files use the “-force” parameter.Get-ChildItem -Force<enter>

As stated earlier in this PowerShell tutorial, Providers allow the use of the same cmdlets. Here is a second look at the cmdlet table, so that you don’t have to scroll back to the top.Cmdlet Alias Cmd Commands DescritptionGet-Location gl pwd Current Directory.Set-Location sl cd, chdir Change current directory.Copy-Item cpi copy Copy Files.Remove-Item ri del Removes a File or directory.

Page 36: PowerShell Tutorials

Move-Item mi move Move a file.Rename-Item rni rn Rename a file.

New-Item ni n/aCreates a new empty file or folder.

Clear-Item cli n/a Clears the contents of a file.Set-Item si n/a Set the contents of a file.Mkdir n/a md Creates a new directory.

Get-Content gc typeSends contents of a file to the output stream.

Set-Content sc n/a Set the contents of a file.Example 2. Using “Get-Location” CmdletUse “Get-Location” to show current directory.Get-Location<enter>

Using Alias and CMD Command.gl<enter>

pwd<enter>

Example 3. Creating files and DirectoriesUse “New-Item” cmdlet to create a New Directory.New-Item -Path C:\NewFolder -Type Directory<enter>

A cool thing about PoweShell, it will assist you when you leave out required information. For example, let’s say your creating the directory in the example above but you forget the -Type paramter.New-Item -Path C:\NewFolder<enter>PowerShell will prompt you for the missing parameter…Type:Continuing with the “New-Item” cmdlet, let’s create a file in our new directory.New-Item -Path C:\NewFolder\NewFile.txt -Type File<enter>

Example 4. Move NewFile to the root of “C:\” using “Move-Item” cmdletMove-Item -Path C:\NewFolder\NewFile.txt C:\<enter>

Verify file moved.Get-ChildItem N*<enter>

Example 5. Renaming Files and DirectoriesLet’s rename the NewFile.txt to RenFile.txt.Rename-Item -Path C:\NewFile.txt RenFile.txt<enter>

Verify the file has been renamed.Get-ChildItem R*<enter>

Rename Directroy NewFolder to RenFolder.Rename-Item -Path C:\NewFolder RenFolder<enter>

Page 37: PowerShell Tutorials

Again, verify the change.Get-ChildItem R*<enter>

Example 6. Removing Files and Directoriesin our last example of this PowerShell training section, let’s remove the RenFolder and RenFile.txt. Just for fun, let’s add the -confirm parameter so that PowerShell prompts us to confirm the action.Remove-Item -Path C:\RenFile.txt -Confirm<enter>

Press “Y” to confirm the deletion of the file and verify the files has been removed.Get-ChildItem R*<enter>

You should still see the RenFolder but the RenFile is no longer present. Now remove the directory.Remove-Item -Path C:\RenFolder -Confirm<enter>

Again, press “Y” to confirm and verify Directory has been removed.Get-ChildItem R*<enter>

There are other cmdlets such as “Clear-Item” and “Set-Item” that enable you to work with data within files. Use “Get-Help” on these cmdlets to read about how to use these cmdlets in the PowerShell FileSystem Provider. I personally like to use “Get-Content” to output a files contents to the screen and “Set-Content” to add information to a file.PowerShell Function ProviderPowerShell has a set of Functions specified in the PowerShell engine. The PowerShell Function Provider allows us to access these functions using, hope this is starting to sound redundant, the same cmdlets as working with Files and Folders.Not familiar with what a function is? A function allows you to make calls to a block of code. When scripting, if you notice that you are using the same code over and over (within the same script), you should consider creating a function. A function would reduce the amount of code and keep your scripts clean and readable. The examples in the section will help define a Function. Be aware that we are discussing Functions defined in PowerShell, not how to create PowerShell Functions. Creating your own Functions comes later in the PowerShell Scripting tutorials.Example 1. Listing Functions

1. Use “Set-Location” cmdlet and connect to the PowerShell Function Provider’s PSDrive.

Set-Location Function:<enter>

2. You should be familiar with what cmdlet comes next…

Get-ChildItem<enter>

Page 38: PowerShell Tutorials

Functions Provider

Image 5.10Image 5.10 displays the Functions that are defined in PowerShell. “Name” is the name given to the function and the “Definition” is the code that runs when we call the name.What does it mean to “call” a function? In PowerShell, we are only required to type a function name and the corresponding code will execute. For example, typing “set-Location C:” navigates to the root of C: drive. We can also navigate to the root of C: just by typing(calling) the “C:” function name. PowerShell runs the “Set-Location C:” code which places us at the root of C: drive. Let’s take a look at another example.Example 2. Viewing the Code of a PowerShell Function

1. We are going to use the “Get-Content” cmdlet to view the code block of the Clear-Host Function.

Get-Content Clear-Host<enter>

Output:$spaceType = [System.Management.Automation.Host.BufferCell]; $space = [Sys

Page 39: PowerShell Tutorials

tem.Activator]::CreateInstance($spaceType); $space.Character = ‘ ‘; $space.ForegroundColor = $host.ui.rawui.ForegroundColor; $space.BackgroundColor= $host.ui.rawui.BackgroundColor; $rectType = [System.Management.Automation.Host.Rectangle]; $rect = [System.Activator]::CreateInstance($rectType);$rect.Top = $rect.Bottom = $rect.Right = $rect.Left = -1; $Host.UI.RawUI.SetBufferContents($rect, $space); $coordType = [System.Management.Automation.Host.Coordinates]; $origin = [System.Activator]::CreateInstance($coordType); $Host.UI.RawUI.CursorPosition = $origin;

So my guess is that you would be more inclined to calling the “Clear-Host” function than actually typing the code required to clear the screen. Can you see how calling a function reduces the amount of code written in the script?Before getting in too deep and making your head swim, I’m going to end this discussion about this Provider until we talk more about PowerShell Functions and Scripting. For now, let’s move on to the coolest PowerShell Provider in the world!!!The PowerShell Registry ProviderIf you ever wanted to work with the registry with the same ease as working with the file system, your wish has come true. The Registry Provider allows us to connect to two PSDrives; HKCU (HKEY_CURRENT_USER) and HKLM (HKEY_LOCAL_MACHINE). With the Registry Provider we can:

Navigate the registry. Search the registry. Create new registry keys. Delete registry keys. Add new values. Modify existing values. Manage ACLs (Access Control Lists).

Eample 1. Connect to the HKLM PSDrive and List Registry Keys.

1. The two PSDrives we can connect to are HKLM and HKCU. Verify this by checking which PSDrives are available.

Get-PSDrive<enter>

Image 5.11

Page 40: PowerShell Tutorials

Registry Provider

2. Connect to HKLM PSProvider using the “Set-Location” cmdlet.

Set-Location HKLM:<enter>

3. We can also connect anywhere in the path. Let’s connect to the SOFTWARE Key:

Set-Location HKLM:\Software<enter>

4. From the Software location let’s list the keys available.

Get-ChildItem<enter>

Image 5.12

Page 41: PowerShell Tutorials

HKLM

We’re all familiar with the warnings of making changes to the Registry. Since I wish to only help and do no harm, I’m not going to provide examples of making registry changes. Just note that you can use the same cmdlets used when working with all PowerShell Providers.Cmdlet Alias Cmd Commands DescritptionGet-Location gl pwd Current Directory.Set-Location sl cd, chdir Change current directory.Copy-Item cpi copy Copy Files.

Page 42: PowerShell Tutorials

Remove-Item ri del Removes a File or directory.Move-Item mi move Move a file.Rename-Item rni rn Rename a file.

New-Item ni n/aCreates a new empty file or folder.

Clear-Item cli n/a Clears the contents of a file.Set-Item si n/a Set the contents of a file.Mkdir n/a md Creates a new directory.

Get-Content gc typeSends contents of a file to the output stream.

Set-Content sc n/a Set the contents of a file.I will show you one very cool example of using the “Get-ChildItem” cmdlet to list installed Hot Fixes on a system:Get-ChildItem -Path “HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\HotFix”<enter>

Note: In the -Path parameter, quoting the path statement was required as there is a space between Windows and NT.You should now see a list of “Hot Fixes” that have been installed on the system. Staying with the theme of this PowerShell tutorial, I’m going to use the “CD” alias to navigate to one of the “Hot Fix” keys. Choose any hot fix you wish to enumerate.CD KB888240<enter>

Next question should be… How do we enumerate the information inside the registry key? Simply use the “Get-ItemProperty” cmdlet.Get-ItemProperty .<enter>

I used the “.” as we are currently working within the registry path location. You can also get the properties using the -Path parameter. Here’s the example:Get-ItemProperty -Path “HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\HotFix\KB888240″<enter>

Now we see all the properties, how about just a specific property?Get-ItemProperty . -Name Comments<enter>

Create and Remove a New Registry Key and PropertyFirst, Let’s work from the root of SOFTWARE.Set-Location -Path HKLM:\SOFTWARE<enter>

Create new registry Key and Default Property using “New-Item” cmdlet from the table.New-Item -Name Test -Value “This is a test string”<enter>

Verify “Test” key existsGet-ChildItem T*<enter>

Verify the default property has the string value we created.Get-ItemProperty -Path .\Test<enter>

Page 43: PowerShell Tutorials

Next, Let’s delete the new key using the “Remove-Item” cmdlet.Remove-Item Test<enter>

Verify the key has been removed.Get-ChildItem T*

Using the Registry Provider we are able to navigate, enumerate, create, and delete registry items just like files and folders.Real-World Example: An associate of mine started working for a banking institution. We’re talking multiple locations around the United States. His boss didn’t like the naming convention for network printers as they provided no clue of printer type or location. His task was to create new print queues (with a new naming convention) and cut all the user over to the new print queues. Because he was dealing with multiple locations, it was impossible for a tech to be on-site to remap clients to the new print queues. Another requirement was to automate the process so that clients would not experience down time when printing. He told the boss… “No Problem.”I’m only going to describe what he did in pseudo code as it would take another tutorial to examine his script. Network Print Queues are stored in the registry as a UNC (\\PrintServer\PrinterName). He created a second print queue for each printer on all his print servers. Created a printer script which used an array to store the old printer names and their new counterparts. The script would change the registry setting from \\PrintServer\OldQueue to \\PrintServer\NewQueue while also preserving the default printer setting. He replicated the new script to all Domain Controllers in his environment and edited the company’s logon script to call the printer script. When the printer script runs, it looks at the registry keys and if it finds reference to an old print queue name, it would edit that key with the new value. He allowed the script to run for a month or two to ensure that everyone using shared PCs would get the new print queues. After that time period, if he received calls from clients stating they could not connect to a new printer, he would just turn on the print script (uncomment it in the main logon script) and ask the client to re-logon the Domain.This example shows just how powerful connecting the registry can be. Needless to say, his boss thought he was brilliant (which he is) an sent him off to Hawaii (ok - maybe not! But it is a nice thought).The PowerShell Variable ProviderWhat is a variable? I like to think of a variable as a “little box” that is used to store information. The Variable Provider shows us which PowerShell and user defined variables are available. Again, we will be working with variables when scripting, so this is just an introduction.Example 1. Connect to the PSDrive Variable: and Show a List of Available VariablesConnect to the PSDrive.Set-Location Variable:<enter>

Use.. What Command to list variables?Get-ChildItem<enter>

Example 2. List the Information in the PSHome Variable

Page 44: PowerShell Tutorials

In PowerShell, variables are preceded by the dollar sign character ($). However, the list of variables in example 1. don’t show a “$” sign. To view the information stored in the PSHome variable, just add the “$” before the variable name.$PSHome<enter>

The $PSHome variable holds the information of the PowerShell installation path. Check out the information stored in other variables such as the $Profile and $Home variables.Example 3. Create a User Defined VariableThere are a few ways to create variables. Since were talking about File System cmdlets used with providers, sticking with theme we would do the following:New-Item MyVar -Value “This is my new variable.”<enter>

You can also use the “Set-Variable” cmdlet to accomplish the same:Set-Variable MyVar2 -Value “This is my second variable.”<enter>

This last example is most commonly used when scripting. You will find yourself using this example more than the others:$MyVar3 = “This is my third variable.”<enter>

Let’s sort the listing of variables by name and verify our newly created variables exist.Get-ChildItem | Sort {$_.Name}<enter>

Do you see MyVar, MyVar2, and MyVar3 user-defined variables?Example 4. Remove VariablesLet’s use the “Remove-Item” cmdlet to remove the variables we created:Remove-Item MyVar,MyVar2,MyVar3<enter>

Let’s verify the variables have been removed:Get-ChildItem | Sort {$_.Name}<enter>

By now your asking yourself, what is $_.Name? We can see that $_ must be a variable (all variables are noted by the dollar sign in PowerShell)… and it is. As defined, variables hold information. $_ is a special variable the holds the object piped from the “Get-ChildItem” cmdlet. The .Name is the Name Property of the object. I know your sick of me saying this but, we will explore script blocks in a later PowerShell tutorial.One more PowerShell Provider to go…The PowerShell Certificate ProviderHere is the last PowerShell Provider we need to cover. Using “Get-PSDrive” cmdlet we can see that we need to connect to the “cert” drive.Example 1. Set Location to the Cert PSDrive and List all the Certificates on the SystemSet-Location cert:<enter>

Get-ChildItem<enter>

This command truncates the “StoreNames” for good reason, there are a lot of entries. If you want a report of all certificates on a system may I suggest the following:Get-ChildItem -Recurse | Export-CSV “C:\Certificates.csv”<enter>

Page 45: PowerShell Tutorials

View results:Invoke-Item “C:\Certificates.csv”<enter>

Certificates

Image 5.13Wow!!! we made it to the end of this PowerShell Training session. The basic concepts to take away from this tutorial are that PowerShell Providers allow us to use common cmdlets outside of the PowerShell environment. We only have to learn a few cmdlets, shortening the learning curve, to be affective working with:

PowerShell Aliases Environment Variables

Page 46: PowerShell Tutorials

Files and directories Functions The Registry Variables in PowerShell Certificates

Hope you enjoyed this tutorial, use the comment section for any questions or comments. See you in the next PowerShell Tutorial…

Windows PowerShell Scripting Primer

PowerShell Tutorial 6: PowerShell Scripting - Introduction to Script Writing

It’s time to take what we have learned and apply it to writing scripts. The plan is six new and exciting PowerShell tutorials to explain the fundamentals of the PowerShell scripting language. Here is what will be covered:

Variables, Constants, Arrays, and Hash Tables. Using Conditional Logic. Processing data with Loops. Modular Scripting Using Functions. Scripting using WMI Objects (Computers, Printers, Etc…). Scripting using ADSI Objects (Active Directory Management).

Variables, Constants, Arrays, and Hash TablesWhat’s in Tutorial 7:

String manipulation and concatenation. Storing and Retrieving information using variables and Constants. Operators and Expressions. Creating, Modifying, and Combining Arrays and Hash Tables.

Conditional LogicTutorial 8. explains:

Testing conditions and running commands based on results. Introduce and work with “if” and “Switch” statements. Using Operators to test conditions.

LoopsTutorial 9. gets loopy:

Applying “while,” “do while” and “do until” loop processing.

Page 47: PowerShell Tutorials

Applying “for” and “foreach” loop processing.

Modular and Dot Source Scripting using FunctionsClean up your act in Tutorial 10:

Organizing your code Enlisting “Data Types” Calling Functions from other scripts

PowerShell Scripting using WMI ObjectsTutorial 11. Oh my! WMI:

Concept of WMI namespaces. The WMI Provider. Navigating and using the WMI namespace. WMI Classes. Using the “Get-WmiObject” cmdlet. Querying WMI.

PowerShell Scripting using ADSI Object (Active Directory Objects)Tutorial 12. Administration without the GUI:

Concepts of Active Directory Objects. The ADSI Provider. The Active Directory namespace. Creating and modifying Active Directory Objects (Users, Computers, OUs,

Groups, etc…)

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 VariablesThink of a variable as an imaginary box where we store information. Two basic uses of variables are:

Page 48: PowerShell Tutorials

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 strComputerdim strUserdim intDatestrComputer = “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

Page 49: PowerShell Tutorials

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>

$strComputer Variable

image 7.0The 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 StringsA [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

Page 50: PowerShell Tutorials

[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 objectYep, we will be discussing them all at some point…String ConcatenationConcatenation 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 NumbersPowerShell 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

Page 51: PowerShell Tutorials

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

Page 52: PowerShell Tutorials

$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.145. 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 = 73. [int]$y = 114. [decimal]$Pi = 3.145. strA + strB -or- strA += strB6. $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 ArraysVariables 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

Page 53: PowerShell Tutorials

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 = “.”

Page 54: PowerShell Tutorials

$colItems = get-wmiobject -class Win32_BIOS -namespace root\CIMV2 -comp $strComputerforeach ($objItem in $colItems) {write-host “BIOS Characteristics: ” $objItem.BiosCharacteristicswrite-host “BIOS Version: ” $objItem.BIOSVersionwrite-host “Build Number: ” $objItem.BuildNumberwrite-host “Caption: ” $objItem.Captionwrite-host “Code Set: ” $objItem.CodeSetwrite-host “Current Language: ” $objItem.CurrentLanguagewrite-host “Description: ” $objItem.Descriptionwrite-host “Identification Code: ” $objItem.IdentificationCodewrite-host “Installable Languages: ” $objItem.InstallableLanguageswrite-host “Installation Date: ” $objItem.InstallDatewrite-host “Language Edition: ” $objItem.LanguageEditionwrite-host “List Of Languages: ” $objItem.ListOfLanguageswrite-host “Manufacturer: ” $objItem.Manufacturerwrite-host “Name: ” $objItem.Namewrite-host “Other Target Operating System: ” $objItem.OtherTargetOSwrite-host “Primary BIOS: ” $objItem.PrimaryBIOSwrite-host “Release Date: ” $objItem.ReleaseDatewrite-host “Serial Number: ” $objItem.SerialNumberwrite-host “SMBIOS BIOS Version: ” $objItem.SMBIOSBIOSVersionwrite-host “SMBIOS Major Version: ” $objItem.SMBIOSMajorVersionwrite-host “SMBIOS Minor Version: ” $objItem.SMBIOSMinorVersionwrite-host “SMBIOS Present: ” $objItem.SMBIOSPresentwrite-host “Software Element ID: ” $objItem.SoftwareElementIDwrite-host “Software Element State: ” $objItem.SoftwareElementStatewrite-host “Status: ” $objItem.Statuswrite-host “Target Operating System: ” $objItem.TargetOperatingSystemwrite-host “Version: ” $objItem.Versionwrite-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 $strComputerforeach ($objItem in $colItems) {write-host “BIOS Characteristics: ” $objItem.BiosCharacteristicswrite-host “BIOS Version: ” $objItem.BIOSVersionwrite-host “Build Number: ” $objItem.BuildNumberwrite-host “Caption: ” $objItem.Captionwrite-host “Code Set: ” $objItem.CodeSetwrite-host “Current Language: ” $objItem.CurrentLanguage

Page 55: PowerShell Tutorials

write-host “Description: ” $objItem.Descriptionwrite-host “Identification Code: ” $objItem.IdentificationCodewrite-host “Installable Languages: ” $objItem.InstallableLanguageswrite-host “Installation Date: ” $objItem.InstallDatewrite-host “Language Edition: ” $objItem.LanguageEditionwrite-host “List Of Languages: ” $objItem.ListOfLanguageswrite-host “Manufacturer: ” $objItem.Manufacturerwrite-host “Name: ” $objItem.Namewrite-host “Other Target Operating System: ” $objItem.OtherTargetOSwrite-host “Primary BIOS: ” $objItem.PrimaryBIOSwrite-host “Release Date: ” $objItem.ReleaseDatewrite-host “Serial Number: ” $objItem.SerialNumberwrite-host “SMBIOS BIOS Version: ” $objItem.SMBIOSBIOSVersionwrite-host “SMBIOS Major Version: ” $objItem.SMBIOSMajorVersionwrite-host “SMBIOS Minor Version: ” $objItem.SMBIOSMinorVersionwrite-host “SMBIOS Present: ” $objItem.SMBIOSPresentwrite-host “Software Element ID: ” $objItem.SoftwareElementIDwrite-host “Software Element State: ” $objItem.SoftwareElementStatewrite-host “Status: ” $objItem.Statuswrite-host “Target Operating System: ” $objItem.TargetOperatingSystemwrite-host “Version: ” $objItem.Versionwrite-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 TablesA 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>

Page 56: PowerShell Tutorials

Hast Table

Image 7.1Looks 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.As with other programming languages, PowerShell is a dynamic scripting language. Script code can be executed based on conditions that exist or occur. For example, a script might prompt for user input and run a block of code based on the data supplied by the user. A process or application may stop running, triggering an action within a script. Conditional Logic allows us to write scripts in a complex environment, it adds the intelligence required to create decision-making scripts.Launch PowerShell and let's get started…Comparing Data

Page 57: PowerShell Tutorials

We are going to compare data using the following PowerShell Comparison and Logical Operators.Table 1: PowerShell Comparison Operators: Operator Description

-eq Equal to-lt Less than-gt Greater than-ge Greater than or Eqaul to-le Less than or equal to-ne Not equal to

I'm not going to join in the great debate over why these operators where chosen, they exists within PowerShell and must be used. Special note: When comparing text strings, by default PowerShell is not case-sensitive. "TOM" and "tom" would compare "equal to" (-eq). However, you can force PowerShell to compare values based on case-sensitivity. By appending an "i" to the operator, you're telling PowerShell to be "case-insensitive." Appending a "c" forces PowerShell to compare as "case-sensitive."Examples:Tom -eq TOM. The result is "True"Tom -ieq TOM. The result is "True"Tom -ceq TOM. The result is "False"Table 2: PowerShell Logical Operators:Operator Description

-not Not! Not

-and And-or Or

Now that we have the table listings of Operators, let's do some examples to show their use and results.7 -eq 7<enter>

Result is "True"7 -ne 7<enter>

Result is "False"7 -lt 10<enter>

Result is "True"7 -gt 10<enter>

Result is "False""Tom" -eq "tOm"<enter>

Result is "True""Tom" -ceq "tOm"<enter>

Page 58: PowerShell Tutorials

Result is "False"I'm going to skip the logical operators for now, we'll get back to them in a moment. What's important to understand is each code snippet is providing a result, either True or False. The results are used in the decision-making process within PowerShell scripts.Conditional LogicNow that we have results, what do we do with them? We need a way to apply comparison results with conditional logic (the decision-making process). PowerShell supports two logic statements to help out:

1. if - evaluates a comparison, then either executes or sidesteps code blocks based on the result. if statements require result of the comparison to be True to execute it's associated code block.

2. switch - Does the same as the if statement with the exception that it can evaluate multiple comparisons, each having the ability to execute code blocks. This is the same as a "select case" or "case" statements in VBScript and other programming languages.

Using the "if" StatementThe if statement syntax:if (condition) {code block}elseif (condition) {code block}else (condition) {code block}

condition = an expression that results to a Boolean Value (True or False). code block = what to execute if condition is True. elseif (optional) = test an alternative condition if preceding condition was

False. else (optional) = executes it's code block whenever none of the if or elseif

statements return a True result.

Let's do a simple script that shows the if statement in action. Copy the code into clogic.ps1 file and save it to the "MyScripts" directory. Run the script: "C:\MyScripts\clogic.ps1<enter>" -or- type ".\clogic.ps1 if you are currently working in the MyScripts directory.$x = 2 #creates a variable x and assigns 2 as the value  if ($x -eq 5) {Write-Host "Hello my name is Bob"}    elseif ($x -eq 4) {Write-Host "Hello, my name is Sue"}    elseif ($x -eq 2) {Write-Host "Hello, my name is Troy"}    elseif ($x -gt 1) {Write-Host "Hello, my name is Mary"}  else {"I have no idea what my name is?"}

The result should be Hello, my name is Troy as the condition ($x -eq 2) resulted in a True value and executed the script block {}. But I purposely threw you a curve ball. Notice that the last elseif statement ($x -gt 1) would also result in a True condition, so why doesn't it's script block get executed? This is by design, once an if statement condition results in a True value the associated script block is executed and

Page 59: PowerShell Tutorials

PowerShell stops testing subsequent conditions. The way around this is to use a switch statement which we will discuss in this PowerShell training session.Real-World Example:Sometimes different Operating Systems use different WMI classes and/or properties. I ran into this difference when attempting to enumerate printers on Windows XP, Windows 2003, and Windows 2000. I used an if statement to test the OS version and based on the version, PowerShell would run the code block associated for each OS. Here's the code I used:Copy the following code into a .ps1 script file. Name it PrintReport.ps1 and execute the script.$strComputer = Read-Host "Printer Report - Enter Computer Name"$OS = Get-WmiObject -Class win32_OperatingSystem -namespace "root\CIMV2" `-ComputerName $strComputer# if statement to run code for Windows XP and Windows 2003 Server.if (($OS.Version -eq "5.1.2600") -or ($OS.Version -eq "5.2.3790")){    write-host "Computer Name: " $strComputer    #nested if statement    if ($OS.Version -eq "5.1.2600") {write-host "OS Version: Windows XP"}    elseif ($OS.Version -eq "5.2.3790") {write-host "OS Version: Windows 2003"}        $colPrinters = Get-WmiObject -Class win32_Printer -namespace "root\CIMV2" `        -computerName $strComputer            foreach ($objPrinter in $colPrinters) {            write-host "Name: " $objPrinter.Name            write-host "Description: " $objPrinter.Description            write-host            }}# if statement to run code for Windows 2000 Serverelseif ($OS.Version -eq "5.0.2195"){    write-host "Computer Name: " $strComputer    write-host "OS Version: Windows 2000 Server"        $colPrinters = Get-WmiObject -Class win32_PrintJob -namespace "root\CIMV2" `        -computername $strComputer        foreach ($objPrinter in $colPrinters) {        write-host "Name: " $objPrinter.Name        write-host "Description: " $objPrinter.Description        write-host        }}# if OS not identifiedelse {write-host "The OS for: $strComputer is not supported."}write-host "–END OF REPORT–"

Page 60: PowerShell Tutorials

When the script is executed, you are prompted to enter the computer name you wish to enumerate. By adding the "Read-Host" cmdlet, you're now able to enumerate other computers on your network. Pretty cool stuff going on here, let's break it down.Step 1. $strComputer = Read-Host "Printer Report - Enter Computer Name"Creates a variable called $strComputer and assigns a value supplied from user input.Step 2.  $OS = Get-WmiObject -Class win32_OperatingSystem -namespace "root\CIMV2" `-ComputerName $strComputerCreates the variable "$OS" and assigns the win32_OperatingSystem class object. Something else to look at. Even though it looks like two lines of code, it's actually one line of code. The "`" escape character means to continue as one line. Used for keeping scripts legible should you run out of space. PowerShell reads the line as:$OS = Get-WmiObject -Class win32_OperationSystem -namespace "root\CIMV2" -Computername $strComputerStep 3.  if (($OS.Version -eq "5.1.2600") -or ($OS.Version -eq "5.2.3790"))Here is where we talk about Logical Operators.Operator Description

-not Not! Not

-and And-or Or

What you need to know. The Not operators -not and ! (both mean NOT) allow you to modify the results of a condition. For example:if (1 -eq 1) - results in a True value and runs the script block.if (!(1 -eq 1) - results in a False value and skips the script block.The -or operator means at least one of the conditions must be True to execute the script block.For example:if ((1 -gt 2) -or (2 -gt 1)) - One of the conditions are True so, it's associated script block will execute.The -and operator means that all conditions must be True to execute the script block.Example:if ((1 -ge 1) -and (2 -ge 1)) - Both conditions are True, script block executes.if ((1 -ge 1) -and (2 -le 1)) - The first condition is True, whereas the second is False. The script block is skipped.Step 4.  {    write-host "Computer Name: " $strComputer    #nested if statement    if ($OS.Version -eq "5.1.2600") {write-host "OS Version: Windows XP"}    elseif ($OS.Version -eq "5.2.3790") {write-host "OS Version: Windows 2003"}        $colPrinters = Get-WmiObject -Class win32_Printer -namespace "root\CIMV2" `        -computerName $strComputer            foreach ($objPrinter in $colPrinters) {            write-host "Name: " $objPrinter.Name

Page 61: PowerShell Tutorials

            write-host "Description: " $objPrinter.Description            write-host            }}In step 3. if one of the conditions are True the script block in step 4. is executed. The script block writes the following information to the screen:

The Computer Name The OS Type - Note, in RED, we can nest additional if statements within

code blocks. Now you are stating to see how complex PowerShell, as a scripting language, can be.

The script block then enumerates the win32_Printer class and sends the requested property information to the screen.

Once the block completes, PowerShell skips to Step 8. and writes "–END OF REPORT–" to let the end user know it has completed.

If none of the conditions are True in step 3. PowerShell moves to the next if statement, in this example that would be…Step 5.  elseif ($OS.Version -eq "5.0.2195")If this condition results in a True value, the script block in step 6. is executed.Step 6.  {    write-host "Computer Name: " $strComputer    write-host "OS Version: Windows 2000 Server"        $colPrinters = Get-WmiObject -Class win32_PrintJob -namespace "root\CIMV2" `        -computername $strComputer        foreach ($objPrinter in $colPrinters) {        write-host "Name: " $objPrinter.Name        write-host "Description: " $objPrinter.Description        write-host        }}The result of the script block outputs the following information to the screen:

Computer Name OS version Requested Property information of the win32_PrintJob class. Once the block completes, PowerShell skips to Step 8. and writes "–END

OF REPORT–" to let the end user know it has completed.

If the result in step 5. is False, PowerShell continues reading the script and finds the "else" statement.Step 7.  else {write-host "The OS for: "$strComputer" is not supported."}Outputs " The OS is not supported." Step 7. runs when all conditions in the script end with a False value.

Page 62: PowerShell Tutorials

Step 8. write-host "–END OF REPORT–"Let's you know the script has completed.This example shows just how dynamic our scripts can be, based on conditions that exist in our environment. And how we can write if statements to test those conditions and run script blocks according to the results of those tests. Using the Switch Statement for Multiple ComparisonsSince we can use elseif statements to test multiple conditions, there may come a time when too many additional tests lend to difficult script writing and down-right ugliness. There are other times where you want to test multiple conditions that result in multiple True values and you don't want the script to stop testing when it receives the first True value (as it does with an if statement). The option that allows you to accomplish this is the switch statement. The PowerShell switch statement organizes a collection of tests that are evaluated using the same expression.The Switch statement syntax:switch (expression){  (test) {code block}  value {code block}  default {code block}}

Test = An evaluated expression. Value =  A value, like a number or text string. Default = Default code block to run if none of the expressions return a

True value.

Here is an example from Ed Wilson's PowerShell book: "Windows PowerShell Step by Step." Save the script code as ComputerRoles.ps1 and run the script:$objWMI = Get-WmiObject -Class win32_ComputerSystem -namespace "root\CIMV2""Computer "+ $objWMI.name + " is a: "switch ($objWMI.domainRole)  {  0 {Write-Host "Stand alone workstation"}  1 {Write-Host "Member workstation"}  2 {Write-Host "Stand alone server"}  3 {Write-Host "Member server"}  4 {Write-Host "Back-up domain controller"}  5 {Write-Host "Primary domain controller"}  default {Write-Host "The role can not be determined"}  }

In this example I used a number value which correlates to the value of the domainrole property within the win32_ComputerSystem WMI class. When the value was returned as True, the script block output the role using the "Write-Host" cmdlet.Modify the script to prompt user for "Computer Name:"

Page 63: PowerShell Tutorials

$strComputer = Read-Host "Enter Computer Name"$objWMI = Get-WmiObject -Class win32_ComputerSystem -namespace "root\CIMV2" `  -computername $strComputerWrite-Host "Computer: $strComputer is a:"switch ($objWMI.domainRole)  {  0 {Write-Host "Stand alone workstation"}  1 {Write-Host "Member workstation"}  2 {Write-Host "Stand alone server"}  3 {Write-Host "Member server"}  4 {Write-Host "Back-up domain controller"}  5 {Write-Host "Primary domain controller"}  default {Write-Host "The role can not be determined"}  }

Now that we can input the $strComputer value, we can run this script on any remote computer in the environment, as long we have local admin rights.This next example has no real purpose other than demonstrating how the switch statement works using the (test) expression with multiple True value results. Unlike if statements, switch statements continue running when True value matches are found. So it is possible that more than one code block will be executed. Copy and Paste the code into the PowerShell shell. The results should be obvious, test expressions that correctly equal 10 will run:switch (10){  (1 + 9) {Write-Host "Congratulations, you applied addition correctly"}  (1 + 10) {Write-Host "This script block better not run"}  (11 - 1) {Write-Host "Congratulations, you found the difference correctly"}  (1 - 11) {Write-Host "This script block better not run"}}

Conditional logic is the foundation for dynamic PowerShell script writing. We successfully demonstrated how we can control the flow of a script base on conditional responses. In the next PowerShell training session we are going to build on what we have learned and introduce Loops, which takes flow control to the next level. See you in the next PowerShell tutorial…

Conditional Logic Using Loops

PowerShell Tutorial 9: Getting LoopyThe last PowerShell training session introduced Conditional Logic, controlling execution of script blocks with if and switch statements. Looping is a basic programming process that allows us to repeat a command and process large amounts of data. Without this ability, writing scripts would be tedious if not next to impossible.Here are the loops we will be working with in this tutorial:

Page 64: PowerShell Tutorials

do while - Script block executes as long as condition value = True. while - Same as “do while.” do until - Script block executes until the condition value = True. for - Script block executes a specified number of times. foreach - Executes script block for each item in a collection or array.

do while and whiledo while and while Loops executes “while” the condition value stays True.Syntaxes:do whiledo {code block}while (condition)whilewhile (condition) {code block}Both loops run code block while the condition is True. the difference between the two; do while runs the code block (at least once) before testing the condition, while tests the condition before executing the code block. So if required, you can always count on the do while loop to execute the code block at least once, even if the condition = False. This is one of those rules you will want to remember when troubleshooting scripts.Example: do while - Count to 5Type the code into notepad and save with the .ps1 file extension or copy and paste into PowerShell.$i = 1 do {Write-Host $i; $i++}while ($i -le 5)- or written like this -$i = 1do {Write-Host $i$i++}while ($i -le 5)

Output:12345What the code is doing:1. Creates the variable $i and assigns the Integer value of “1″.2. do - Code block writes the output of the variable. If you remember, $i++ increments the value of the variable by 1 each time the code block is executed (looped).3. while - The condition statement compares the value of $i to the number 5, using the comparison operator -le (less than or equal to). As long as the condition is true, the loop continues to run.

Page 65: PowerShell Tutorials

This simple example is just to help you with understanding the concepts. Let’s look at the same example using the while loop.$i = 1 while ($i -le 5) {Write-Host $i; $i++}- or written like this -$i = 1while ($i -le 5) {Write-Host $i$i++}

In the code examples I’m showing both ways of writing script blocks, either single line or multi-line. Basically, the semi-colon (;) is a delimiter which allows us to separate commands when writing code on a single line. The <carriage return> or <enter> delimits code when using multiple lines. Either way is correct, it just depends on how long your command statements become.Real-World PowerShell example:Scenario: Our company is having application issues with Notepad and it is mission critical (LOL). It can actually be any application in your environment. We have been asked to monitor the application and report any failure and log the time the failure occurred.Solution: We’re going to use PowerShell to build a simple script to monitor the process and report when a failure occurs. We’re going to use a do while loop to watch the “Responding” property of the “Get-Process” object cmdlet. From an earlier PowerShell training session I showed you how to get an object’s properties and methods using the “Get-Member” cmdlet. As already stated, we will be using the “Responding” property for our script.Get-Process | Get-Member<enter>

Step 1. Close all current running versions of Notepad (if applicable).Step 2. Write the script, save as NoteMon.ps1#launches NotepadNotepad #Setup a do while loop that does nothing while property value is True.do {}While (get-process notepad | select -Property Responding)#Code to run when loop stops (when notepad is closed)$strTime = get-dateWrite-Host “The Application Notepad failed to respond on: $strTime”

Step 3. Run the NoteMon.ps1 script. Move notepad so that you can see the PowerShell console.Step 4. Exit or Close Notepad. The following is reported to the console window: “The Application Notepad failed to respond on: 10/25/2007 14:16:07″Run the script again if you wish to restart the application. OK, so kind of a simple “poor-man’s” example of creating a monitoring system. Again, it’s provided to help you

Page 66: PowerShell Tutorials

understand the looping concept and to give you a better real world example, rather than just counting numbers.Additional Reading:Get-Content $PSHome\about_while.help.txt

do untilThe do until loop is the opposite of do while. It executes the code block until the condition is True, in other words it runs while the condition value is False.Syntax:do {code block}until (condition)Example:$i = 1 do {Write-Host $i; $i++}until ($i -gt 5)

Output:12345In this example the script block runs until the variable ($i) is incremented to the value of 6. Since 6 is greater than 5 the condition value becomes True, halting the loop from executing further.Real-World PowerShell Example:Jerry Lee Ford’s book (Microsoft Windows PowerShell Programming for the absolute beginner) teaches PowerShell through game creation. It’s a fun book that I recommend for beginners, “No Experience Required.” You can read my review and pick up a copy from this site. Jerry uses the do until loop to control the collection of user input. Here is the example.$strResponse = “Quit” do {$strResponse = Read-Host “Are you sure you want to quit application? (Y/N)”}until ($strResponse -eq “Y”)

Page 67: PowerShell Tutorials

do until loop

Image 9.0Looking at the image, I copied the code into PowerShell and typed in numerous responses. Each time the response did not equal “Y” the value of the condition was False, therefore the script block was execute again and prompted the user for input.forThe standard use of the for statement it to run the code block a specified number of times.Syntax:for (initialization; condition; repeat){code block}Note: each of the three parameters are optional.

initialization -  one or more commands, separated by commas, that run before the loop begins. Commonly used to create and initialize a variable with a starting value. This variable is the basis for the condition to be tested in the next portion of the for statement.

Condition - Resolves to a Boolean True or False value. PowerShell evaluates the condition each time the loop runs. If the condition is True the code block is executed, then the condition is tested again.

Repeat - one or more commands, separated by commas, that run each time the loop repeats. Commonly used to modify a variable that is tested inside the “condition” portion of the for statement.

Example:for ($i=1; $i -le 5; $i++){Write-Host $i}

Output:123

Page 68: PowerShell Tutorials

45Couple of things to take note:

We delimit each parameter with a semi-colon (;). Don’t confuse this with separating commnads within a parameter using commas.

We assigned the variable ($i=1) within the condition statement. Since parameters are optional we could have assigned the variable outside of condition statement. If you omit a parameter you are required to still use (;) to delimit the parameters, example in BLUE. Here is the example showing variable assignment outside the condition and how it would look.

$i=1for (; $i -le 5; $i++){Write-Host $i}

Test what would happen if you omit a parameter forget to delimit (;) and attempt to run the code.$i=1for ($i -le 5; $i++){Write-Host $i}

OK - don’t panic, your in an infinite loop!!! Just type “Ctrl + C” to quit PowerShell execution. Forgetting to delimit an omitted parameter can cause some unexpected results, be careful.If your code becomes large you can always delimit using <carriage return>.for ($i=1$i -le 5$i++){write-host $i}

The for loop can also be used to process elements within an array.$ints = @( 1, 2, 3, 4, 5) for ($i=0; $i -le $ints.Length - 1; $i++){Write-Host $ints[$i]}

Do you know why the example sets the variable ($i) to 0 (zero) rather than 1? Remember from the “Arrays” tutorial that arrays are indexed starting with the number 0. If we set the variable to 1, our output would have been 2 3 4 5 <blank>.The condition statement states, run script block as long as $i is less than or equal to 4.  $int.Length (length would be 5 entries in the array) so 5 - 1 = 4. When the Write-Host cmdlet runs it gives us the following entries (0=1, 1=2, 2=3, 3=4, 4=5).Output:12345

Page 69: PowerShell Tutorials

You should not have any issues working with arrays, as long as you remember that indexing begins with 0 (zero). I dealt with this in VBScript and was hoping it would have changed with PowerShell, maybe a later release?Additional Reading:Get-Content $PSHome\about_for.help.txt

foreachThe foreach loop description from the PowerShell Help file:

The foreach statement (also known as a foreach loop) is a language construct for stepping through (iterating) a series of values in a collection of items. The simplest and most typical type of collection to traverse is an array. Within a foreach loop it’s common to run one or more commands against each item in an array.

Note: Those writing VBScript code will have to get use to not using “Next” as PowerShell doesn’t require the keyword to move to the next item in the collection.Syntax:foreach ($<item> in $<collection>){code block}Sticking with our number example, let’s see how the foreach loop works$ints = @(1, 2, 3, 4, 5) foreach ($i in $ints){Write-Host $i}

Output:12345Looks a little like the for loop example presented earlier. However, notice that we are not testing a condition. The foreach loop runs the script block against each element within the array. It doesn’t required testing a condition and it doesn’t care how many elements exist in the array. You point it and it runs. As stated in the help file, foreach loop is the most typical statement used when working will arrays and collections.I have presented many examples of foreach loops on this site. Most of the Microsoft PowerShell Scripts in the Scripting Center use this loop.Real-World Examples:How about listing processor information.$strComputer = “.” $colItems = get-wmiobject -class “Win32_Processor” -namespace “root\CIMV2″ `-computername $strComputerforeach ($objItem in $colItems) {write-host “Caption: ” $objItem.Captionwrite-host “CPU Status: ” $objItem.CpuStatuswrite-host “Current Clock Speed: ” $objItem.CurrentClockSpeedwrite-host “Device ID: ” $objItem.DeviceIDwrite-host “L2 Cache Size: ” $objItem.L2CacheSize

Page 70: PowerShell Tutorials

write-host “L2 Cache Speed: ” $objItem.L2CacheSpeedwrite-host “Name: ” $objItem.Namewrite-host}

Listing disk information$strComputer = “.” $colItems = get-wmiobject -class “Win32_DiskDrive” -namespace “root\CIMV2″ `-computername $strComputerforeach ($objItem in $colItems) {write-host “Description: ” $objItem.Descriptionwrite-host “Device ID: ” $objItem.DeviceIDwrite-host “Interface Type: ” $objItem.InterfaceTypewrite-host “Media Type: ” $objItem.MediaTypewrite-host “Model: ” $objItem.Modelwrite-host “Partitions: ” $objItem.Partitionswrite-host “Size: ” $objItem.Sizewrite-host “Status: ” $objItem.Statuswrite-host}

Let’s say we want to determine which processes are running on our computer.foreach ($item in Get-Process){if ($item.Responding -eq “True”){Write-Host $Item.Name}}

Just showing that we can add the conditional logic if statement within the foreach loop to give us more control over the data we wish to retrieve.Notice the code block - {{}} - what I’ve done is called nesting. Perfectly legal and a concept that we will discuss as you progress through these PowerShell Training sessions.Additional Reading:Get-Content $PSHome\about_foreach.help.txt

Varying Loop ProcessingThere are two statements, break and continue, that allow you to alter the execution of a loop when certain conditions are met.The Break StatementExcerpt: Taken from the PowerShell help file.

A break statement appearing in a code block of a foreach, for, while, or do loop or in a switch statement, ends the code block. In the case of the looping statements, the break statement causes the loop to exit. In the case of the switch statement, the break statement causes a code block inside of a switch statement to exit and thus the entire switch statement exits.The following example shows how to use a break statement to exit a for statement:

for($i=1; $i -le 10; $i++){

Page 71: PowerShell Tutorials

Write-Host $ibreak}

In this case, the break statement exits the for loop when $i equals 1. Even though the for statement evaluates to true until $i is greater than 10, the Windows PowerShell reaches the break statement the first time through the for loop.It’s more common to see the break statement used inside of a loop where there is some inner condition to be met. Consider the following foreach statement example:

$i=0$varB = (10,20,30,40)foreach ($var in $varB){$i++if ($var -eq 30){break}}Write-Host “30 was found in array position $i”

In this example, the foreach statement iterates the $varB array. Each time through the code block, the $i variable is incremented by 1. The if statement inside evaluates to false the first two times through the loop. The third time through the loop, $i equals 3 and the $val variable equals 30, at which point the break statement runs and the foreach loop exits.

Additional Reading:Get-Content $PSHome\about_break.help.txt

The Continue StatementExcerpt from PowerShell help file:

In a script, the continue statement causes program flow to move immediately to the top of the innermost loop controlled by any of these statements:

for foreach while

EXAMPLEIn this example, program flow returns to the top of the while loop if $ctr is equal to 5. The result is that all numbers between 1 and 10 except 5 are displayed.

while ($ctr -lt 10){$ctr += 1if ($ctr -eq 5){continue}Write-Host $ctr}

Page 72: PowerShell Tutorials

Note that in a for loop, execution continues at the first line in the loop. If the arguments of the for statement test a value that is modified by the for statement, an infinite loop can result.

In this PowerShell Training session you learned how to control script block flow using loop processing. You were also able to process large amounts of data by looping through a collection and enumerating properties of an object. In up-coming PowerShell Let’s start off be defining the terms:

Function - A function allows you to name a block of code. The code block can then be called (by its name) once or multiple times anywhere from within your script.

Filter - A Filter (as it sounds) takes large amounts of pipeline data and displays only the results of interest to you.

PowerShell FunctionsThe main reason I use functions is script organization. It allows me the ability to call script blocks multiple times within a script, cutting down on the amount of code writing to accomplish my task. Not to mention it improves readability and makes complex PowerShell scripts manageable. This PowerShell training session introduces the concepts of a Function and a Filter. It is intended as an introduction, advance techniques will be covered in the PowerShell advanced tutorials launched early next year. With that being said, this tutorial will teach the concept of functions used for modular scripting and how to build libraries of reusable code. We will also briefly talk about filters.Function Syntax:Function(keyword) FunctionName (parameters) {script block}The syntax uses the keyword Function, a FunctionName you provide, optional parameters, and the script block.Example 1. Create a Function called “Time” which runs the Get-Date cmdlet when called.Function Time {Get-Date}<enter>

Call the function by typing the FunctionName Time at the command prompt.

PowerShell Function

image 10.1Simple stuff right! We defined a function using the “Function” keyword, named the function “Time,” omitted the optional parameters, and assigned the Get-Date cmdlet within the script block. Now let’s start adding some parameters.

Page 73: PowerShell Tutorials

Passing Arguments to FunctionsThere are multiple ways to pass arguments to a function. I’ll introduce some common methods.Method 1: Passing Arguments in a comma separated list. Notice that the parameters enclosed in parenthesis and separated by a comma, much like an array.Function Add ($x, $y){$Ans = $x + $yWrite-Host “The Answer is $Ans”}

Result

Copy the code into PowerShell and hit enter twice to get back to the command prompt. Now, at the command prompt type the function and arguments for $x and $y variables:Add 10 2<enter>You should see the following result - The Answer is 12

image 10.2Method 2: Using the Param keyword. When using the Param keyword, notice that we are defining the arguments within the scriptblock {}. The Param keyword must be the first word inside the script block.Function Add{param ($x, $y) $Ans = $x + $yWrite-Host “The Answer is $Ans”}

Type - Add 10 12<enter>

Page 74: PowerShell Tutorials

Addition

image 10.3Method 3: If you recall from PowerShell Tutorial 7: Variables, Arrays, and Hash Tables - There is a special variable $Args which contains an array of the parameters passed to a function. Let’s use this variable to show how we can pass an argument using string expantion.Function HAL {”What are you doing $args ?”}<enter>

Type in the FunctionName and an Argument:HAL Dave

$Args

image 10.4You can use multiple $Args variables to pass more than one parameter.Example 2.Function Add { $args[0] + $args[1] }<enter>

Type: Add 5 8

Multiple $Args

image 10.5Defining Data TypesRemember the “Data Type” table that was introduced in PowerShell training session 7?

Page 75: PowerShell Tutorials

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 objectPowerShell does a good job of automatically setting data types for us. Although, there may be instances were it is required to define (or hard code) the expected data type for a variable. Best practices would recommend that you always define the Data Type for a variable as it prevents parsing errors. For example, you have written a script that asks the users age. The expected result is an integer, otherwise the script would fail.Let’s test this:Function Age{Param ([int]$x) Write-Host “You are $x years old.”}

Data Type Error

image 10.6Notice to two commands I ran in image 10.6.

Age 10 - The argument 10 is an integer and is accepted by PowerShell resulting in the output You are 10 years old.

Page 76: PowerShell Tutorials

Age A - The argument A is not an integer and cannot be automatically converted as we defined the variable requirement as an integer ([int]$x). Therefore PowerShell gives us the error in image 10.6.

Assigning a Default ValueWe can also assign a default value should an argument not get passed to the function.Function Add{Param ([int]$x = 0, [int]$y = 0) $Ans = $x + $yWrite-Host $Ans}

Data Type Error

image 10.7So I created the Add function with the default variable of $x=0 and $y=0. What happens when I run the following commands:

Add 10 2 - Variable $x becomes 10 and $y becomes 2. The result is 12.

Add - Since we did not send any arguments, the default was used for $x and $y resulting in 0 + 0 = 0.

Add A - Again, we attempted to send an alpha character when the expected entry for the variable is an integer resulting in a conversion error. I wanted to make a point that sending the wrong data type does not result in the variable being assigned the default of 0.

Using the PowerShell Special Variable “$input”The $input variable allows a function to access data coming from the pipeline. For example let’s say were looking for the folder “Windows” and we don’t know where it is located.

Page 77: PowerShell Tutorials

First build the function to find the Windows Folder:Function FindFolder{$input | Where-Object {$_.Name -eq “Windows”}}

Next Type the following command which pipes the cmdlet output to the function we defined:Get-ChildItem -Path C:\ | FindFolder<enter>

$input Results

image 10.8So, what are we doing here? We created a function call FindFolder which uses the “Where-Object” cmdlet to filter results based on the Name property. But what results is it filtering? By itself it is just a function that does nothing until we send piped results to the $input variable.In this example we run the Get-ChildItem cmdlet telling it to start at the root of C:\ drive. Simple enough, if we ran this command by itself we would get all the files and directories just under the root of C: drive. By piping the information to our function, the information is stored in the $input variable and only the folder named “Windows” is allow to pass.Let me show you how we can use a function to find a needle in the haystack. In this example we will use a filter to find the Hosts file on a system.Create the Function:Function FindHosts{$input | Where-Object {$_.Name -eq “hosts”}}

Next, since were not sure if the directory containing the hosts file is a directory under of the root of C: drive, we use the -recurse parameter to search all directories and subdirectories under the root.Use the following command:Get-ChildItem -Path C:\ -Recurse | FindHosts<enter>

Page 78: PowerShell Tutorials

Eventually we find the hosts file and the location Directory: Microsoft.PowerShell.Core\FileSystem::C:\Windows\system32\drivers\etcI know that there are other ways to filter this information in PowerShell. The examples provided were to show how this task can be accomplished using functions. Next let’s talk about filters.PowerShell FiltersA Filter and a Function are essentially the same. The difference is how they process data.Filter Syntax:Filter(Keyword) FilterName (parameters) {Script Block}The syntax is the same as defining a Function except the “Filter” keyword is used, not the “Function” keyword. A function uses the $input variable to contain pipeline information whereas the filter uses a special variable $_ that contains the current pipeline object. Here is where the Function and Filter differ; The function doesn’t run until all data has been stored in the $input variable, whereas the filter has immediate access to the $_ variable and begins processing elements as they become available (streaming).Due to the $_ variable being able to process objects immediately, filters are widely used and more efficient when large amounts of data are passed through the object pipeline.For now, just take in the concepts. We will be working more with filters as we progress.Real World ExamplesOrganizing Your CodeThere are two methods I use to organize code:

1. Modular Scripting2. Dot Sourcing

I find both methods useful but, most of the feedback I have gotten points to Dot Sourcing as being the most commonly used method. I’m going to show you both as I believe both methods have there own unique value.Modular Scripting ExampleI’m going to take two PowerShell script examples from the “Microsoft Script Center” and show you how to create user-defined functions and call them from a script.Say you want to inventory your system, gathering information about the Processor(s) and Disk(s) available on the system. From the “Microsoft Scripting Center” you find these two scripts.List Processor Information:$strComputer = “.” $colItems = get-wmiobject -class “Win32_Processor” -namespace “root\CIMV2″ `-computername $strComputerforeach ($objItem in $colItems) {write-host “Caption: ” $objItem.Captionwrite-host “CPU Status: ” $objItem.CpuStatuswrite-host “Current Clock Speed: ” $objItem.CurrentClockSpeedwrite-host “Device ID: ” $objItem.DeviceIDwrite-host “L2 Cache Size: ” $objItem.L2CacheSize

Page 79: PowerShell Tutorials

write-host “L2 Cache Speed: ” $objItem.L2CacheSpeedwrite-host “Name: ” $objItem.Namewrite-host}

List Physical Disk Properties:$strComputer = “.” $colItems = get-wmiobject -class “Win32_DiskDrive” -namespace “root\CIMV2″ `-computername $strComputerforeach ($objItem in $colItems) {write-host “Description: ” $objItem.Descriptionwrite-host “Device ID: ” $objItem.DeviceIDwrite-host “Interface Type: ” $objItem.InterfaceTypewrite-host “Media Type: ” $objItem.MediaTypewrite-host “Model: ” $objItem.Modelwrite-host “Partitions: ” $objItem.Partitionswrite-host “Size: ” $objItem.Sizewrite-host “Status: ” $objItem.Statuswrite-host}

List Processor Information and List Disk FunctionsIn this example we are converting the ListProcessor and the ListDisk scripts, provided by Microsoft, into functions. Here are the syntaxes I’ve used: Function ListProcessor {Script Block} -and- Function ListDisk {Script Block}Note: In PowerShell scripting, the “#” symbol is used for comments.ListProcessor Function# FileName: ListProcessor.txt# =============================================================================# FUNCTION LISTINGS# =============================================================================# Function: ListProcessor# Created: [09/17/2007]# Author: Jesse Hamrick# Arguments:# =============================================================================# Purpose: Provides Processor information### ==================================================================

Page 80: PowerShell Tutorials

===========function ListProcessor {$colItems = get-wmiobject -class “Win32_Processor” -namespace “root\CIMV2″ `-computername $strComputer foreach ($objItem in $colItems) {write-host “Caption: ” $objItem.Captionwrite-host “CPU Status: ” $objItem.CpuStatuswrite-host “Current Clock Speed: ” $objItem.CurrentClockSpeedwrite-host “Device ID: ” $objItem.DeviceIDwrite-host “L2 Cache Size: ” $objItem.L2CacheSizewrite-host “L2 Cache Speed: ” $objItem.L2CacheSpeedwrite-host “Name: ” $objItem.Namewrite-host}}

ListDisk Function#* FileName: ListDisk.txt#*=============================================================================#* FUNCTION LISTINGS#*=============================================================================#* Function: ListDisk#* Created: [09/15/2007]#* Author: Jesse Hamrick#* Arguments:#*=============================================================================#* Purpose: Provides Disk Information#*#*#*=============================================================================Function ListDisk {$colItems = get-wmiobject -class “Win32_DiskDrive” -namespace “root\CIMV2″ `-computername $strComputer foreach ($objItem in $colItems) {write-host “Description: ” $objItem.Descriptionwrite-host “Device ID: ” $objItem.DeviceIDwrite-host “Interface Type: ” $objItem.InterfaceTypewrite-host “Media Type: ” $objItem.MediaTypewrite-host “Model: ” $objItem.Modelwrite-host “Partitions: ” $objItem.Partitionswrite-host “Size: ” $objItem.Sizewrite-host “Status: ” $objItem.Statuswrite-host

Page 81: PowerShell Tutorials

}}

To verify functionality, you can copy and paste the functions into PowerShell and call them from the command line by name. They will enumerate the data on the local host.Building a Modular PowerShell ScriptI’m going to write a script that enumerates the processor(s) and disk(s) properties. I’ll “snap-in” my newly created functions and use the “SCRIPT BODY” section of the template to control the function calls. This may sound familiar to you if you have worked with VBScript; subroutines and functions. Couple of differences:

1. Functions in PowerShell provide the same functionality that both subroutines and functions did in VBScript. So, subroutines do not exist in PowerShell.

2. PowerShell parses scripts sequentially - meaning functions need to be declared before they can be called in the script. This is unlike VBScript, were the whole script is read by the scripting host before it is executed.

Here is what a modular script would look like:#* FileName: ComputerInv.ps1#*=============================================================================#* Script Name: [Computer Inventory]#* Created: [09/15/2007]#* Author: Jesse Hamrick#* Company: PowerShell Pro!#* Email:#* Web: http://www.powershellpro.com#* Reqrmnts:#* Keywords:#*=============================================================================#* Purpose: Computer Invetory of CPU and Disk Properties#*#*#*============================================================================= #*=============================================================================#* REVISION HISTORY#*=============================================================================#* Date: [DATE_MDY]#* Time: [TIME]#* Issue:#* Solution:#*

Page 82: PowerShell Tutorials

#*=============================================================================#*=============================================================================#* FUNCTION LISTINGS#*=============================================================================# Function: ListProcessor# Created: [09/17/2007]# Author: Jesse Hamrick# Arguments:# =============================================================================# Purpose: Provides Processor information### =============================================================================function ListProcessor {$colItems = get-wmiobject -class “Win32_Processor” -namespace “root\CIMV2″ `-computername $strComputerforeach ($objItem in $colItems) {write-host “Caption: ” $objItem.Captionwrite-host “CPU Status: ” $objItem.CpuStatuswrite-host “Current Clock Speed: ” $objItem.CurrentClockSpeedwrite-host “Device ID: ” $objItem.DeviceIDwrite-host “L2 Cache Size: ” $objItem.L2CacheSizewrite-host “L2 Cache Speed: ” $objItem.L2CacheSpeedwrite-host “Name: ” $objItem.Namewrite-host}}#*=============================================================================#* Function: ListDisk#* Created: [09/15/2007]#* Author: Jesse Hamrick#* Arguments:#*=============================================================================#* Purpose: Provides Disk Information#*#*#*=================================================================

Page 83: PowerShell Tutorials

============Function ListDisk {$colItems = get-wmiobject -class “Win32_DiskDrive” -namespace “root\CIMV2″ `-computername $strComputerforeach ($objItem in $colItems) {write-host “Description: ” $objItem.Descriptionwrite-host “Device ID: ” $objItem.DeviceIDwrite-host “Interface Type: ” $objItem.InterfaceTypewrite-host “Media Type: ” $objItem.MediaTypewrite-host “Model: ” $objItem.Modelwrite-host “Partitions: ” $objItem.Partitionswrite-host “Size: ” $objItem.Sizewrite-host “Status: ” $objItem.Statuswrite-host}}#*=============================================================================#* SCRIPT BODY#*=============================================================================# Create a string variable using the local computer.$strComputer = “.”# Call the “ListProcessor” function.ListProcessor# Call the “ListDisk” function.ListDisk#*=============================================================================#* END OF SCRIPT: [Computer Inventory]#*=============================================================================

Now you have a visual of a modular PowerShell script. I declared the functions and used the “SCRIPT BODY” to snap the functions in place. Let’s say you want to change to order of the script, you want to list the Disk Properties before the Processor Properties. You only need to reverse the order of the function calls in the “SCRIPT BODY” to make this happen.Modular scripting is a great way to organize your scripts. It allows you to build from a user-defined functions library, that you maintain. You can “snap-in” new functionality to existing scripts as needed and easily control the flow of your script without having to move around large chunks of code. Modular scripting may not be the best solution for the example above, the example was provided only to introduce the concept. Again, as your tasks become more complex so do your scripts. With modular scripting, complex scripts become more manageable.

Page 84: PowerShell Tutorials

Dot Source (Calling Scripts and Functions)Essentially, “dot-source” means using dot-notation to call script blocks, functions, and/or aliases from within your script. We’re going to use the same script examples above, but instead of calling the function written within the script, we will use dot-notation to call scripts that exists outside the main script. The syntax used for dot-notation and script-blocks is:.{}

Example 1. Calling a Script from within a ScriptIn the first example, I’m going to be working from the “C:\MyScripts” directory.Step 1. Save the following code as CPU.ps1 in the MyScripts directory:$colItems = get-wmiobject -class “Win32_Processor” -namespace “root\CIMV2″ `-computername $strComputer foreach ($objItem in $colItems) {write-host “Caption: ” $objItem.Captionwrite-host “CPU Status: ” $objItem.CpuStatuswrite-host “Current Clock Speed: ” $objItem.CurrentClockSpeedwrite-host “Device ID: ” $objItem.DeviceIDwrite-host “L2 Cache Size: ” $objItem.L2CacheSizewrite-host “L2 Cache Speed: ” $objItem.L2CacheSpeedwrite-host “Name: ” $objItem.Namewrite-host}

Step 2. Save this code as Disk.ps1:$colItems = get-wmiobject -class “Win32_DiskDrive” -namespace “root\CIMV2″ `-computername $strComputer foreach ($objItem in $colItems) {write-host “Description: ” $objItem.Descriptionwrite-host “Device ID: ” $objItem.DeviceIDwrite-host “Interface Type: ” $objItem.InterfaceTypewrite-host “Media Type: ” $objItem.MediaTypewrite-host “Model: ” $objItem.Modelwrite-host “Partitions: ” $objItem.Partitionswrite-host “Size: ” $objItem.Sizewrite-host “Status: ” $objItem.Statuswrite-host}

Steps 1 and 2 are the same script blocks that we’ve worked with in this PowerShell Article. Now, let’s modify our main script body to use dot-notation to call these scripts.Step3: Modify the main script as follows: Remove the function(s) code from the script and modify the script body to call both CPU.ps1 and Disk.ps1 scripts.#* FileName: ComputerInv_v1.1.ps1#*=============================================================================#* Script Name: [Computer Inventory]

Page 85: PowerShell Tutorials

#* Created: [09/15/2007]#* Author: Jesse Hamrick#* Company: PowerShell Pro!#* Email:#* Web: http://www.powershellpro.com#* Reqrmnts:#* Keywords:#*=============================================================================#* Purpose: Computer Invetory of CPU and Disk Properties#*#*#*============================================================================= #*=============================================================================#* REVISION HISTORY#*=============================================================================#* Date: [10/09/2007]#* Time: [9:30 AM]#* Issue: Dot-Source Example#* Solution:#*#*=============================================================================#*=============================================================================#* SCRIPT BODY#*=============================================================================# Create a string variable using the local computer.$strComputer = “.”# Use Dot-Source to Call the “ListProcessor” function..{.\CPU.ps1}# Use Dot-Source to Call the “ListDisk” function..{.\Disk.ps1}#*=============================================================================#* END OF SCRIPT: [Computer Inventory]#*=============================================================================

Since I’m working from “C:\MyScripts” directory I can use “.\CPU.ps1″ to call the scripts in my code. Run the script:C:MyScripts\ComputerInv_v1.1.ps1<enter>

Page 86: PowerShell Tutorials

This works great if we organize all of our scripts (code library) within the “MyScripts” directory. We can use the System Path to find the .ps1 files. The $PsHome variable provides the installation path of PowerShell. By saving our scripts (code library) to this directory, we only have to call the script name without possible path issues. By default, PowerShell is installed using the following directory path: C:\WINDOWS\system32\WindowsPowerShell\v1.0Example 2.Step 1. Let’s move ComputerInv_v1.1.ps1, CPU.ps1, and Disk.ps1 to the v1.0 directory. Then modify the script body as follows:#* FileName: ComputerInv_v1.1.ps1#*=============================================================================#* Script Name: [Computer Inventory]#* Created: [09/15/2007]#* Author: Jesse Hamrick#* Company: PowerShell Pro!#* Email:#* Web: http://www.powershellpro.com#* Reqrmnts:#* Keywords:#*=============================================================================#* Purpose: Computer Invetory of CPU and Disk Properties#*#*#*============================================================================= #*=============================================================================#* REVISION HISTORY#*=============================================================================#* Date: [10/09/2007]#* Time: [9:30 AM]#* Issue: Dot-Source Example#* Solution:#*#*=============================================================================#*=============================================================================#* SCRIPT BODY#*=============================================================================# Create a string variable using the local computer.$strComputer = “.”

Page 87: PowerShell Tutorials

# Use Dot-Source to Call the “ListProcessor” function..{CPU.ps1}# Use Dot-Source to Call the “ListDisk” function..{Disk.ps1}#*=============================================================================#* END OF SCRIPT: [Computer Inventory]#*=============================================================================

Here is the change in the script body - from .{.\scriptname.ps1} to .{scriptname.ps1}Step 2. With the script files being placed in the PowerShell install directory, we only have to type in the script name in which to run. The system path will find the where the scripts are located and launch them. Let’s launch the Computer Inventory script:C:\MyScripts\ComputerInv_v1.1.ps1<enter>

Now, CD to the root of C: drive and attempt to run the script again:C:\ComputerInv_v1.1.ps1<enter>

Did the script work? It will use the System’s path to find the .ps1 files if necessaryExample 2. Calling a Function from another script file.Using “dot-sourcing” you could create a library of functions. For example, let’s say you have one large file that contains over 100 separate functions you’ve created. Essentially, you maintain your function library in one or two documents. You can use dot sourcing to read the file and call one or more functions written in the file. Click here to find out how…Which process should I use (Modular or Dot Source)?Do I write functions within the script or do I call other scripts outside the main script? There is really no wrong or right here, it depends on the situation. For example, let’s say you are writing a script for a client that will be utilizing functions in your script library. You may wish to use the modular approach so that you can present your client will a single script that is well document. If your writing scripts for you own environment, chances are your using dot sourcing to call other functions as it takes less time and less code to accomplish the task…ConclusionIn this PowerShell Training session we have:

Defined Functions and Filters. Learned how to create and call Functions. Passed arguments to Functions. Introduced the param keyword and the $args variable. Talked about how to define data types. Explained how to set default parameters. Touched on the differences between Functions and Filters. The $input variable and the $_ variable. Examples of using Functions to organize scripts and control script

execution.

Page 88: PowerShell Tutorials

Again, the purpose of this tutorial was the introduction of Functions and Filters and how they can assists with script organization. Functions and Filters provide many uses as we will discover as we progress. These uses will become known throughout the rest of the tutorials.Until next time, happy scripting…tutorials, we will be looking a Functions and more Script Block detail. See you then…

PowerShell Functions and Filters - The basics

PowerShell Tutorial 10: Functions and Filters