Windows Running Windows PowerShell Scripts Against Multiple Computers

6
Windows PowerShell Tip of the Week 17 out of 20 rated this helpful Here’s a quick tip on working with Windows PowerShell. These are published every week for as long as we can come up with new tips. If you have a tip you’d like us to share or a question about how to do something, let us know. Find more tips in the Windows PowerShell Tip of the Week archive. Running Windows PowerShell Scripts Against Multiple Computers If there’s a problem with the Script Center – wait a minute, who said there was a problem with the Script Center? Boy, if we ever get our hands on that guy we’ll …. Um, as we were saying, if there’s a problem with the Script Center it’s the fact that our scripts are almost all designed to be run against one computer at a time. That was actually done on purpose: because we are an educational site, we try to keep our scripts as simple as we can. Our concern is that, if we start to randomly toss in the code required to get a script to run against multiple machines, we run the risk of needlessly complicating and confusing matters. Therefore, we tend to keep our scripts short and sweet. Yes, just like the Scripting Guys. Of course, in real life things aren’t so simple; system administrators (that is, people who actually use scripts, as opposed to simply writing about them) need to manage multiple machines. As you might expect then, rarely does a day go by that the Scripting Guys don’t get at least one email that begins, “I really like your script that does X. But how can I get that script to run against multiple computers?” In response to those questions, we posted our Remote/Multiple Computer Templates, templates that VBScript users can use as the foundation for a VBScript script that runs against multiple computers. That’s nice, but how do those templates help Windows PowerShell users? Well, to be honest, they don’t. (Although we’ll see if we can create some similar templates for Windows PowerShell users.) But don’t despair, PowerShell users; we haven’t forgotten about you. In fact, this week – and next – we’ll show you different ways to get a script to run against multiple computers. This week we’ll show you how to supply multiple computer names as command-line arguments; how to read computer names from a text file; and, as a bonus, how to repeatedly prompt a user to enter a computer name. Next week – well, who knows what we’ll do next week? But you can bet we’ll have such tasks as reading computer names from an Excel spreadsheet and running a script against all the computers in an OU. But first things first. Top of page Using Command-Line Arguments Let’s take a look at one of the “classic” ways to run a script against multiple computers: by supplying computer

Transcript of Windows Running Windows PowerShell Scripts Against Multiple Computers

Windows PowerShell Tip of the Week17 out of 20 rated this helpful

Here’s a quick tip on working with Windows PowerShell. These are published every week for as long as we can

come up with new tips. If you have a tip you’d like us to share or a question about how to do something, let us

know.

Find more tips in the Windows PowerShell Tip of the Week archive.

Running Windows PowerShell Scripts Against Multiple Computers

If there’s a problem with the Script Center – wait a minute, who said there was a problem with the Script

Center? Boy, if we ever get our hands on that guy we’ll ….

Um, as we were saying, if there’s a problem with the Script Center it’s the fact that our scripts are almost all

designed to be run against one computer at a time. That was actually done on purpose: because we are an

educational site, we try to keep our scripts as simple as we can. Our concern is that, if we start to randomly

toss in the code required to get a script to run against multiple machines, we run the risk of needlessly

complicating and confusing matters. Therefore, we tend to keep our scripts short and sweet.

Yes, just like the Scripting Guys.

Of course, in real life things aren’t so simple; system administrators (that is, people who actually use scripts, as

opposed to simply writing about them) need to manage multiple machines. As you might expect then, rarely

does a day go by that the Scripting Guys don’t get at least one email that begins, “I really like your script that

does X. But how can I get that script to run against multiple computers?”

In response to those questions, we posted our Remote/Multiple Computer Templates, templates that

VBScript users can use as the foundation for a VBScript script that runs against multiple computers. That’s nice,

but how do those templates help Windows PowerShell users?

Well, to be honest, they don’t. (Although we’ll see if we can create some similar templates for Windows

PowerShell users.) But don’t despair, PowerShell users; we haven’t forgotten about you. In fact, this week – and

next – we’ll show you different ways to get a script to run against multiple computers. This week we’ll show you

how to supply multiple computer names as command-line arguments; how to read computer names from a

text file; and, as a bonus, how to repeatedly prompt a user to enter a computer name. Next week – well, who

knows what we’ll do next week? But you can bet we’ll have such tasks as reading computer names from an

Excel spreadsheet and running a script against all the computers in an OU.

But first things first.

Top of page

Using Command-Line Arguments

Let’s take a look at one of the “classic” ways to run a script against multiple computers: by supplying computer

names as command-line arguments. For example, suppose we have a simple WMI script that retrieves BIOS

information from a computer (or computers). In that case, we might start the script using a command similar to

this:

That’s pretty cool, isn’t it? Except for one thing: how do we grab those command-line arguments and use them

within the script?

Well, here’s one way to do that:

You’re right: this is remarkably simple, isn’t it? By default, any command-line arguments supplied to a Windows

PowerShell script are automatically placed into a special variable named $args. That means that the moment

we run our sample command $args will be equal to this:

atl-fs-01

atl-fs-02

That was pretty easy. After all, we didn’t even have to do anything; like we said, our command-line arguments

were automatically tucked away into $args for us. That’s good. Now here’s something even better: to access,

and make us of, those arguments, all we need to do is set up a very basic foreach loop, one that cycles

through each item in the $args collection:

As you can see, we’re simply looping through the $args collection, using $i as our loop variable. (Note that the

loop conditions are enclosed in parentheses.) And then, inside curly braces, we call the Get-WMIObject

cmdlet, passing two parameters:

Win32_BIOS, the name of the WMI class we want to retrieve information from.

The –computername parameter, followed by the name of the computer we want to run the script

