Click here to Skip to main content
Email Password   helpLost your password?

Introduction

In a discussion about an articled posted on CodeProject entitled, "Importing contacts from Outlook", I pointed out that using file references for importing type libraries was not usually a good idea. You shouldn't assume that everyone has their projects or type libraries in the same path or even on the same drive. Using simple alternatives that any COM developer should already be familiar with, you can improve the portability of your source code.

Requirements

To import type libraries using alternatives to file references, you will need the C/C++ compiler, version 13.00. This compiler ships with Microsoft Visual C++ .NET, Microsoft Visual Studio .NET, and the Microsoft Platform SDK.

About Type Libraries

Before jumping into alternatives for importing type libraries, you might wonder what a type library (typelib) is. As defined in the MSDN, a type library is "[a] file or component within another file that contains type information about exposed objects. Type libraries are created using the MIDL compiler, and can be accessed through the ITypeLib interface." This means that information about interfaces, structures, and enumerations and all their members can be obtained without actually referring to the object that implements these things. This is important when developing COM clients because you usually don't know in which directory - or computer - the implementation library resides, which is one goal and feature of COM: reusability and extensibility.

Since you typically don't know where the implementation class is, you must know more information about it. Early-bound automation clients use this information to cache member IDs at compile-time and use that information to call methods directly. Late-bound automation clients use this information during design-time but call the methods based on their IDs at run-time through the power of the IDispatch interface. For more information about this subject, see the documentation for the IDispatch interface.

Now that you have some idea what type libraries are, you may wonder why and how you should use them. The "how" will be answered by the following sections and is the scope of this tutorial. The "why" is because you typically must know at design- and compile-time what members are available for use. Unless you're writing a completely autonomous client that discovers all type information at run-time through IDispatch and knows what to do with more interfaces exposed, you'll need to know what to call, even in late-bound environments like Visual Basic, in which case you "reference" libraries. The compilers will take care of a lot of detail for you if you take advantage of them.

Referencing Type Libraries

As with most COM objects, you can refer to typelibs using several methods. They are identified by globally unique identifiers (GUIDs), or more specifically LIBIDs. Unlike COM objects, however, typelibs typically only have one LIBID for all versions of the typelib. This alone improves portability, especially for late-bound clients or other implementation classes. Similar techniques can be used to import specific COM objects as well, using either their class identifier (CLSID) or their program ID, both version-independent and version-dependent identifiers.

You can still reference typelibs by their file path using both relative and absolute paths, but you should usually only do this when it's a typelib you or your company is developing and may not want registered on the system during design-time.

Importing Type Libraries

Now that you know you can reference typelibs using their LIBID, you must know how to leverage that information. In the article previously mentioned, the author needed to import the typelibs for Office and Outlook. You can use oleview.exe (provided in the Platform SDK) to find information about interfaces, such as the LIBID and versions of the typelib present on your system. In most case, typelibs are backwards-compatible but ensuring that a client machine has the minimum or correct version of the COM libraries is recommended and often necessary.

These LIBIDs can be found in your registry under HKEY_CLASSES_ROOT\TypeLib or using oleview.exe. Using oleview.exe yields the following information about the Office and Outlook typelibs on my system:

OleView.exe Screen Shots - Type Libraries

To import these type libraries without namespaces that we must declare with using and with named GUIDs for easy reference (see the MSDN for more attributes), we would type the following:

#import "libid:2DF8D04C-5BFA-101B-BDE5-00AA0044DE52" named_guids no_namespace
#import "libid:00062FFF-0000-0000-C000-000000000046" named_guids no_namespace

This information you can see in the right pane. The GUID - in the form {12341234-1234-1234-1234-123412341234} - is the LIBID and the decimal below it is the version in the format major.minor. Again, the LIBID will typically stay the same for a typelib, but the version will most often change. As you can see from the screen shot, Outlook XP's typelib uses a version of 9.1. If you wanted to modify the code above to use a specific typelib version so that only code compiled against the Outlook XP typelib, you would change the following:

#import "libid:00062FFF-0000-0000-C000-000000000046" version(9.1) named_guids no_namespace

