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
Anonymous
June 01, 2004
The comment has been removedAnonymous
June 01, 2004
"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.
FWIW,
KimAnonymous
June 01, 2004
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 detailsAnonymous
June 01, 2004
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.Anonymous
June 01, 2004
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!)Anonymous
June 01, 2004
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.Anonymous
June 01, 2004
Those are a whole lot of interesting topics for future blogs!Anonymous
June 01, 2004
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 :)Anonymous
June 02, 2004
The comment has been removedAnonymous
June 02, 2004
<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).Anonymous
June 02, 2004
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.Anonymous
June 05, 2004
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?)Anonymous
June 05, 2004
Yes, JScript and VBScript share the code for everything they have in common -- the engine framework, type library importer, regexp parser, etc.Anonymous
June 06, 2004
Cheers for clearing that up - another cargo-cultist mantra shot down in flames! :(
http://blog.marcustucker.com/blog_comment.asp?blog_id=22Anonymous
June 08, 2004
The comment has been removedAnonymous
August 29, 2006
PingBack from http://www.guangmingsoft.net/wordpress/index.php/146/difference-between-createobject-calls/Anonymous
September 07, 2007
(Sorry about the title. I work for Microsoft; we like nouns .) Over a year ago now a reader noted inAnonymous
January 14, 2008
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 ? Thanks. Anand.Anonymous
January 15, 2008
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.Anonymous
May 19, 2008
PingBack from http://kaitlin.mediaplusnews.info/createobjectwscript.htmlAnonymous
July 21, 2010
@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.