Server Automation ToolsDancing Tools

"Software Tools to Maximize Up-time and Automate Functions in Microsoft’s Internet Information Server”


MetaBase 102

In Metabase 101 we took a look at the IIS Metabase and how it stores data. We also (in our examples) looked at some vbscript code to access the metabase. This article will concentrate on the vbscript code and how it can be used to access and change metabase properties.

Any language that uses the ADSI (Active Directory Services Interface) can be used to access the metabase, not just vbscript.

For this article let's use vbscript, it's simple to use, simple to understand, and available to anyone.


TIP: If you want to follow along real-time download and install the MetaBase. You can do that here: http://support.microsoft.com/default.aspx?scid=kb%3ben-us%3b301386#3
(If the URL is dead the Microsoft Knowledge Base Article is- 301386.)
You will also need to install the Scripting host. You can download it from here:
You will also need to install IIS on your server and just make a few Web sites. Any number will do

so long as you have a few to get meaningful data using our vbscript.

Let's start with this simple vbscript. It opens the metabase and lists all the virtual Web sites within it.

' First declare your variables
Dim parent_object 
Dim child_object 
Dim ServerName
Dim allsites 
' Then, set your variables ServerName = "localhost" yourADSIPath = "IIS://" & ServerName & "/W3SVC" Set parent_object = GetObject(yourADSIPath)
' Finally, write your code For each child_object in parent_object If IsNumeric(child_object.Name) then Wscript.echo "Site Index ID: " & child_object.Name & vbTab
& "ServerComment: " & child_object.ServerComment End If Next


And, let's refer to this image of the metabase:



First we'll use the DIM statement to declare the variables. Using the DIM statement sets aside some memory space for each variable defined. And don't forget the Option Explicit statement (see the footnotes).

The variables we are defining are the:

parent_object - this is the main container we will get
child_object - this will hold the values contained in the main container or parent_object
ServerName - this is the computer name the IIS server runs on
allsites - we'll use this one later to concatenate allsites into a pretty output

Dim parent_object 
Dim child_object
Dim ServerName
Dim allsites

Next, let's Set some variables, especially the parent_object, or, let's fill the container we want to work with:

 Then, set your variables
ServerName = "localhost" 
yourADSIPath = "IIS://" & ServerName & "/W3SVC"
Set parent_object = GetObject(yourADSIPath)


First, we'll Set the ServerName. That's just the computer name. "localhost" will work in most cases. If not, replace it with the real computer name. Next, we'll set the yourADISPath. This is the path to your IIS object or container. I like to refer to it as container instead of object. Object tends to scare people. It sounds so technical. We all know and can visualize a container. We Set the yourADSIPath in case we want to use it later in the script so we won't need to type in that long phrase and maybe make mistakes.

This brings us to the most important variable in the script - the parent_object. Easy enough to Set by using the Set statement and assigning the parent_object all the contents of the CONTAINER defined in the GetObject statement. Look at the image above. See the arrow pointing to the index values? These are the values stored in the container: IIS://" & ServerName & "/W3SVC

Now that we've opened the container, let's actually take some stuff out of it. Here's how:

For each child_object in parent_object 
  If IsNumeric(child_object.Name) then 
   Wscript.echo  "Site Index ID: " & child_object.Name & vbTab 
& "ServerComment: " & child_object.ServerComment End If Next


This segment says, "For every item (in this case item refers to Web sites) in the container show me the item's Index value and the item's ServerComment. The ServerComment is within the Index value. (See how the child_object can access not only the item's within the container but the values within the item's themselves. )

The For/Next statement gives the child_object access to the values in the parent_object. Notice how the child_object later refers to the parent_objects values by their real names? Like child_object.name and child_object.ServerComment.

The TIP: It doesn't matter what you call the variables like parent_object or child_object. These aren't rules in any way ground in stone. In our script we could have called them: rat or dog, or cookie jar or anything we wanted. I just like to refer to them in some sort of meaningful way.

Not to get off track, but if we expand the metabase a little more like this:

you can see other parent_objects we can get and manipulate using the child_object.

For example, we could get the:

  • child_object.ServerBindings - we can add/delete/change server bindings or the IP #
  • child_object.ServerState - using this one we could stop and start the site just by changing the value!

Back to the tutorial....

This is the output of the script we just examined. It displays each site one at a time.

If you don't like hitting the enter key at every OK dialog box you could change the output of the script to make it pretty like this:

The code to do this is a simple concatenation of each output line. By simply using a variable and the &, the concatenation operator, we can append each output line to the variable allsites. Here's what the code looks like:

