# Closed   as Won't Fix

to vote
 ID 515410 Comments 12 Status Closed Workarounds 0 Type Bug Repros 0 Opened 11/29/2009 3:44:08 AM Access Restriction Public

### Description

1. create a C# .NET class library with a com visible object
2. create .tlb with tlbexp
3. create unmanaged C++ windows console application
4. in stdafx.h add #import <Foo.tlb> no_registry no_namespace

Compiling the unmanaged C++ windows console application fails with the following error:

fatal error C1083: Cannot open type library file: 'd:\stdev\vs2010\test\testcomvisibleimport\include\foo.tlb': Error loading type library/DLL.

The same #import statement with the same .tlb works in Visual Studio 2008.
The #import statement works without no_registry in Visual Studio 2010 Beta 2.
Posted by Microsoft on 7/19/2010 at 1:25 PM
Hi Bernd -

Apologies for the continued delay on this bug. We are looking at possibly not fixing this bug for SP1, as any fix would be incomplete and there are a couple of pretty solid workarounds. Can you tell us if the workarounds suggested by Jon would be unacceptable for your situation?

Thanks,
Andy Rich
Visual C++ QA
Posted by Microsoft on 1/6/2010 at 10:01 AM
Bernd: sorry for the delay in getting back to you but a lot of people were out for the last two weeks.

It turns out that there is a bug here and the bug is in the compiler - when the CLR code calls back into the compiler it specifies the major and minor version numbers of the dependent type-library it is looking for. As your C# component targets the 2.0 runtime it creates a 2.0 type-library and hence it requires the 2.0 version of the dependent type-libraries. Unfortunately the compiler doesn’t check that any type-library it finds has the correct version - if the names matches then it assumes that it is the library it wants - basically it ignores the version information. So the result is that the compiler passes a 4.0 version of say, mscorlib.tlb, back to the CLR which then rejects it as it is the wrong version.

Luckily it appears that there are a couple workarounds:

1) Have your C# component target the 4.0 runtime instead of the 2.0 runtime.
2) Have the location of the 2.0 type-libraries appear first on the LIB environment variable (or the PATH if you still use it).

We will work on fixing the compiler but given where we are in the schedule the fix won’t make it into the final Visual C++ 2010 release (as we like to build what we ship using the shipping compiler we tend to shutdown the compiler early) but it will be in the SP1 release.

Note: even with the fix your project may fail to build if the location of the 2.0 type-libraries is not on the LIB/PATH.

Jonathan Caves
Visual C++ Compiler Team
Posted by RAB36 on 12/18/2009 at 11:58 AM
Jonathan,

thank you very much for this in-depth explanation. This is very much appreciated. Thank you also for pointing me to no_path.

Just for your info: I am having this problem on Windows 7 32-Bit as well as on Windows 7 64-Bit.

How can I track progress on this issue? Will the CLR team answer to this topic, too?
Why did you change the status to "Solved / by design".

Best regards,
Bernd
Posted by Microsoft on 12/17/2009 at 11:03 AM
Hi Brend: I am sorry that this has taken a while to resolve but to answer your questions:

- Yes: I can reproduce the problem - but only on a 64-bit OS.
- No: I have not resolved the issue
- See below
- C1083 is the generic error message that we issue when the loading of a type-library fails for some reason other than we can't find the file.

First some background: when a #import with no_registry is seen the compiler is still responsible for finding the type-libraries (as it knows how to search along paths etc.) but an external DLL, tlbref.dll, contains the code that does the loading of the type-libraries. This DLL uses a call-back to call into compiler to do the lookup for type-libraries (including dependent type-libraries).

The behavior I saw while debugging the compiler was that the compiler can find the original type-library, foo.tlb, and it also finds the two dependent type-libraries, stdole2.tlb and mscorlib.tlb. But, I originally believed, it is where it finds stdole2.tlb that causes the problem. On the system I was using (which I believe was a clean install of both the OS (Windows 7 64-bit) and Dev10) the compiler found stdole2.tlb at:

D:\Windows\syswow64\stdole2.tlb

This I believe is a 64-bit version of the TLB and the 32-bit compiler will not load it - hence the error message.

I changed the #import to:

#import “foo.tlb” no_registry no_namespace no_path

The attribute no_path tells the compiler not to search the along the PATH environment variable for any TLB. Note: no_path was added at the request of some internal customers and the current consensus appears to be that #import should always be used with both no_registry and no_path.