Using this method, you can still control the typelib version used by your application but still don't have to worry about file paths. This is especially handy when working in development teams without a common workstation image. You can even specify language ID to specify which typelib locale to use. If you don't specify a version number, the most recent typelib version is used. In this case, specify the lcid attribute along with a hexadecimal representation of the language ID. For example, en-US (U.S. English) would be "409". This is "1033" in decimal form. If you don't specify a locale ID or only one locale is available, the first or only locale is used.

The information about typelibs can also be used with the less-portable alternative, which is using relative or absolute paths. Both techniques offer advantages over the other, and present disadvantages when porting source code to different systems. Using file references is a good idea, however, when you know that the directory structure of your project layout is consistent throughout your development team and you don't want to register any libraries until it's time to test or deploy. You can see an example of such a situation in my article entitled, "Embedding .NET Controls in Java", or from the example below:

#import "C:\Program Files\Microsoft Office\Office10\msoutl.old" named_guids

This can limit us to specific versions, although keep in mind that a typelib doesn't have to be registered to extract information from it. In development situations that call for file references, you could always include the typelib with your project - perhaps even in source control systems like Visual SourceSafe or CVS - to make sure all members of your development team have the same version.

Referencing COM Objects

What if you don't need to reference the entire typelib and just want a particular control out of the typelib? Using similar alternatives - along with another alternative - and help. COM objects are also identified by GUIDs, specifically known as class IDs or CLSIDs; however, these CLSIDs typically change from version to version of the object. To combat the situation, you can use the object's program ID, or ProgID. ProgIDs can be both version-dependent and version-independent, which means that you can either specify a specific version or use the latest version (or whichever version is referenced).

A version-dependent ProgID typically takes the form AppID.ClassID.Major[.Minor]. For example, if you wanted to reference the Outlook Application object (the object from which all application-specific methods typically originate), you could use the version-dependent ProgID, Outlook.Application.10. If you knew that your method calls are compatible with many versions of Outlook - perhaps even all since Outlook isn't that old - you could use the version-independent ProgID Outlook.Application. These ProgIDs can be found in your registry directly under HKEY_CLASSES_ROOT, or using oleview.exe, which yields the result:

OleView.exe Screen Shots - Program IDs

You can see both the version-independent and version-dependent ProgIDs in the right pane. The registry stores this information in separate keys and usually points the version-independent at the latest version-dependent ProgID, but this may not always be the case since a number of factors could mistakenly - or intentionally - change this behavior. This is a rare occurrence, however.

Importing COM Objects

Now that you know the ProgID of the object you want to import, you need only modify the previous statements to use a ProgID instead of a LIBID:

#import "progid:Outlook.Application" named_guids no_namespace

A version-independent ProgID is used above. If you want to specify that the Outlook 10 typelib should be imported, you can use either the version-dependent ProgID or the typelib version attribute. Remember that these might not agree, however. You should remember that the typelib version as we learned before was 9.1, not 10. When using ProgIDs, I recommend that you stick with version-dependent ProgIDs instead of using the version attribute; it can get a bit confusing. Using a version-dependent ProgID would look like:

#import "progid:Outlook.Application.10" named_guids no_namepace

Attributes

Throughout the article, I've been mainly consistent with the #import attributes I've used. These are to my preference and different situations call for different measures. For much more information about the attributes available and what they do, see the MSDN.

One such variation of the code examples above is more common, with is to eliminate no_namespace. When you do this, you allow your code to group #import statements in a single file while limiting the scope of calls throughout your source code. If I were to drop the no_namespace attribute, I would have to use the using directive like in the following code:

#import "progid:Outlook.Application" named_guids
using namespace Outlook;

// Or we can use it explicitly...

CComPtr<Outlook::_ContactItem> spContactItem;

See the MSDN for more information about the using declaration and the using directive.

Example

Because this tutorial was inspired by discussions on Deepesh Dhapola's article, "Importing contacts from Outlook", and because I used the Office and Outlook typelib and COM object references through this tutorial, I invite you to download his sample source and change the following lines in OutlookContactsDlg.cpp:

// #import "E:\Program Files\Common Files\Microsoft Shared\Office10\mso.dll" \

//    named_guids

// #import "E:\Microsoft Office\Office10\MSOUTL.OLB" \

//    no_namespace exclude("_IRecipientControl", "_DRecipientControl")


