Getting - or Creating - an Object

By The Microsoft Scripting Guys

Sesame Script

Welcome to Sesame Script, the column for beginning script writers. The goal of this column is to teach the very basics of Windows scripting for system administration automation. We’ll provide you with the information you’ll need to begin reading and understanding scripts and to start modifying those scripts to suit your own needs. If there’s anything in particular about scripting you’re finding confusing, let us know; you’re probably not alone.

Check the Sesame Script Archives to see past articles.

On This Page

Getting - or Creating - an Object
The Four Object Creators
CreateObject vs. GetObject
VBScript CreateObject
VBScript GetObject
Retrieving Information from the WMI Service
VBScript vs. WSH
Mystery Solved

Getting - or Creating - an Object

The mysteries of the universe seem endless. How were the great pyramids of Egypt created? Where do crop circles really come from? How many licks does it take to get to the Tootsie Roll center of a Tootsie Pop? One of the great mysteries of scripting is how object references are created. Do we use GetObject or CreateObject? What’s the difference between the two? There are plenty of hypotheses surrounding these other, non-scripting, mysteries (for instance, a lot of people think they’ve solved the Tootsie Pop mystery), but today we really are going to shed light on the great scripting mystery, and the truth will be revealed.

Before we go any further, we should warn you that, because this is Sesame Script, you’re probably expecting information for beginners. However, this particular article is a first look at some concepts that are a little more advanced. For example, before you can begin to understand how to create object references, you need to understand what an object reference is. But don’t worry, we talked about that in another article, “Class is in Session,” so you can go read that article first then come back here for the grand unveiling. Don’t worry, we’ll stay right here and wait for you.

The Four Object Creators

There are four methods available for creating object references: CreateObject, GetObject, CreateObject, and GetObject. No, that’s not a mistake. (The Scripting Guys make a mistake? Never! Well, okay, sometimes - but not in this case.) That really is four methods, and not just two methods repeated. Two of these methods are VBScript methods and two are Windows Script Host (WSH) methods:

VBScript

CreateObject(servername.typename [, location])

GetObject([pathname] [, class])

WSH

object.CreateObject(strProgID[,strPrefix])

object.GetObject(strPathname [,strProgID], [strPrefix])

Now, you could slog through the VBScript and WSH Language References and painstakingly try to figure out how to use these methods. Or you could continue to read and we’ll explain everything you really need to know to distinguish between all these. (If you still want to understand what’s happening in the Language References, read “How to Read an SDK.”)

CreateObject vs. GetObject

We’ll talk in more detail later about the differences between the VBScript and the WSH versions of these objects. For now, we’re going to focus on the VBScript versions, because that’s what you’ll be using most of the time. What’s most important here is to understand the difference between CreateObject and GetObject, and why you sometimes need to use one and sometimes the other.

VBScript CreateObject

You use CreateObject when you want to create a new instance of an object. For example, if you want to start up a new instance of Excel, you’d create an object reference like this:

Set objExcel = CreateObject("Excel.Application")

You now have an object reference to an instance of Excel, and you can use that object reference to call methods and properties that will manipulate Excel. Just to prove it, here’s a script that uses CreateObject to create an instance of Excel, then uses that object to make Excel visible on the screen and add a new workbook:

Set objExcel = CreateObject("Excel.Application")
objExcel.Visible = True
Set objWorkbook = objExcel.Workbooks.Add

Here’s a script that creates two separate instances of Excel:

Set objExcel = CreateObject("Excel.Application")
objExcel.Visible = True
Set objWorkbook = objExcel.Workbooks.Add

Set objExcel2 = CreateObject("Excel.Application")
objExcel2.Visible = True
Set objWorkbook = objExcel2.Workbooks.Add

Run this script and you’ll see two instances of Excel open on your desktop. You can control each one separately within your script based on the variables we used to hold the object references: objExcel and objExcel2.

VBScript GetObject

Now that we know we can create an object by calling CreateObject, why would we need to use GetObject? Can we use it in place of CreateObject?

Set objExcel = GetObject("Excel.Application")
objExcel.Visible = True

If you try running this script, you’ll discover that the answer is no, you can’t just use GetObject in place of CreateObject. You’ll know this is the answer when you receive the error “Invalid syntax.” That’s a pretty good clue.

The purpose of GetObject is to retrieve a reference to an object that’s already running. So you might be thinking that if you can create an object reference to Excel by calling CreateObject then you can create another object reference to that same instance of Excel by calling GetObject, like this:

Set objExcel = CreateObject("Excel.Application")
objExcel.Visible = True
Set objWorkbook = objExcel.Workbooks.Add

Set objExcel2 = GetObject("Excel.Application")

Well, almost. That code doesn’t work, but you’ll find that this does:

Set objExcel = CreateObject("Excel.Application")
objExcel.Visible = True
Set objWorkbook = objExcel.Workbooks.Add

Set objExcel2 = GetObject(, "Excel.Application")
Set objWorkbook = objExcel2.Workbooks(1)
Set objWorksheet = objWorkbook.Worksheets(1)
objExcel2.Cells(1, 1).Value = 11

