Click to Rate and Give Feedback
Tips
Here is an overview of the new features you can use in the User State Migration Toolkit (USMT) to simplify migration to Windows 7. ...

Read more!

Auditing in Exchange Server offers many options for tracking important information. We show you all of them and how to configure the policy you want in seven simple steps. ...

Read more!

To make replication go smoothly, you need to do a bit of planning, which involves selecting a specific replication model. Here's an overview of the common replication models you will likely choose from. ...

Read more!

In six easy steps, you can configure message delivery options for your organization’s transport servers so that they don’t apply filters to IP addresses from internal servers and your perimeter network ...

Read more!

You can pin files and resources to the Taskbar for easy access to the documents you use most often. Find out how. ...

Read more!

Related Articles

Don Jones concludes his four-part series on automating user provision with Windows PowerShell. In this final edition, Don discusses adding users to domain groups and modifying directory attributes.

Don Jones

TechNet Magazine June 2009

...

Read more!

Don Jones kicks off a four part series that will look at how you can use Windows PowerShell to create a real-world user provisioning script.

Don Jones

TechNet Magazine March 2009

...

Read more!

You need to calculate server downtime in order to report on server uptime. The Scripting Guys have a Windows PowerShell script that can do this for you.

The Microsoft Scripting Guys

TechNet Magazine December 2008

...

Read more!

Discover how to use the Excel.Application automation model for a more powerful way to process data from your servers and take advantage of the analysis and charting tools built into Excel.

The Microsoft Scripting Guys

TechNet Magazine January 2009

...

Read more!

Despite its object oriented nature, Windows PowerShell is also able to parse complicated strings. Don Jones demonstrates how you can do this in Windows PowerShell using Select-String.

Don Jones

TechNet Magazine September 2008

...

Read more!

Also by this Author

Looking for a way to avoid making mistakes? Validation is a good start. Learn how to perform character pattern matching in a script using regular expressions.

The Microsoft Scripting Guys

TechNet Magazine January 2008

...

Read more!

Discover how you can use disconnected recordsets—virtual database tables—to work around VBScript limitations relating to data-sorting and working with large data sets.

The Microsoft Scripting Guys

TechNet Magazine September 2008

...

Read more!

The Microsoft Scripting Guys create a Windows PowerShell script that provides an easy way to back up, archive, and clear your event log files.

The Microsoft Scripting Guys

TechNet Magazine July 2009

...

Read more!

With Windows Vista, the UserAccounts.CommonDialog ActiveX control for opening a file open dialog box no longer exists. Here's a look at how you can solve that problem using Visual Basic Express Edition.

The Microsoft Scripting Guys

TechNet Magazine August 2008

...

Read more!

The Scripting Guys discuss Socrates and revisit the topic of querying an XML file . This time, however, the XML file is structured so that rather than using child nodes, additional property values are configured as attributes.

The Microsoft Scripting Guys

TechNet Magazine October 2008

...

Read more!

Popular Articles

The introduction of Hyper-V makes virtualization an even more compelling solution for IT environments. Get an overview of today’s virtualization market and see how Hyper-V improves the manageability, reliability, and security of virtualization

Rajiv Arunkundram

TechNet Magazine October 2008

...

Read more!

Security principals underlie so much of Windows security that it is essential for any administrator to have at least a basic understanding of how the various types of Security principals work and how they are used. Here's what you need to know.

Jesper M. Johansson

TechNet Magazine January 2009

...

Read more!

Aaron Margosis

TechNet Magazine August 2006

...

Read more!

Virtualization brings significant changes to disaster recovery. Here’s an introduction to how the Microsoft virtualization platform factors into your disaster recovery plan, as well as a deeper look into backup and restore options and considerations for Windows Server 2008 Hyper-V.

Adam Fazio

TechNet Magazine October 2008

...

Read more!

Why do attachment sizes increase when sending and receiving e-mail messages? How can you ensure databases on a passive node in a CCR cluster are defragmented during online maintenance? Can you use an external trust between forests? We answer these questions and more.

Henrik Walther

TechNet Magazine January 2009

...

Read more!

Our Blog