Now when I ran the compiler it found stdole2.tlb at:

D:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\lib\stdole2.tlb

Which is where I would expect the compiler to find it.

Unfortunately it then fails to find mscorlib.tlb (as it no longer searches PATH). In this case it gave the error message I think you were expecting to see:

d:\users\joncaves\tests\bar\stdafx.h(16): error C3510: cannot locate dependent type library 'mscorlib.tlb' {bed7f4ea-1a96-11d2-8f08-00a0c9a6186d} v.2.0

I fixed this by adding “D:\Windows\Microsoft.NET\Framework\v4.0.21214” to the LIB environment variable (note: your version number will almost certainly be different).

Unfortunately then the execution path returns into tlbref.dll and when it returns back to the compiler tlbref.dll reports that it cannot load the type-library. So whatever is causing the failure is in tlbref.dll - and as far as I can tell the compiler is finding the correct TLBs.

So I have assigned this issue over to the CLR team (as they own tlbref.dll).

If you have any further questions feel free to contact my directly joncaves AT microsoft DOT com
Posted by RAB36 on 12/16/2009 at 11:36 AM
Jonathan,

thank you for pointing me to the documentation. I am well aware of how #import no_registry works. We are using it in big projects since years using Visual Studio 2008.

Nevertheless, I checked the LIB path. In my environment it is

D:\STDev\VS2010\Test\TestComVisibleImport>set lib
LIB=C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\LIB;C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\ATLMFC\LIB;C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\lib;

The type libraries referenced by Foo.tlb are mscorlib.tlb and stdole2.tlb. mscorlib.tlb references only stdole2.tlb:

library mscorlib
{
// TLib :     // TLib : OLE Automation : {00020430-0000-0000-C000-000000000046}
importlib("stdole2.tlb");

// Forward declare all types defined in this typelib

mscorlib.tlb is here:

C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Lib\StdOle2.Tlb

stdole2.tlb is here:

C:\Windows\Microsoft.NET\Framework\v4.0.21006\mscorlib.tlb

so both .tlb's are in the LIB path. Nevertheless I still get the same error.

I could reproduce this behaviour on a second machine. Both machines have Visual Studio 2008 SP1 and Visual Studio 2010 Beta 2 installed.

I have a couple of simple questions:

- were you able to reproduce the problem by compiling my attached solution?
- if yes, were you able to fix it by changing any project settings or LIB environment variables?
- if yes, could you please tell me how to do this?
- why does the compiler complain with "Error loading type library/DLL" and not with "Cannot open type library file: 'xxx.tlb': No such file or directory" when the library is not found or missing?
- we have projects with dozends of COM objects and cross references typelibraries. They all compile with #import no_registry. All work fine with Visual Studio 2010, apart from a few. The ones that produce the error message all import a typelibrary generated by a .NET COM visible object. Why is that so? Isn't that a hint that there is a bug in the compiler?

Again: Visual Studio 2008 compiles all projects without problem, including the attached solution.

Could you please comment on this?

Best regards,
Bernd
Posted by Microsoft on 12/15/2009 at 8:41 AM
Hi: the solution is to make sure that the path that leads to the "dependent" type-libraries is on the LIB environment path. This page has a section that describes how type-libraries are found:

http://msdn.microsoft.com/en-us/library/8etzzkb6(VS.71).aspx

With no_registry the compiler searches for dependent type-libraries the same as it does for top-level type-libaries (internally at Microsoft LIB has become preferred over PATH). Unfortunately this is a bit of a recursive process - you have to hunt down the dependent type libraries one "level" at a time - but it is something you only need to do once.

For a consistent builds across machines this is definitely the correct thing to do.

Jonathan Caves
Posted by RAB36 on 12/9/2009 at 12:01 PM
Jonathan,

did I understand you correctly, that you could reproduce the bug by buildiing the solution I provided?

I did some experiments with the command line too, and the problem still occurs. When I run msbuild from the solution directory I am getting the same error. When I run only cl.exe for stdafx.cpp in the project directory of "Bar" I am getting the same error:

D:\STDev\VS2010\Test\TestComVisibleImport\Bar>CL /c /I..\Include /ZI /nologo /W4
/WX- /Od /Oy- /D WIN32 /D _DEBUG /D _CONSOLE /D _UNICODE /D UNICODE /Gm /EHsc /
RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Yc"StdAfx.h" /Fp"Debug\Bar.p
ch" /Fo"Debug\\" /Fd"Debug\vc100.pdb" /Gd /TP /analyze- /errorReport:queue stdaf
x.cpp
stdafx.cpp
d:\stdev\vs2010\test\testcomvisibleimport\bar\stdafx.h(16) : fatal error C1083:
Cannot open type library file: 'd:\stdev\vs2010\test\testcomvisibleimport\includ

You are absolutely right, the Foo.tlb references other type libraries. When you fire up oleview.exe and open the foo.tlb you can see it:

library Foo
{
// TLib :     // TLib : mscorlib.dll : {BED7F4EA-1A96-11D2-8F08-00A0C9A6186D}
importlib("mscorlib.tlb");
// TLib : OLE Automation : {00020430-0000-0000-C000-000000000046}
importlib("stdole2.tlb");

// Forward declare all types defined in this typelib
interface IFoo;

So there is nothing else referenced than mscorlib.tlb and stdole2.tlb.

Both seem to be in the path of the Visual Studio 2010 command prompt:

D:\STDev\VS2010\Test\TestComVisibleImport\Bar>where mscorlib.tlb
C:\Windows\Microsoft.NET\Framework\v4.0.21006\mscorlib.tlb

D:\STDev\VS2010\Test\TestComVisibleImport\Bar>where stdole2.tlb
C:\Windows\System32\stdole2.tlb

So what is going on here? We urgently need the no_registry support of #import because otherwise it is near to impossible to build different versions of our product on the same machine.

Could you please investigate this further and find a solution to this?

Please note, that the same project builds without any problems with Visual Studio 2008.

Best regards,
Bernd

Posted by Microsoft on 12/8/2009 at 9:23 AM
I suspect that there is not a C++ compiler issue here. I tried several permuatations from the command-line and they all compiled. I suspect there must be one of two things going on here.

1) There is a project system issue here in which correct paths are not getting set/propagated through the build system

2) In your case there is a dependent type library and it is this dependent type library that this failing to load (unfortunately the complier doesn't know what the dependent type library is and COM doesn't tell us) - no_registry impacts both the top-level type library and all dependent type-libraries (and more often than not it is the dependent type libraries that are found via the registry).

