2

Does anyone know why a C# created COM library that was compiled under CLR2 (.Net 3.5) doesn't work when used with only CLR4(.Net 4)? What is missing in CLR4 that is in CLR2 for COM?

We are using the appropriate startup in the app.config to have the C# run under CLR4/.Net 4:

<startup>
  <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>

All the C# stuff works until it try's to create our COM interface. It provided the following exception:

Failed to load the runtime. (Exception from HRESULT: 0x80131700)

We get the same issue when we try to create the COM interface from C++.

Once we install CLR2 (.Net 3.5) all the COM stuff starts working. We would like to know what's going on.

Omar
  • 14,695
  • 8
  • 40
  • 61
Rodney S. Foley
  • 9,444
  • 10
  • 44
  • 64
  • 1
    AFAIK, the .net runtimes are all independent and must be individually installed. You could recompile your COM library and target the 4.0 framework though, assuming you have the source. – lc. Nov 05 '12 at 18:02
  • RE-compiling as .Net 4 doesn't work same issue. However that was for testing purposes as we need to remain .Net 3.5 for compatibility reasons but run on Windows 8 without requiring user to install .Net 3.5. So like I stated everything works but the COM part when running under CLR4. Something for COM is in 3.5 that isn't in 4.0 is my first though. – Rodney S. Foley Nov 05 '12 at 18:14

3 Answers3

3

The assembly is registered to require CLR v2 but you explicitly disallowed that version to be loaded with the .config file. You'll need an extra bit in the .config file to say, "I know, but it's okay". Like this:

<startup useLegacyV2RuntimeActivationPolicy="true">
   <supportedRuntime version="v4.0"/>
</startup>  

Do note that you are intentionally bypassing the in-process side-by-side versioning feature that was added in .NET 4. A new feature, expressly added to allow an application to load multiple versions of the CLR to support COM servers that have different CLR version requirements. Which certainly sounds like your scenario. In which case the more compatible mouse trap is to allow both versions of the CLR to be loaded:

<startup>
   <supportedRuntime version="v4.0"/>
   <supportedRuntime version="v2.0.50727"/>
</startup>  

Another very important detail is the name and location of this .config file. It is unintuitive but the CLR locates the .config file from the directory and name of the startup EXE. So if you are testing this [ComVisible] server from a native C++ program, say c:\foo\bar.exe, then you must name the file "bar.exe.config" and copy it to the c:\foo directory. Putting the .config file in the same directory as the DLL with the DLL's name will not work.

Hans Passant
  • 873,011
  • 131
  • 1,552
  • 2,371
  • While that sounds promising and one would think it would work it doesn't. Our CLR2/.Net 3.5 based COM DLL is not usable when running on CLR4 with useLegacyV2RuntimeActivationPolicy enabled or disabled. Remember C++ can't instantiate the COM objects in this C# COM DLL either unless .Net 3.5 is installed, since DLL's don't have app.configs it couldn't be as simple as this attribute. There is something that is simply not installed with CLR4 but is with CLR2 that is related to COM. – Rodney S. Foley Nov 05 '12 at 18:36
  • Use SysInternals' ProcMon to see the EXE searching for missing files. Do start by first checking that it loads the .config file. If it doesn't then you didn't put it in the right place. Which is the same folder as the native EXE, not the DLL. – Hans Passant Nov 05 '12 at 18:40
  • What do you mean NATIVE exe? This is a C# COM DLL it doesn't have a NATIVE.exe The assembly uses the Make assembly COM-Visible option and GUID, InterfaceType, DispId, ClassInterface, ComVisible attributes to decorate interfaces, classes, and methods. There one config file with the startup and its in the right place as if we remove startup the C# application that uses this C# COM DLL doesn't start at all. So safe to assume we are working with the correct config file. The C++ application in question was a test application to help trouble-shoot this issue. – Rodney S. Foley Nov 05 '12 at 18:46
  • I mean the program that **uses** this COM dll. Like you C++ test application, a native EXE after you compiled it. This strongly suggests that you put the .config file in the wrong directory. If it sounds weird that a native EXE would have a .config file: no, that's really the way it works. The CLR locates the .config file from the startup EXE directory and name. – Hans Passant Nov 05 '12 at 18:51
  • The C++ is a test app. The EXE that is used is a C# app not Native. This however doesn't look like the issue. As pointed on in a another recent answer (http://stackoverflow.com/a/13238652/196020) the issue is regasm.exe and how it registers the COM classes with the CLR2 because that is what they are compiled with. This is why we we tried .NET 4 versions that we only DROPPED in they didn't work. .NET 4.0 would work if we re-registered with regasm.exe. However we want to avoid .Net 4.0 compiling. We changed it as stated in that answer and all just started working via C# and C++. – Rodney S. Foley Nov 05 '12 at 19:07
3

After compiling the assemblies in .NET 4, you'll probably need to use regasm.exe to update the RuntimeVersion. If recompiling is not an option, you could potentially change the RuntimeVersion in the registry from v2.0.50727 to v4.0.30319. This worked for me. I found a similar answer here: Using a .NET-2.0-targeted COM DLL in the GAC on a .NET-4-only system

Community
  • 1
  • 1
0

The CLR version is written in the .dll file header and its value is copied to the registry by the regasm tool. The activator then tries to run the component with the exact CLR version specified. To have CLR 4 run the components implemented in CLR 2 assemblies you can either manually change the registration information (Classes/{clsid}/InprocServer32/component-version/RuntimeVersion) or set the useLegacyV2RuntimeActivationPolicy as described in the previous answer (the config file really does go next to the native .exe, nothing wrong with that).

cynic
  • 5,005
  • 1
  • 22
  • 40
  • You are only half right. The registry changes described in the marked answer (stackoverflow.com/a/13238652/196020) do work, setting the useLegacyV2RuntimeActivationPolicy to true does nothing to fix this C# COM issue as stated already in previous comments. – Rodney S. Foley Nov 05 '12 at 20:16