NAP monitors the health of specified computers when they attempt to connect to a network and includes a number of mechanisms to enforce health requirements. In this article, Geek of All Trades Greg Shields gives readers an overview of these enforcement mechanisms and, as an example, takes a closer look at setting ...

Read more!

Use Windows PowerShell to Manage Virtual Machines Here are a few examples of how you can use Windows PowerShell scripts to manage virtual machines running on a Server Core installation. Note that these scripts are presented as samples and may need to be customized to work in your environment.

Create a New ...

Read more!

Disabling an Unused Part of Group Policy Objects One way to disable a policy is to disable an unused part of the GPO. By disabling part of a policy that isn’t used, the application of GPOs and security will be faster.

Administer Windows Server 2008 Server Core from the Command Prompt ...

Read more!

In the August 2008 issue of TechNet Magazine, Paul Randal wrote an article Top Tips for Effective Database Maintenance.  It was geared toward "involuntary  DBAs" (IT pros who inadvertently wind up responsible for a SQL Server instance).  The article had a great response from our readers so Paul has written another ...

Read more!

Microsoft Forefront is designed to deliver an integrated security solution that makes it much easier to deploy and manage security across an organization’s IT infrastructure. In this, our annual security issue, we feature two articles that describe how Forefront Security protects instant messaging and e-mail.

Protect ...

Read more!

Hey, Scripting Guy! The Games Are Afoot! Oh, and Some XML, Too
The Microsoft Scripting Guys

Download the code for this article: HeyScriptingGuy2008_02.exe (151KB)

