From: ralph on
On Wed, 07 Jul 2010 20:48:57 -0600, Tony Toews
<ttoews(a)> wrote:

>I'm wanting to determine the version of various DAO, MSJet, ACE and
>One means of doing this is by using a CSIDL to get to C:\Program
>Files\Common Files\system\ado\msado15.dll (or close and then adding
>on system\ado as requiired.)
>Elsewhere it has been suggested that I should use the CLSID. In this
>case the entire key is
>which I got from
>Is this a relable method especially if dealing with other language
>OSs? Is this the best, recommended method?

By maintaining a list of GUIDS (CLSIDs, ...), AppID/ProgIDs, and
interesting stats of the various components (builds, size, date, ...)
you can build an assortment of methods of interrogate the Registry and
files to derive this information, but I have to ask ... Why?

In other words what are you plannning on doing if the current versions
are something less or something greater than what you want to see?


From: ralph on
On Wed, 07 Jul 2010 22:04:43 -0600, Tony Toews
<ttoews(a)> wrote:

>> I don't know how it works with a 64-bit library,
>>but that shouldn't matter if you're running 32-bit.
>No, that part I don't care about yet although I might given that
>Access 2010 comes in a 64 bit edition.

If the Office Betas are any clue, this is going to be an interesting
problem. As it stands now installing a 64-bit version means there are
no 32-bit components, and you will have trouble updating a 32-bit
Office product to 64-bit as it will fail if 32-bit components are

ACE is an equally interesting issue. For ACE versioning and the new
64-bit 'mess' you need to haunt the Office newsgroups/forums.

From: Mayayana on
| >That's how COM makes it possible to find
| >the object. But if the object is out-of-process the
| >key is LocalServer32 rather than InProcServer32.
| >Application objects and ActiveX EXEs are in that
| >category.
| Ok, now I'm not understanding all this but then prat of that is I do
| not fully understand what COM means.

I think Matthew Curland covers a lot in his book.
I don't know of much else. I once bought a book
called "The Essence of COM". It was big and thick,
and entertaining in parts, but taught me pretty
much nothing.

I'm not the person to provide official definitions,
but I think COM is not so complex from the usage
point of view. Maybe it's murky to VBers because
VB is so completely designed for COM that we don't
see it.

Basic points of relevance:

A standard DLL may have
any functions, which require documentation for use.
A COM library still needs docs, for all practical purposes,
but functions and data types follow a standard design,
and a COM library has a typelib that self-documents
at least the interfaces, methods, parameters, etc.

(Tlbinf32.chm has a lot of info., if you can find it.
But it's a little confusing. Tlbinf32.chm goes with
tlbinf32.dll. Tlbinf32.dll is a wrapper around the typelib
functions in oleaut32.dll. The only purpose for tlbinf32.dll
is to present the oleaut32.dll functions in more easily
digestible form for VB. But tlbinf32.dll is really not
necessary. With a typelib, oleaut32.dll is just as easy
to use, without the middleman. Unfortunately, the complex
typelib terminology got jumbled around in translation
from oleaut32 to tlbinf32. Tlbinf32.dll does not match the
oleaut32.dll functions. Worse, in places it uses the same
terms for different things. So it's best not to get too friendly
with tlbinf32.chm, but it does provide a lot of info. about
how typelib usage works.)

Since VB types align with COM types, and VB is designed
to easily access COM objects, most of the mechanics of
it is hidden. In C++ COM manifests as interfaces and
is apparently more cumbersome. At one point I came
across a posting by Raymond Chen where he used
a bizarre amount of Shell COM code. If I remember correctly
he was demonstrating that it was possible to access a
ShellFolderView object. (The object that wraps a folder
window listview.) For some reason he demonstrated a
circuitous method. In any case, the post was followed by
grumpy comments from C++ people lamenting that they
had to deal with COM.

When it's COM there are 2 ways to load it. Early/vtable
binding and late/dispatch binding. Most COM libraries
are compiled with a dual interface -- you can use either
method. Some libraries meant to be used by native code
might only have early binding interfaces, but I don't know
of any offhand. In rare cases there might be only
dispatch binding. (Example: MSI.dll. WindowsInstaller.Installer
offers only dispatch binding. It's an odd design. There's
an API for C++ and a dispatch interface for script. But
MS seems to have deliberately left VB out of their planning.)

Early binding in VB is
"as New...". It requires access to the typelib for the
library, so that VB can resolve the function pointers at
compile time and identify the data types. Your EXE can
then load the library (which VB does transparently) and
call the methods directly.

"CreateObject..." is late binding. It's slow and used
mainly by script. The data types are only variant or object.
If the library has a dispatch interface, the vtable will have
several standardized functions that a caller can use without
knowing anything else about the library. Those functions
allow for accessing the typelib and "discovering" the vtable
offset of given methods.

