What’s the Difference between WScript.CreateObject, Server.CreateObject and CreateObject?

A reader asked me last week

I have always used Server.CreateObject in ASP scripts and WScript.CreateObject in WSH scripts, because I was unable to find any *convincing* information on the subject and therefore assumed that they were there to be used, and were in some way beneficial… but perhaps they’re not?!

What exactly is the reasoning behind having additional CreateObjectmethods in ASP and WSH when VBScript already has CreateObject and JScript already has new ActiveXObject ?  (new ActiveXObject is for all intents and purposes identical to CreateObject, so I’ll just talk about VBScript’s CreateObject for the rest of this article.)  There are two reasons:

1)     VBScript and JScript aren’t the only game in town.  What if there is a third party language which (inexplicably) lacks the ability to create ActiveX objects?  It would be nice to be able to create objects in such a language, thus the hosts expose said ability on their object models.  (Similarly, IE, WSH and ASP all have “static” object tags as well.) 

Of course, this is a pretty silly reason.  First off, no such language comes to mind, and second, why stop at object creation?  A language might not have a method that concatenates strings, but that doesn’t mean that we should add one to WSH just because it comes in handy.  We need a better justification.

2)     The ASP and WSH versions of CreateObject are subtly different than the VBScript/JScript versions because they have more information about the host than the language engine posesses.  The differences are as follows:

WScript.CreateObject with one argument is pretty much identical to CreateObject with one argument.  But with two arguments, they’re completely different.  The second argument to CreateObject creates an object on a remote server via DCOM.  The second argument to WScript.CreateObject creates a local object and hooks up its event handlers. 

Sub Bar_Frobbed()
WScript.Echo “Help, I’ve been frobbed!”
End Sub
Set foo = CreateObject(“Renuberator”, “Accounting”)
Set bar = WScript.CreateObject(“Frobnicator”, “Bar_”)

This creates a renuberator on the accounting server, a frobnicator on the local machine, and hooks up the frobnicator’s events to functions that begin with the particular prefix.

Remember, in the script engine model the control over how event binding works is controlled by the host, not by the language.  Both IE and WSH have quite goofy event binding mechanisms for dynamically hooked up events — IE uses a single-cast delegate model, WSH uses this weird thing with the string prefixes. 

Server.CreateObject creates the object in a particular context, which is important when you are creating transactable objects.  Windows Script Components, for example, are transactable objects.  This means that, among other things, you can access the server object model directly from a WSC created with Server.CreateObject , because the object obtains the server context when it is created.  Ordinary CreateObject has no idea what the current page context is, so it is unable to create transactable objects. There are many interesting facets of transactable objects which I know very little about, such as how statefulness and transactability interact, how the object lifetime works and so on. Find someone who writes a blog on advanced ASP techniques and ask them how it works, because I sure don’t know.

I’ll answer the question “what’s the difference between WScript.CreateObject and WScript.ConnectObject?” in a later blog entry.

I answered the question “What’s the difference between GetObject and CreateObject ?” in this blog entry.