allsites = "Site Index ID: " & child_object.Name & vbTab & "ServerComment: " 
& child_object.ServerComment & vbcrlf & allsites


Place this line somewhere inside the For/Next loop. It doesn't really matter where.

The new script looks like this:

' First, we declare all variables
Dim parent_object 
Dim child_object 
Dim ServerName
Dim allsites 
Dim theObjectToGet
ON ERROR RESUME NEXT
' Next, we set the variables to the contents we like
ServerName = "localhost" 
yourADSIPath = "IIS://" & ServerName & "/W3SVC"
Set Parent_object = GetObject(yourADSIPath)
' Finally, we write the core code
if IsObject(Parent_object) then
    Wscript.echo "Yes " & yourADSIPath & " is an object"
  
    For each child_object in parent_object 
      If IsNumeric(child_object.Name) then
        allsites =  "Site Index ID: " & child_object.Name & vbTab 
& "ServerComment: " & child_object.ServerComment & vbcrlf & allsites 'Wscript.echo "Site Index ID: " & child_object.Name & vbTab
& "ServerComment: " & child_object.ServerComment
End If Next else Wscript.echo "Sorry " & yourADSIPath & " is not an object. Good Bye!" end if 'And then, write the output in a more effecient format. The bonus! Wscript.echo allsites


Ok, I know...there's some new stuff in the script above. The first thing you'll notice is the: ON ERROR RESUME NEXT A couple of things about his line. First, it sets up error handling in the script. It's no good however, unless WE, the programmer(s),handle the errors.

What errors are we handling in this script?

Wait, before we get into that let's look at thesecond new item we see, which is the use of the vbscript function IsObject. This tests the variable defined as an Object - parent_object. If it is not an Object we skip the core code - it won't work anyway. If it is not an Object, we are safe and can continue 'cause we know it will work. Note the last line: Wscript.echo allsites It will resolve to blank since the allsites variable did not get set to anything.

Thethird new item we see is the use of the if/else construct. It's a simple bit of code. The hardest part to understand is the bit that looks like this: if IsObject(Parent_object) This test returns a true if valid and a false if not valid. Basically, it resolves to if TRUE or if FALSE depending on the output of the IsObject function.

Ok, let's contimue with what error(s) we are handling. The IsObject test is the error we want to handle. If we do not specify the ON ERROR RESUME NEXT statement and the yourADSIPath variable defines an incorrect path to an object then the script will blow up with a nasty message that looks like this:

Not good! This will not only end your script but your day or your users day as well.

The ON ERROR RESUME NEXT statement will direct the script to your if/else construct's else statement and the resulting display will look like this:

Oh, a much nicer way to end the day!

The END!

Just a couple of things I wanted to mention but did not want to get off track of the core reason for the article.

 1. The scripts we are working with are meant to be run on the server console or on the server via the task scheduler, not in an ASP page. But, they could easily run in an ASP page with some very minor changes.

2. To define a vbscript page in ASP the page must have <SCRIPT LANGUAGE="VBScript" RUNAT="server"> at the top of the page.

3. Also, you cannot use the Wscript.echo statement to display results in an ASP page...you could but it won't work. You need to substitute Response.write in for Wscript.echo to display results in an ASP page.

4. And you must enclose your script within <% %> tags.

The TIP:  Option Explicit tells vbscript that all the variables defined on the page MUST have been defined by DIM first. Basically, if you want to code sloppy and just place variables anywhere in the page without regard to whether they are even spelled correctly or even being used, then don't use the Option Explicit statement. If you want your vbscript programs to bomb out at compile (run) time and warn you that stuff in the page probably won't work correctly then use the Option Explicit statement.

4. And, very important, when writing scripts that access the metabase, registry or secret spots (i.e., restriced folders) on your Web server you WILL need access permissions to these locations. I won't discuss this stuff in this article but I will in another later.

I hope this tutorial helps you on your way to automating Microsoft's Internet Information Server and furthers your development knowledge in this area.

Thanks,

John Cesta



If you like this article or maybe had a similar experience and would like to share it with other readers then feel free to:
Simply fill in YOUR e-mail address, your name and your comment. Click the SEND button.

After submitting your comment, you will be transported back to the article you commented on!

  Name E-Mail Address
You
Sending to
  Your Message



John Cesta is a contract programmer. John's current project is designer and lead developer of the automated hosting software at bestcfhosting.com, a ColdFusion MX hosting company. John is currently working on commercializing his programs and offering them to the IIS community at serverautomationtools.com