So "component object model" is a system for providing
standardized programming classes (objects). It allows for
doing things like wrapping window messages in an object
model to make GUI controls possible. But perhaps more
importantly, it provides a way for interpreted code to
load and use compiled libraries. (Which can include
application automation.)

In the case of dispatch interfaces, it all happens in the
Registry: A library gets registered on the system. In so
doing it creates keys under HKCR for each creatable object. The
ProgID key is directly under HKCR. It's name is the server.class
of an object: InternetExplorer.Application, Scripting.Dictionary,
HKCR\server.class\CLSID holds the CLSID for the object.
That number points to a key under HKCR\CLSID, where everything
needed to load the library and access the dispatch interface
is stored. Not all subkeys exist in all cases:

InProcServer32 - path of in-process library file

LocalServer32 - path of out-of-process lib. file.

(One of the above must exist for a 32-bit dispatch

Typelib - CLSID of typelib, found under HKCR\Typelib

Two ProgID keys - one naming the server.class and
one naming server.class.currentversionnumber

Control - The existence of this key indicates a sited

ToolboxBitmap - path of icon for VB toolbox.

Implemented Categories - A number of CLSID keys can
be here. I think there's one to indicate a control.
There are also CLSIDs to indicate "safe for scripting"
and "safe for initialization". You can mark a control
safe for use in IE by adding those keys.


So if your object has a dispatch interface then it
has to have a CLSID key. If it can be used with
CreateObject (as opposed to a control on a webpage
or in VB) then it must have a ProgID key. That's the
only way for the interpreter to figure out what you
mean by the server.class string. If there's no ProgID
you get a "can't create object" error.

I hope that wasn't "more than I needed to know",
as the teenagers like to say. I thought it might be
useful to have a basic explanation. The whole thing
makes much more sense when you know the gist of
how it works, but MS hasn't documented all of this
very well. (I don't think I've ever seen an exhaustive
list of Implemented Categories CLSIDs, for instance.)

| > Watch out for 2 things when parsing the path string,
| >though. There could be switches in the path. (Check
| >for " /" and snip it off if found.) The path string
| >may also need to be expanded. (Check for "%" in
| >the string.)
| Switch I can handle. % maybe not.

I use a simple function. You send in the result from
RegQueryValueEx and get back an expanded string
with any quotes removed.


Public Declare Function ExpandStr Lib "kernel32" Alias
"ExpandEnvironmentStringsA" (ByVal lpSrc As String, ByVal lpDst As String,
ByVal nSize As Long) As Long

Private Function ExpandIt(s1 As String) As String
'--reformat exp. strings (%s%)---------------------
Dim sExp As String, spth As String
Dim LExp As Long
If (InStr(1, s1, cPERCENT, vbBinaryCompare) <> 0) Then
LExp = 255
sExp = String$(LExp, 0)
LExp = ExpandStr(s1, sExp, 254)
If (LExp > 1) Then
spth = Left$(sExp, LExp)
spth = ""
End If
spth = s1
End If
spth = Replace(spth, QUOTEMARK, "", 1, -1, vbBinaryCompare)
ExpandIt = spth
End Function


From: Kevin Provance on

"Mayayana" <mayayana(a)invalid.nospam> wrote in message
: I think Matthew Curland covers a lot in his book.
: I don't know of much else. I once bought a book
: called "The Essence of COM". It was big and thick,
: and entertaining in parts, but taught me pretty
: much nothing.

While I understand the name Dan Appleman carries a certain stigma with some
folks, his book "Developing COM/ActiveX components with VB6" is about as
close to COM for Dummies as you'll find. A working knowledge of VB is
required, but otherwise Appleman does an excellent job breaking down COM to
it's basics and building it back up so the reader understands what is going
on. I re-read the book every year and always learn something new.

At this stage of the game, one could probably find the book used dirt cheap.
The CD that comes with is also worth having since much of the book is
example based.

From: Paul Clement on
On Wed, 07 Jul 2010 20:48:57 -0600, Tony Toews <ttoews(a)> wrote:

� Folks

� I'm wanting to determine the version of various DAO, MSJet, ACE and

� One means of doing this is by using a CSIDL to get to C:\Program
� Files\Common Files\system\ado\msado15.dll (or close and then adding
� on system\ado as requiired.)

� Elsewhere it has been suggested that I should use the CLSID. In this
� case the entire key is
� HKEY_CLASSES_ROOT\CLSID\{00000535-0000-0010-8000-00AA006D2EA4}\InprocServer32
� which I got from

� Is this a relable method especially if dealing with other language
� OSs? Is this the best, recommended method?

� Tony

Using the Registry would be a crapshoot at best, especially with MDAC and WDAC. As a matter of fact
I don't believe that msado15.dll is associated with any CLSIDs.

Probably best to check the known locations of the DLLs based upon the OS version and get then grab
the file version information.

Microsoft MVP (Visual Basic)