Comments (21)

  1. Mike Dimmick says:

    The business with the context is probably something to do with MTS or COM+. I’m not entirely clear on this – and I’ve read Tim Ewald’s "Transactional COM+".

    It left me with a strong feeling of knowing the what and how, but still a bit hazy on the why and when.

    If on Windows 2000 or later (if not, why not??) ASP uses COM+ services for context, which loads any new object into the context for the page, so long as the COM+ configuration for the new object is compatible. On NT 4.0, MTS is used instead – COM on NT 4.0 is totally ignorant of context (hence CreateObject cannot create an object which needs a context).

    One of the factors in being able to reuse the caller’s context is whether you’re in the same apartment. According to Ewald, ASP runs your page code in an STA; if your component is marked ‘Free’, it will load in the MTA and cannot inherit the page’s context.

    A post on the Wrox asp_xml mailing list (archived at http://p2p.wrox.com/archive/asp_xml/2001-05/47.asp) suggests that for Windows 2000 and later, there’s no difference.

  2. Kim Gräsman says:

    "Server.CreateObject creates the object in a particular context"

    Adding to this, before the whole context and IIS intrinsic business was finished, Server.CreateObject only did:

    – QueryInterface for IDispatch

    – GetIDsOfNames for "OnStartPage"

    – If method found, call it, and pass in an implementation of IScriptingContext, so that the object could access the ASP intrinsics

    – If method not found, don’t bother

    This also implies that ASP holds a reference to each object where OnStartPage is implemented, so it can call OnEndPage at the end of the request.



  3. Andrew Clinick says:

    Wscript.createobject also allows you to hook up events to the object since it’s added as a named item to the script engine. http://msdn.microsoft.com/library/default.asp?url=/library/en-us/script56/html/wsmthconnectobject.asp has the details

  4. Eric Lippert says:

    Not quite. WS.CreateObject does NOT add the object as a named item and then use the named item connection mechanism.

    Rather, it walks the coclass typeinfo of the newly created object, searches it for events, and then hooks those events up to methods in the script engine namespace that match the right pattern.

    The point is that its the HOST which does the binding, not the ENGINE. The engine can only bind to named items.

  5. Andrew Clinick says:

    Ah yes it’s all coming back to me now. I remember much anglo-saxon remarks about connectobject when we took over WSH 1.0 way back when.

    TBH if we could redo it again I’d totally cut WScript.CreateObject because there are no Windows Script engines that don’t have the equivalent and the whole connectobject syntax was confusing (to put it in the least anglo-saxon!)

  6. Bob Riemersma says:

    Well from "Joe Coder’s" perspective IE offers the same sort of event binding to VBScript authors, at least for elements/objects present when the page is loaded.

    Who in their right mind writing VBScript-based DHTML would code something like:

    <body onload="VBScript:LoadHandler">

    … or hope the default is JScript and write:

    <body onload="LoadHandler()">

    … instead of using a Sub or Function named "window_onload" anyway?

    If one were to rip WScript.CreateObject( ) out of WSH how are we supposed to wire up events? Or do you mean that ConnectObject( ) would remain intact? I suppose there is plenty of redundancy here.

    I keep wondering why a .WSF’s <object> objects aren’t wired up to properly-named VBScript event handlers in the same <job>. Or are they and I just failed to ever try it? The documentation seems silent on this.

    I seem to recall a few cases where using VBScript’s CreateObject( ) was beneficial with ADO in ASP pages, though most of the time you ended up trashing connection pooling and transactability if you did this. Wish I remembered the details, but I’d have to do some excavation within several years of notes.

    I’m also puzzled why somebody would ask when to use WScript.CreateObject( ) and when to use VBScript’s CreateObject( ) in a WSH script. The Windows Script 5.6 CHM document seems to make it pretty clear, though you do have to get past the use of "sync" for "sink" under the description of WScript.Createobject( ).

    Keep in mind I’m looking at all of this from a user’s perspective though.

    Looking back on my scripting experiences I have to say the biggest pain in the rump for me was IE’s lack of something approximating WSH’s <reference> tag for loading type libraries. Or is it there, staring me in the face but undocumented? I’d love to toss all of those include files of Consts. A VBScript Enum construct would have been nice too while I’m wishing.

    The lack of a Sleep( ) in IE also rendered many an HTA more clunky than it needed to be. But now I’m REALLY digressing.

  7. Eric Lippert says:

    Those are a whole lot of interesting topics for future blogs!

  8. I asked Eric when to use what simply because the topic has never adequately been explained in any "official" MS documentation or articles, and people such as myself are presently using one or the other because of "cargo-cult" mentality, founded on various performance tests, heresay, and guesswork. Therefore, it would be nice to have a definitive answer.

    Fundamentally, I wanted to know which object creation method I should use when I simply want to create and use an instance of the FileSystemObject (or a Dictionary/Recordset/etc), and what are the performance/stability implications of the choice?

    While I see that for many people the ability to bind events and suchlike is useful and/or necessary to many, these don’t really concern me personally.

    Therefore, as it stands, I’m not sure my question (or at least, my *intended* question) has been answered! lol πŸ™‚

  9. Eric Lippert says:

    If you don’t care about event binding, transactability, or DCOM then it doesn’t matter which you call.

    I really have no idea what the performance implications of each are other than the fact that object creation is EXTREMELY expensive no matter how you slice it. Object creation almost always requires hitting the registry and the disk, and those are not cheap.

    As I’ve said before: If you care deeply about performance, using late-bound unoptimized dynamic languages like VBScript and JScript is possibly a poor choice. There are early-bound heavily optimized languages like C++ that are much more amenable to high performance.

  10. James Hugard says:

    <blockquote>Looking back on my scripting experiences I have to say the biggest pain in the rump for me was IE’s lack of something approximating WSH’s <reference> tag for loading type libraries. […] I’d love to toss all of those include files of Consts.</blockquote>

    My emperical JScript testing showed that loading constants from a typelib is one or two orders of magnitude <i>slower</i> than preloading an engine with script which defines those same constants.

    Plus, the implementation of ATL in VC6 had a multi-threading bug (fixed in VC7) that caused the typelib to report that it failed to load every once in a while (even though it did load).

  11. Eric Lippert says:

    I wrote all the type library importation code — you are correct, it is NOT FAST compared to simply defining a bunch of consts/vars.

    There are good reasons why. I’ll blog about them at some point.

    I too wish there was some way to do this in IE, but AFAIK, there is not.

  12. Is the slow loading of constants from typelibs also a true for VBScript too? (Compared to using constants defined in the code, such as with ADOVBS.INC?)

  13. Eric Lippert says:

    Yes, JScript and VBScript share the code for everything they have in common — the engine framework, type library importer, regexp parser, etc.

  14. Cheers for clearing that up – another cargo-cultist mantra shot down in flames! πŸ™


  15. James Hugard says:

    IMHO, the mantra should be "when it matters, profile it."

    This is why the command-line (developer) version of our script-host spits out both parse time and run time. There is also a "loop" command line option so that we can measure run times after our copious lazy instantiation has done its thing.

  16. (Sorry about the title. I work for Microsoft; we like nouns .) Over a year ago now a reader noted in

  17. Anand Sagar says:

    Iam working on a project where Server.CreateObject is replaced with CreateObject all over the project. Though I know that this will improve performance in terms of Memory overload because of how the object creation happes with CreateObject, I would like to have ‘visible scenarios’ that i create with code to show people that ‘"look. here’s the difference". Is it possible ?

    Can i create a simple project to simulate and see the performance differences between Server.CreateObject and CreateObject ?



  18. EricLippert says:

    Sure, you could do that, but that would be the wrong thing to do.

    Doing so would answer the question "is there a perfornance difference in a fake, contrived, small, unrealistic scenario?"  Do the people you are going to show this to care about the performance of fake, contrived, small and unrealistic scenarios?

    If the question you want to answer is "what is the performance difference in the real scenario that actually matters to our business?" then find a way to measure that.

    This is almost certainly the wrong area for exploration. It is a waste of time and money to spend any time analyzing and remediating anything other than the _slowest fixable thing_.  If the difference between CO and S.CO takes up 0.1% of the total time of your application, then fixing all of them cannot speed it up by more than 0.1%.  There is probably a bigger win somewhere else; spend the time that you would have spent twiddling CreateObject calls on finding out where that bigger win is.  When you do so, you’ll then have the figures to show the people who write the cheques what their return on investment is.

  19. Olivier Mengué (dolmen) says:

    @Eric: "WSH uses this weird thing with the string prefixes"

    In fact this is weird. This means one can not dynamically bind events after the COM object has been created, as the event function has to exist in the host namespace before the object creation. This is quite different from what is possible in an IE host and makes writing framework that work in both environments more difficult.

    For example, XMLHttpRequest is easier to use in synchronous mode in WSH.

    This is why almost no one use event binding in WSH.