You’ll notice that we skipped the first parameter and used only the second parameter to refer to Excel.Application. Other than that, it still seems to work a lot like CreateObject, and just as we’d expect. So what’s the problem? Actually, there are a couple of problems. For starters, we can’t come up with a good reason why you would do this. You already have an object reference to Excel, why do you need another one? And even if you did want another, rather than using GetObject you could simply do this:

Set objExcel2 = objExcel

Now you have two variables that reference the same object, and you didn’t have to call any methods at all. And, really, this second option is better anyway because at least you know which instance of Excel you’ll be getting. Suppose you have three instances of Excel running and you run this script:

Set objExcel2 = GetObject(, "Excel.Application")
Set objWorkbook = objExcel2.Workbooks(1)
Set objWorksheet = objWorkbook.Worksheets(1)
objExcel2.Cells(1, 1).Value = 11

Which instance of Excel did you just change? There’s no way to tell.

So let’s just make our lives simple, avoid a lot of headaches, and say that, in all but the most extreme cases, use CreateObject to create object references. Except…

Yes, there are always exceptions. The main exceptions are Windows Management Instrumentation (WMI) and Active Directory Service Interfaces (ADSI). We’ll focus on WMI here, but everything we say is also true of ADSI.

The main difference between the way WMI works and the way an application such as Excel works is that WMI is always running. Even if you stop the WMI service, as soon as you try to access it, it will automatically start again. So if the computer is on, WMI objects are available. For that reason, you don’t need to create objects, they already exist. You only have to get them - with GetObject.

Here’s an example of using GetObject to retrieve a reference to a WMI object:

Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")

The parameter we pass to GetObject is really composed of three parts: winmgmts (a moniker for the SWbemServices object, which represents the WMI service), the name of the computer we’re accessing (a dot . represents the local computer), and the namespace within WMI you want to access (in this case root\cimv2). For this reason, in most scripts you’ll see the call made like this:

strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")

Separating out the computer name into a variable allows you to easily change the name of the computer you’re accessing.

Yes, we know, this is getting more confusing by the minute. WMI service, namespace…what is all this? Well, you probably know what a service is. There’s the Alerter service, the Event Log service, the Messenger service, and so on. And of course there’s also the WMI service. Namespaces are just of way of organizing objects. Most WMI objects you’ll use will be in the root\cimv2 namespace.

Note: To see the different namespaces and the different objects associated with them, download the Scriptomatic.

Retrieving Information from the WMI Service

Now that we have a reference to the WMI service we can query for the particular WMI object we’re looking for by calling either the Get method or the ExecQuery method on the service (the SWbemServices object). Here’s an example that uses the Get method to return an object reference to the Win32_LogicalDisk object with a DeviceID of C::

strComputer = "."

Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set objLogicalDisk = objWMIService.Get("Win32_LogicalDisk.DeviceID='c:'")

If you want to retrieve a collection of objects, or retrieve objects based on multiple criteria, you use ExecQuery. Here’s an example that, again, uses the Win32_LogicalDisk object, but in this case we want all the Win32_LogicalDisk objects:

strComputer = "."

Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")

Set colDrives = objWMIService.ExecQuery _
    ("Select * From Win32_LogicalDisk")

For Each objDrive in colDrives
    Wscript.Echo "Drive letter: " & objDrive.DeviceID
    Wscript.Echo "Network path: " & objDrive.ProviderName
Next

If we had used the Get method in this case rather than ExecQuery, Get would have returned the first network drive it encountered and returned an object reference to that drive. If you have more than one network drive you have no way of knowing which will be returned. By using ExecQuery, you return all of them. (To read details on how the rest of this script works, see this Hey, Scripting Guy! article.)

VBScript vs. WSH

We’re not going to talk a lot about the difference between the VBScript methods and the identically-named WSH methods because as we mentioned, most of the time you’ll use the VBScript methods like we just showed you.

The one obvious difference between the two is that if you use the WSH version of either the CreateObject or GetObject method you need to precede the method name with Wscript, like this:

Set objExcel = Wscript.CreateObject("Excel.Application")

You might have noticed that everything else in this statement looks exactly like the VBScript version. The surprise is that it works exactly the same, too. The difference only becomes apparent when you decide to use a second parameter:

Set objExcel = CreateObject("Excel.Application", "atl-ws-01")
Set objExcel = Wscript.CreateObject("Excel.Application", "Sub")

The first example uses the VBScript CreateObject method. The second parameter designates a machine name against which you want to run the script. The second example is the WSH version, and the second parameter is a subroutine prefix. We’re not going to go into detail on any of this because these parameters don’t always behave as expected, and you’ll rarely use them. Offhand we can’t think of very many examples out of the thousands of scripts on the Script Center that require the use of these additional parameters. (Although the Tales from the Script column I’ll Get You My Pretty …. And We’ll Manage Windows Update, Too! does discuss how you can use VBScript’s second parameter to manage the Windows Update service on a remote computer.)

More Information

WSH - Using COM Objects

VBScript - Connecting to Objects

Eric Lippert’s Blog - What’s the Difference between Wscript.CreateObject, Server.CreateObject, and CreateObject?

Mystery Solved

We know that was a little confusing, and it was sort of a long-winded version of this: Use GetObject for WMI and ADSI, use CreateObject for just about everything else.

As with most rules there are exceptions, but they’re few and far between. Now maybe we’ll get to work on those Tootsie Pops.