#import "libid:2DF8D04C-5BFA-101B-BDE5-00AA0044DE52" named_guids
#import "libid:00062FFF-0000-0000-C000-000000000046" \
    no_namespace exclude("_IRecipientControl", "_DRecipientControl")

Now, just in case your E: drive (if you have one) is a CD-RW like mine, you shouldn't have any problems compiling the sample so long as you have the typelib registered which doesn't mean the application has to be installed.

Summary

Using file references shouldn't be thrown out altogether. File references are typically necessary when a development team is developing both automation serves and clients, especially when dealing with newer versions of an existing project. However, I hope this tutorial has given you alternatives to use to make your source code more portable from machine to machine for the majority of times when you're using pre-existing typelibs to extend your own application, or to even extend existing functionality. Importing typelibs helps reduce your code through reusable code and makes your development job often easier. Make your job even easier still by considering these alternatives to importing typelibs and COM objects that next time your developing for COM.

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
GeneralWhat is the GUID for msado15.dll
AlexEvans
17:05 3 Oct '06  
Can't find a GUID id for that Library

Any help will be appreciated

Thanks
Alex
GeneralRe: What is the GUID for msado15.dll
Heath Stewart
7:04 4 Oct '06  
You can use oleview.exe to look at the typelib stored in msado15.dll to find the typelib ID. I see 2A75196C-D9EB-4129-B803-931327F72D5C.

This posting is provided "AS IS" with no warranties, and confers no rights.
Software Design Engineer
Developer Division Customer Product-lifecycle Experience
Microsoft
[My Articles] [My Blog]

GeneralUsing libid locks up Visual Studio
Anonymous
11:35 22 Sep '04  
I am using the latest Visual Studio version 7.0.9466 and when I import a type library using the filename it works fine. This is a VB DLL built in house with VB 6.0

#import "C:\Program Files\NBC CREST v3.11\RRE_DLL.dll" rename_namespace("RRE")
using namespace RRE;

But when I try to load it using the TypeLibrary GUID it locks up my entire Visual Studio.

#import "libid:CFEFC3EA-8697-4EB2-82D4-991F3C523CC6" named_guids no_namespace

I would really like to use the GUID instead of the path. Any ideas??
GeneralRe: Using libid locks up Visual Studio
Heath Stewart
11:40 22 Sep '04  
Since you're using VB, you must check "Binary compatibility" in your project settings otherwise the typelib ID will change with each compile. This is more than likely the problem.