You know, any time people talk about the legends of the sporting world, the same names inevitably come up: Babe Ruth. Pele. Muhammad Ali. Walter Payton. ScooterK and MrRat. Johnny—
Ha, that's funny, you ... oh, you're serious? You actually don't know who ScooterK and MrRat are? Well, for those of you who obviously don't keep up with the Winter Scripting Games (February 15th through March 3rd at the TechNet Script Center; go to microsoft.com/technet/scriptcenter/funzone/games), ScooterK and MrRat are true legends, competitors who earned perfect scores in at least one division in the 2007 Winter Scripting Games.
And here's the really cool part: can you realistically hope to become a soccer legend like Pele? Probably not. Can you ever hope to become the heavyweight boxing champion of the world? Well, some of the Scripting Guys seem to have the heavyweight part down, but that boxing champion bit is a much tougher nut to crack. But you—yes, you—can very easily become the next ScooterK or the next MrRat.
Note: In theory, you might be able to become the next Babe Ruth, too. All you would have to do is be able to eat 24 hot dogs between games of a baseball doubleheader.
Take it easy; we'll tell you how you can become the next ScooterK or MrRat (and maybe even the next Bizzy or H2Data). All you have to do is show up at the Script Center and take part in the Scripting Games. On February 15th we're going to post 10 different events (10 scripting challenges) and dare you to complete any or all of them. Write a script that solves the problem we pose and e-mail it to the Scripting Guys. (You'll find full instructions at the Scripting Games home page.) We'll test your script and, if it works, award you points. Successfully complete all 10 events and you too will become a legend of the sporting world. Or at least of the scripting sporting world, which is pretty much the same thing.
The Scripting Games (February 15th through March 3rd) are fun and challenging. Best of all, the Scripting Games are for everyone. Are you still somewhat new to system administration scripting? Then enter the Beginners Division; we'll have separate competitions for beginners in VBScript, Windows PowerShellTM, and (new this year) Perl. Do you find the Beginners Division a bit easy? Then you should try the Advanced Division, which also has competitions in VBScript, Windows PowerShell, and Perl.
The Games (did we mention they run from February 15th through March 3rd?) are quite simply the event of the scripting season, and you don't want to miss them. Visit the Script Center home page now for tips and tricks on training for the competition, then come back on February 15th when we officially let the Games begin.
February 15th through March 3rd. Just in case you missed it.
What's that? Actually, we agree with you: coming out with a new Hey, Scripting Guy! column on top of the announcement about the Scripting Games probably is too much excitement for a single month. However, in order to keep the good folks at TechNet Magazine happy (our primary goal in life, needless to say), we decided to risk it and put out a new column anyway.
Exactly one year ago (wow, has it really been that long?), we published a column that explained how you could use a script to read an XML file. What that column didn't tell you was how you could use a script to create, write, and modify an XML file. This month, we're here to right that wrong. You say you'd like to know how to write a script that can create an XML file? All you had to do was ask. Well, ask and then wait a year for us to get around to it. Figure 1 shows the script. Admittedly, this might look complicated, but we'll explain how it all works.
Set xmlDoc = _
  CreateObject("Microsoft.XMLDOM")  
  
Set objRoot = _
  xmlDoc.createElement("ITChecklist")  
xmlDoc.appendChild objRoot  

Set objRecord = _
  xmlDoc.createElement("ComputerAudit") 
objRoot.appendChild objRecord 
  
Set objName = _
  xmlDoc.createElement("ComputerName")  
objName.Text = "atl-ws-001"
objRecord.appendChild objName  

Set objDate = _
  xmlDoc.createElement("AuditDate")  
objDate.Text = Date  
objRecord.appendChild objDate  

Set objIntro = _
  xmlDoc.createProcessingInstruction _
  ("xml","version='1.0'")  
xmlDoc.insertBefore _
  objIntro,xmlDoc.childNodes(0)  

xmlDoc.Save "C:\Scripts\Audits.xml"  

To begin with, we create an instance of the Microsoft.XMLDOM object. As you might have guessed, this is the object that enables us to work with XML files. Our goal is to produce a simple XML file that looks like Figure 2.
Figure 2 Our target: a simple XML file 
To create this XML file, the first thing we need to do is create the root node (ITChecklist). How do we do that? Like this:
Set objRoot = _
  xmlDoc.createElement("ITChecklist")  
xmlDoc.appendChild objRoot  
That was pretty easy, wasn't it? All we had to do was call the createElement method, passing createElement the name we want to give to the root node. We then simply call the appendChild method, passing the object reference to our new element (objRoot) as the sole method parameter. At that point, we have ourselves a root node.
But wait; there's more. Next we create the ComputerAudit node, a child node of the ITChecklist node that represents the information for a single computer. As you can see, the code to create this node is similar to the code used to create the root node:
Set objRecord = _
  xmlDoc.createElement("ComputerAudit") 
objRoot.appendChild objRecord 
The only difference is this: when we created the root node, we called appendChild on our XML document itself. (Note the object reference xmlDoc.) To add a new child node to the root, we call appendChild on the root node (objRoot) rather than the XML document. It's that easy.
It's equally easy to add the ComputerName and AuditDate nodes as child nodes of ComputerAudit. To do that, we're going to go through a similar process: we're going to call createElement to create a new node, and we're going to call appendChild to append this new node to the file.
(Quick quiz: Where do we call appendChild from this time around? Yes, that's right: from objRecord, the parent (ComputerAudit) node we just took the time to create.)
Oh, and because the ComputerName and AuditDate nodes need to contain values, it's important that we also specify a value for the Text property of each of these nodes right before we add them to the document.
That should all become clear once we take a peek at the code that actually creates the ComputerName node:
Set objName = _
  xmlDoc.createElement("ComputerName")  
objName.Text = "atl-ws-001"
objRecord.appendChild objName  
As you might expect, the code for creating AuditDate is almost identical. We just have to specify a different node name when calling createElement and assign a different value to the Text property.
Man, we're making this too easy on everyone, don't you think?
After we finish creating the nodes for our first (and in this case, only) record, we execute this sweet little block of code:
Set objIntro = _
 xmlDoc.createProcessingInstruction _
  ("xml","version='1.0'")  
xmlDoc.insertBefore _
  objIntro,xmlDoc.childNodes(0)  
That simply inserts the <?xml version="1.0" ?> tag at the beginning of the file, ensuring that we have a well-formed XML document.
At that point, all we have left to do is call the Save method and save our new file as C:\Scripts\Audits.xml:
xmlDoc.Save "C:\Scripts\Audits.xml"  
Just like that, we have a brand-new XML document.
Now, that's actually pretty useful: you now know how to create a brand-new XML file using a script. Of course, the odds are pretty good that most of the time you don't really need to create a brand-new XML file; instead, you simply need to append new data to an existing file. So will the Scripting Guys show everyone how to do that?
You know, originally we decided that the answer to that question would be no, we wouldn't show everyone how to append data to an existing XML file. And then, being kind-hearted and generous people, we decided to try and strike a deal with the readers of TechNet Magazine: if everyone reading this magazine agrees to enter the 2008 Winter Scripting Games, then, in return, we'll show you all how to use a script to append data to an XML file. So, does everyone agree to enter the Scripting Games?
Um, we're waiting on you. Yes, you—the guy in Rochester, MN.
There, that's more like it. And trust us, you'll have a good time during the Scripting Games; everyone always does. We promise.
And now, seeing as how a deal's a deal, we'll show you a script that can append data to an existing XML file. Just take a look at Figure 3.
Set xmlDoc = _
  CreateObject("Microsoft.XMLDOM")

xmlDoc.Async = "False"
xmlDoc.Load("C:\Scripts\Audits.xml")

Set objRoot = xmlDoc.documentElement
  
Set objRecord = _
  xmlDoc.createElement("ComputerAudit")
objRoot.appendChild objRecord

Set objFieldValue = _
  xmlDoc.createElement("ComputerName")
objFieldValue.Text = "atl-ws-100"
objRecord.appendChild objFieldValue

Set objFieldValue = _
  xmlDoc.createElement("AuditDate")
objFieldValue.Text = Date
objRecord.appendChild objFieldValue
  
xmlDoc.Save "C:\Scripts\Audits.xml"  

As you can see, this isn't too terribly different from the script that created the XML file. We start out by creating an instance of the Microsoft.XMLDOM object, then setting the Async property to False, which tells the script that we want to load the document synchronously rather than asynchronously. What difference does that make? Well, if we loaded the document asynchronously, the script would be free to continue even though the document was not fully loaded. Needless to say, trouble can arise in a hurry if you try to perform a task on a document that doesn't exist yet. By ensuring that our XML file loads synchronously, we also ensure that the file will be fully loaded before our script proceeds.
Speaking of fully loaded—well, never mind; we'll just let that one go. Instead, we call the Load method to open the file C:\Scripts\Audits.xml. As soon as the file is open, we use this line of code to create an instance of the documentElement class, which has the net effect of binding us to the document root. In this case, of course, that's the ITChecklist node:
Set objRoot = xmlDoc.documentElement
It's all downhill from that point. We create a new instance of the ComputerAudit node, using the appendChild method to add that new node to the file. We then create new instances of the ComputerName and AuditDate nodes, specifying the appropriate values (atl-ws-100 and the current date, respectively) for each new node. We tuck these two items inside the new ComputerAudit node we just created, call the Save method to save the file, and then happily go back to working on our scripts for the upcoming Scripting Games.
Which, in case we didn't mention it, are scheduled for February 15th through March 3rd at the TechNet Script Center.
So far, so good. We can create a new XML file, and we can add new records to that file. That's all pretty cool, but we still have a ways to go; for example, how do we modify existing records in the file? Well, here's at least one way to do that, as shown in Figure 4.
Set xmlDoc = _
  CreateObject("Microsoft.XMLDOM")

xmlDoc.Async = "False"
xmlDoc.Load("C:\Scripts\Audits.xml")

Set colNodes=xmlDoc.selectNodes _
  ("/ITChecklist/ComputerAudit " & _
   "[ComputerName = 'atl-ws-100']/AuditDate")

For Each objNode in colNodes
   objNode.Text = Date
Next
  
xmlDoc.Save "C:\Scripts\Audits.xml"  

The important part of this script occurs when we call the selectNodes method, a method that determines which records our query will return. As you can see, when we called selectNodes we were careful to specify two criteria: we only want records where the ComputerName attribute is equal to atl-ws-100, and we only want to get back the AuditDate attribute.
Note: You say you can't see how that works? Then take a look at our first article on working with XML files (technetmagazine.com/issues/2007/02/HeyScriptingGuy); the selectNodes query syntax is explained in more detail there.
As it is wont to do, selectNodes returns a collection of all the XML records that meet the specified criteria. In turn, that means we can update the value of the AuditDate attribute (the only attribute we asked for) simply by setting up a For Each loop to walk through all the items in the collection and then, within that loop, assigning a new value to AuditDate:
For Each objNode in colNodes
   objNode.Text = Date
Next
What's that? You're wondering if we could modify more than one attribute at a time? Yes, we could. But sadly, not today; that's something we'll have to address in a future column.
You say you have another question: How would you update the audit date for all the computers in the file? That's easy; you'd use the script in Figure 5.
Set xmlDoc = _
  CreateObject("Microsoft.XMLDOM")

xmlDoc.Async = "False"
xmlDoc.Load("C:\Scripts\Audits.xml")

Set colNodes=xmlDoc.selectNodes _
  ("/ITChecklist/ComputerAudit/AuditDate")

For Each objNode in colNodes
   objNode.Text = Date
Next
  
xmlDoc.Save "C:\Scripts\Audits.xml"

The only difference between this script and our previous XML-modifying script? With this one we didn't specify that we only wanted to view those records where the ComputerName was equal to atl-ws-100. By leaving out that criteria, we get back all the records by default.
Let's take a look at one last script before we go. Suppose our old pal atl-ws-100 has played its last game of solitaire and has shuffled off to that great computer graveyard in the sky.
Theological note: So where do computers go when they die? As it turns out, they're usually given to one of the Scripting Guys. For example, the Scripting Guy who writes this column was once given a laptop computer because, "You do a lot of good things for Microsoft, and you really should have a laptop computer." The only downside to this generous offering? The computer was broken and couldn't actually be turned on. Which was probably just as well. As it turned out, it didn't have a hard disk either.
In order to complete the great circle of silicon life, we need to delete atl-ws-100 from our XML file. How are we going to do that? Check out Figure 6.
Set xmlDoc = _
  CreateObject("Microsoft.XMLDOM")

xmlDoc.Async = "False"
xmlDoc.Load("C:\Scripts\Audits.xml")

Set colNodes=xmlDoc.selectNodes _
  ("/ITChecklist/ComputerAudit " & _
   "[ComputerName = 'atl-ws-100']")

For Each objNode in colNodes
  xmlDoc.documentElement.removeChild _
    (objNode)
Next
  
xmlDoc.Save "C:\Scripts\Audits.xml"  

As you can see, this resembles our previous script, the one that modified the AuditDate property. There're really only two differences here. For one, notice that we didn't bother to specify any property values in our selectNodes query; when we do that, we get back the entire XML record for atl-ws-100:
Set colNodes=xmlDoc.selectNodes _
  ("/ITChecklist/ComputerAudit " & _
   "[ComputerName = 'atl-ws-100']")
And then, within our For Each loop, we simply call the removeChild method to delete all the records where the ComputerName is equal to atl-ws-100:
xmlDoc.documentElement.removeChild _
  (objNode)
And that's it. Farewell, atl-ws-100; we hardly knew ye.
OK, any TechNet Magazine editors still reading this month's column? You say they've all gone off to try the monthly scripting puzzle? Excellent. Now that no one's reading over our shoulders, we can tell you this: drop whatever you're doing (like, say, reading this magazine) and get on over to the Script Center and start preparing for the Scripting Games. After all, TechNet Magazine will be here for a long time to come. But the Scripting Games are only here once a year, and for a limited time at that (specifically, from February 15th through March 3rd, just so you know). Don't miss out!
Note: You know, now that you mention it, we did wait until you'd read our entire column before we told you to stop reading TechNet Magazine, didn't we? Wonder how that happened ...

Dr. Scripto's Scripting Perplexer
The monthly challenge that tests not only your puzzle-solving skills, but also your scripting skills.

February 2008: Mystery Symbols
The computer keyboard includes all sorts of crazy-looking characters; even crazier is the fact that most of these characters have a specific use in the scripting languages VBScript or Windows PowerShell. See if you can match each symbol with its scripting use. The first one has been done for you.


Show Answer
  


The Microsoft Scripting Guys work for—well, are employed by—Microsoft. When not playing/coaching/watching baseball (and various other activities), they run the TechNet Script Center. Check it out at www.scriptingguys.com.
© 2008 Microsoft Corporation and CMP Media, LLC. All rights reserved; reproduction in part or in whole without permission is prohibited.
Page view tracker