Jonathan Caves
Visual C++ Compiler Team
Posted by RAB36 on 12/2/2009 at 10:59 PM
Jonathan,

thank you for looking into this.

1. the C# Foo project creates the .tlb in the directory \$(SolutionDir)Include\Foo.tlb as you can see in the Post Build event command line of the corresponding project.
2. the bar project in the solution I provided has the "..\Include" directory in the include path, see the setting for "Additional Include Directories" at C\C++ / General
3. if I replace "..\Include" by "..\Foo" in this project setting, I get the (expected) error message "fatal error C1083: Cannot open type library file: 'Foo.tlb': No such file or directory". Note that it is different from the one I provided in the bug description.
4. if I use the full path of the .tlb directly in the #import statement as in "#import "D:\STDev\VS2010\Test\TestComVisibleImport\Include\Foo.tlb" no_registry no_namespace", I still get the error "d:\stdev\vs2010\test\testcomvisibleimport\bar\stdafx.h(16): fatal error C1083: Cannot open type library file: 'd:\stdev\vs2010\test\testcomvisibleimport\include\foo.tlb': Error loading type library/DLL."

Could you please comment on this?

Best regards,
Bernd
Posted by Microsoft on 12/2/2009 at 10:12 AM
Hi: this is By-Design. If you tell the compiler to ignore the registry (via the no_registry attribute) then that is what it does. This means you must include the path to the generated *.tlb either via the include path or by explicitly specifying it as part of the #import directive. If I add "..\Foo" to the include path then the provided project builds.

Jonathan Caves
Visual C++ Compiler Team
Posted by Microsoft on 12/2/2009 at 1:29 AM
Thanks for your feedback. We were able to reproduce the issue you are seeing. We are routing this issue to the appropriate group within the Visual Studio Product Team for triage and resolution. These specialized experts will follow-up with your issue.
Posted by Microsoft on 11/30/2009 at 2:20 AM
Thank you for your feedback, We are currently reviewing the issue you have submitted. If this issue is urgent, please contact support directly(http://support.microsoft.com)