Since compiling the VB library registers the typelib and types contained within the library, the GUID would always exist and would point to the original compilation (the output). The typelib would, however, contain a different GUID. Visual Studio might not be handling this problem correctly, hence the hang. Let me know if setting binary compatibility solves the issue. If so, I could probably file a bug with the guys upstairs (although the underlying problem is the changing typelib GUID, but Visual Studio shouldn't hang).

This posting is provided "AS IS" with no warranties, and confers no rights.
Software Design Engineer
Developer Division Sustained Engineering
Microsoft
[My Articles]
GeneralRe: Using libid locks up Visual Studio
Michael Holck
4:36 23 Sep '04  
That was exactly the problem. Thanks. It was weird whenever I tried to use the libid that was wrong and tried to build my Visual Studio would just hang and task manager would show 2 processes each using 50% of the cpu. One was devenv.exe which is the Visual Studio environment and the other was cl.exe. They never would time out. I had to kill the Visual Studio app from task manager. Anyway, thanks for the help.
GeneralRe: Using libid locks up Visual Studio
Decipator
11:22 25 Jan '05  
hi

I have the same problem, but do not use VB.
I'm using MS VC++ 2003 (unmanaged C++).

VC hangs if i try to import "msado15.dll" via its GUID (#import "libid:EF53050B-882E-4776-B643-EDA472E8E3F2")

However I can't find "Binary compatibility" in my project settings - since its not a VB project!
Am I wrong?

What can I do?

THX



GeneralRe: Using libid locks up Visual Studio
Heath Stewart
6:48 26 Jan '05  
The typelib ID for msado15.dll on my machine is 2A75196C-D9EB-4129-B803-931327F72D5C, which is actually Microsoft ADO 2.8 (so clients are upgraded automatically and unknowingly). Where did you find your typelib ID?

There won't be any "binary compatibility". That's a "layman's" term for simply keeping GUIDs for the typelib, classes, and interfaces (though not applicable in old-school VB) the same - something required of COM unless you like things breaking. "Binary compatability" is only a setting for your project, too - not for importing other projects. It is supposed to keep your GUIDs the same.

So, the fact that you're importing a typelib - whether in VB6 or some other language/framework - it does't matter so long as its GUIDs don't change, and you shouldn't see that in any Microsoft and many other third-party libraries. That would break any client using the typelib for early binding.

This posting is provided "AS IS" with no warranties, and confers no rights.
Software Design Engineer
Developer Division Sustained Engineering
Microsoft
[My Articles] [My Blog]
GeneralRe: Using libid locks up Visual Studio
Decipator
10:53 26 Jan '05  
Thx for your response.

I got my typelib ID from OLE/Com Object Viewer by opening msado15.DLL.
Its actually version 2.7.

So it seems to me that I have to import the dll-file dynamically?

I write a tools library that should not use absolute paths Smile

THX
GeneralI export makefile and build with PSDK environment,but error still exist!
codestudy
3:03 8 Apr '04  
I have already installed Platform SDK February 2003.
I have already added Platform SDK /include /Lib /src directory to my VC option/directories in Include file,Library files and source files.
I #import an Office 9.0 Object Library using libid but get a compiler error "fatal error C1083: Cannot open type library file: 'libid:2DF8D04C-5BFA-101B-BDE5-00AA0044DE52': No such file or directory".
Then according to you I Export a Makefile from VC, then use the Platform SDK build environment to compile.
But Error still exist!!! Can You help me?
GeneralRe: I export makefile and build with PSDK environment,but error still exist!
Heath Stewart
5:13 8 Apr '04  
I'm not sure what the Makefile includes as the compiler path, but make sure it uses the VC++ 7.0 (or higher) compiler. See the discussions below for more details.

 
Microsoft MVP, Visual C#
My Articles
GeneralRe: I export makefile and build with PSDK environment,but error still exist!
codestudy
1:57 16 Apr '04  
Thank you very much!
I will use it in VC++ 7.0.;)
GeneralI got a lot of compile errors
Kingwulf
9:45 28 May '03  
When I tried to substitute
#import "C:\PROGRA~1\MICROS~2\Office10\OUTLCTL.DLL" raw_interfaces_only, raw_native_types, no_namespace, named_guids
with
#import "progid:Outlook.Application.10" raw_interfaces_only, raw_native_types, named_guids, no_namepace


I got a lot of compile errors.

Did I do something wrong?

Thanks,

-Henry
GeneralRe: I got a lot of compile errors
Heath Stewart
12:12 28 May '03  
Make sure you're using the latest compiler that comes with the Platform SDK and VS.NET (both 2002 and 2003). See earlier posts for more information.

Also, you shouldn't use commas to separate declarations. They should be space-delimited.


Reminiscent of my younger years...
10 LOAD "SCISSORS"
20 RUN

GeneralRe: I got a lot of compile errors
Kingwulf
12:36 2 Jun '03  
Thanks for the tip

However after using VC 7 I got different error message:

fatal error C1083: Cannot open type library file: '': No such file or directory

this is how I use to import the library:

#import rename "progid:Outlook.Application.10" raw_interfaces_only raw_native_types named_guids no_namespace

this is how I used to use it:

#import "C:\PROGRA~1\MICROS~2\Office10\OUTLCTL.DLL" raw_interfaces_only raw_native_types no_namespace named_guids

Thanks,

-Henry
GeneralRe: I got a lot of compile errors
Heath Stewart
12:58 2 Jun '03  
Kingwulf wrote: #import rename "progid:Outlook.Application.10" raw_interfaces_only raw_native_types named_guids no_namespace
Get rid of "rename".


Reminiscent of my younger years...
10 LOAD "SCISSORS"
20 RUN

GeneralJuly/Aug 2002 Platform SDK - Problems
fbougadou
5:19 21 Mar '03  
Heath! Excellent article and responses, very insightful. I was wondering, I installed the July and August ( same core ) platform SDK in order to utilize the libid method of importing typelibs in VC6. I also installed VC.NET and attempted the following: I #import a simple winword typelib in VC6 using libid but get compiler errors stating : " Cannot open type library file: 'libid:00020905-0000-0000-C000-000000000046': No such file or directory”. I verified my paths in option/directories and they are pointing to the platform sdk dirs first. However, when I compile in VC.Net, no problem. What’s the deal ? Is there a specific PSDK I need to install to get the libid/progid/version/lcid features to work in VC6 or am I forced to work in VC.Net ? Am I missing a step, doing something wrong ? Any ideas ?

fb
GeneralRe: July/Aug 2002 Platform SDK - Problems
Heath Stewart
6:46 21 Mar '03  
The problem is that VC6 will always use the VC6 compiler (perhaps there's a registry key or something to override that, but who knows). You should export a Makefile and use the Platform SDK build environment to compile. That should work. VC.NET (unmanaged) will use the new compiler that comes with Platform SDK in some shape or another.

As a side comment, using LIBIDs and PROGIDs has nothing to do with paths you have defined for your build environment. The compiler uses the registry (just like the default class factory in COM) to find the files.


Reminiscent of my younger years...
10 LOAD "SCISSORS"
20 RUN

GeneralRe: July/Aug 2002 Platform SDK - Problems
fbougadou
10:55 21 Mar '03  
Thanks for all the info, much appreciated.
Side note rebuttal: I appreciate the tip on LIBIDs and PROGIDs. I was alluding to the bin/header/lib modules that the compiler picks up when compiling a project. I was hoping that if I placed the PSDK paths at a higher level in the hierarchy, (especially the BIN dir) ,that the compiler would pickup the latest MIDLC and MIDL compilers. No such luck.
Thanks again, for all your help, looking forward to future articles from you.
fb


fb
GeneralThank you!
Phil J Pearson
3:50 24 Feb '03  
I have always been unhappy with using pathnames to import stuff like ADO, ADOX and JRO. This is an excellent solution. The small problem is that it only works in VC7; VC6 complains "Cannot open type library file: ... : No such file or directory"

At least it's a good reason to use VC7! Wink



The opinions expressed in this communication do not necessarily represent those of the author (especially if you find them impolite, discourteous or inflammatory).
GeneralI just used it
Jörgen Sigvardsson
0:48 24 Feb '03  
and its so sweet! This'll make the development environment a bit more relaxed.

--
we dance to the sound of sirens
and we watch genocide to relax
we dance to the sound of sirens
we are the heroes of self-deception

GeneralLatest platform SDK required !
.S.Rod.
23:10 23 Feb '03  

This article is fine, thanks, although you should have mentioned that using #import with libid:, progid: statements is only available after you install the latest Platform SDK.
I have VC6 SP5 at work along with the standard Platform SDK (read : a bit old), and the compiler refuses other #import statements other than raw filepaths.
GeneralRe: Latest platform SDK required !
Heath Stewart
2:58 24 Feb '03  
Are you sure? Do you have any references? I only ask because I've been able to do this since installing the version of the Platform SDK that came on the VS.NET CD as part of the setup. I believe that was the October 2001 Platform SDK. It always worked fine for me. Now the current SDK is October 2002 (as of a week ago).

You're right, though, I should mention something about that, although I do think that developers should keep their Platform SDK up-to-date, at least updating the components they already have installed.


Reminiscent of my younger years...
10 LOAD "SCISSORS"
20 RUN

GeneralRe: Latest platform SDK required !
Heath Stewart
4:51 24 Feb '03  
I updated the article to reflect this information.


Reminiscent of my younger years...
10 LOAD "SCISSORS"
20 RUN

General[Message Deleted]
Anthony_Yio
16:49 10 Mar '03  

GeneralRe: Latest platform SDK required !
Heath Stewart
3:12 11 Mar '03  
So how are you supposed to get the latest compiler? MS Office will give you the typelibs, but they're useless if you don't have a compiler, which is why the Platform SDK or VS.NET (at least VC++ 7.0/.NET) is required...unless you want to use that crap known as VB that lets morons call themselves "programmers".


Reminiscent of my younger years...
10 LOAD "SCISSORS"
20 RUN


Last Updated 24 Feb 2003 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2010