bios.ps1 atl-fs-01 atl-fs-02

foreach ($i in $args)

{Get-WMIObject Win32_BIOS -computername $i}

foreach ($i in $args)

against. In this case, the name of the computer is represented by the loop variable $i.

What’s that going to give us? That’s going to give us output similar to this:

Not bad, except for one problem; how are we supposed to know which computer is which?

Good question. But, again, don’t despair; here’s one way to fix that. Just change the script block so that it looks

like this:

All we’ve done here is add a couple of things to our foreach script block. Before we call Get-WMIObject we’re

echoing back:

The name of the computer (stored in the loop variable $i).

A carriage return-linefeed (stored in the “escape sequence” `n).

A series of equals signs.

In turn, that gives us output that looks like this:

SMBIOSBIOSVersion : 68DTT Ver. F.0F

Manufacturer : Hewlett-Packard

Name : EPP runtime BIOS - Version 1.1

SerialNumber :

Version : HP - 15060620

SMBIOSBIOSVersion : 70DTT Ver. E.0A

Manufacturer : Hewlett-Packard

Name : EPP runtime BIOS - Version 1.2

SerialNumber :

Version : HP - 16060624

{$i + "n" + "=========================="; Get-WMIObject Win32_BIOS -computername $i}

atl-fs-01

==========================

SMBIOSBIOSVersion : 68DTT Ver. F.0F

Manufacturer : Hewlett-Packard

Name : EPP runtime BIOS - Version 1.1

This time around, even a Scripting Guy can tell which BIOS information belongs to which computer.

And yes, PowerShell being PowerShell, we could have created a single string rather than concatenating three

separating strings. In other words, we could have done this:

We just thought that the concatenation might be a little easier for people to understand.

Top of page

Reading Computer Names From a Text File

OK, so what about reading in computer names from a text file? For example, suppose you have a text file

(C:\Scripts\Test.txt) that looks like this:

How do we get a script to run against each of the computers listed in this text file? Why, like this, of course:

SerialNumber :

Version : HP - 15060620

atl-fs-02

==========================

SMBIOSBIOSVersion : 70DTT Ver. E.0A

Manufacturer : Hewlett-Packard

Name : EPP runtime BIOS - Version 1.2

SerialNumber :

Version : HP - 16060624

{"$in=========================="; Get-WMIObject Win32_BIOS -computername $i}

atl-fs-01

atl-fs-02

atl-fs-03

atl-fs-04

atl-fs-05

$a = Get-Content "C:\Scripts\Test.txt"

foreach ($i in $a)

{$i + "n" + "=========================="; Get-WMIObject Win32_BIOS -computername $i}

Again, there’s not much to this script. In line 1, we simply use the Get-Content cmdlet to read the contents of

the text file and store that information in a variable named $a. When Get-Content stores information in a

variable, that information is stored as an array, with each line in the text file becoming a separate item in the

array. And because each line in our text file just happens to be the name of a computer, we now have an array

($a) containing the name of each computer we want to run the script against.

The rest is very similar to the first script we showed you. We set up a foreach loop that, in this case, loops

through the values in the array $a. And what do we do with each of those values? The same thing we did in the

first script: we use the Get-WMIObject to retrieve information about the BIOS installed on that computer.

It’s that simple. As an extra special bonus, this is also how you could hardcode computer names in the script

and then run that script against all those computers. Remember how, in line 1, we created an array by reading

in lines from a text file? Well, alternatively, we could manually create that array. In that case, our script would

look like this:

You know, this is almost too easy.

Note. Don’t worry; we said “almost.”

Incidentally, for you diehard Windows PowerShell users, those users who like to employ the minimum number

of keystrokes, this modified version of the script will do the same thing:

The only difference here is that instead of using the Get-Content cmdlet to read in the contents and store that

information in a variable, we’re simply placing the Get-Content command directly in the foreach loop.

And yes, Windows PowerShell allows you to do things like that. Pretty slick, huh?

$a = "atl-fs-01", "atl-fs-02", "atl-fs-03", "atl-fs-04", "atl-fs-05"

foreach ($i in $a)

{$i + "n" + "=========================="; Get-WMIObject Win32_BIOS -computername $i}

foreach ($i in Get-Content "C:\Scripts\Test.txt")

{$i + "n" + "=========================="; get-wmiobject win32_bios -computername $i}

Did you find this helpful?

Top of page

Prompting the User to Enter a Computer Name

Let’s do one more before we call it a day. Here’s a script that repeatedly prompts the user to enter a computer

name. After the user enters the name and presses ENTER, the script uses Get-WMIObject to retrieve BIOS

information for that machine. It then prompts the user to enter the name of another computer; this continues

until the user presses ENTER without entering a computer name.

Here’s what the script looks like:

As you can see, we start off by setting up a do while loop that runs as long as (while) the variable $a is not

equal to (-ne) an empty string. Inside the loop, we start off by calling the Read-Host cmdlet, displaying the

message “Please enter a computer name” and storing the user input in the variable $a. Read-Host prompts a

user for input, then sits patiently until the user finishes typing and presses ENTER.

From there we set up an if statement that checks the value of $a. As long as $a is not an empty string, the

script will retrieve the BIOS information from the computer whose name was just entered. Once that’s done we

swing back to the top of the loop and repeat the process, asking the user to enter another computer name.

That’s all we have time for this week. See you next week for yet another exciting Windows PowerShell tip.

Top of page

© 2014 Microsoft. All rights reserved.

do

{

$a = Read-Host "Please enter the computer name"

if ($a -ne "")

{$a + "n" + "=========================="; Get-WMIObject Win32_BIOS -computername $a}

}

while ($a -ne "")

Yes No