Reference COM+ dll - c#

For my job I need to use a 32 bit c++ dll with a 64bit c# program. I wanted to try doing this using dlls as wrappers.
What I have done for the moment is I made a dll that uses dll import to expose the function of the c++ dll and then make it COM+ enabled to make these functions available in 64 bit.
The problem I am facing is using this COM+ dll. To do it I followed this documentation
I signed it with a strong name, compiled it, registered it using gacutil and then sent it to com+ with Regsvcs. But when I want to use it I need to have a reference about it in my 64 bit app.
I tried to do add reference, select COM and then my class and it tells me that:
the ActiveX type library was exported from a .net assembly and cannot be registered.
If I try to add the tlb file it tells me:
check that the file is accessible and this is an assembly or a valid COM component
If I had the dll as reference, I get a badImageException.
My computer is not in English so the messages might not be accurate.

You cannot load a 32-bit DLL in a 64-bit process (nor the other way around). Wrapping it around COM can only help if the COM server is out-of-proc (i.e. an executable). If it's an in-proc COM server (i.e. a DLL), as I understood from your description, that's not going to work. Your 64-bit process will load the 64-bit COM server and then this will try to load the 32-bit DLL and that will fail. What you need to do is to change the COM wrapper into an out-of-proc server. That will run in its own 32-bit process. Communication with proper data marshaling between the 32-bit and the 64-bit process is done transparently through COM.

Related

C# 64-bit COM component for both 32-bit app and 64-bit Microsoft Excel VBA clients

I have created a COM DLL using C#.NET 4.6 and exported class does have all attributes to be exposed as a COM interface. It is built using x64 platform target and registered using "Register for COM interop" flag under project's build option. Inside Microsoft Excel's VBA 64-bit it can be consumed without any issues.
But, I also need to consume this same COM in a Delphi 7 app but Delphi 7 only accepts 32-bit COM references. This app can't be migrated to a more recent version of Delphi though so I need to make this COM component to also work with 32-bit clients.
If I build the same C# DLL targeting x86 platform, it will be visible and functional in Delphi 7 but will stop working in Microsoft Excel VBA 64-bit client.
I understood making a 32-bit client to work with a 64-bit COM server can be done using Surrogates and WOW registry entries but even following these guidelines (Hosting a .NET DLL as an Out-Of-Process COM Server (EXE)) to create extra Windows Registry entries in *HKLM\SOFTWARE\Wow6432Node* it doesn't work (I know this is an old post but thought it would still be valid).
I'm running a Windows 10 x64 machine. Am I missing any additional step? Any tips would be appreciated!
Thank you!
It seems "AnyCPU" does the trick when you UNcheck "Register for COM Interop" in project settings.
To register it on user's machine, I'm running this with Admin rights:
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\regasm.exe /tlb /codebase "C:\MyCOM.dll"
C:\Windows\Microsoft.NET\Framework\v4.0.30319\regasm.exe /tlb /codebase "C:\MyCOM.dll"
Then, to remove (also as Admin):
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\regasm.exe "C:\MyCOM.dll" /u
C:\Windows\Microsoft.NET\Framework\v4.0.30319\regasm.exe "C:\MyCOM.dll" /u
But, it seems some entries are left behind in registry.
Isn't "/u" enough for unregistering it?
Thank you.

COM application referenced dlls troubleshooting

I have a WPF application, which I build as a dll COM component and install using installshieldLE, however I have some issues with some dependent dlls, when running my COM client.
My WPF dll references two other C# dlls (A & B) which reside within the same VS2012 solution.
My WPF dll has the register for COM interop option checked and provides a COM interface for running the WPF GUI application.
I have a C COM client program, which tests the WPF application. The problem I am having is that I need to include some of dll_A's referenced dlls, (which is a third party graphics package) in the folder of the client program for the application to run successfully. I don't have to include dll_A or dll_B in the local client directory.
Also, there are other (C) dlls referenced by the COM server dll and included in the installation that do not need to be present in the client directory, so this is difficult to understand.
I assume that this is not a WPF question but simply a question about com server installation in relation to other referenced assemblies.
I have output some debug messages in the primary dlls that confirm that the dlls A&B, along with the main COM dll are being run from the installation location. But I get exceptions further down the line when the third party dlls are missing from the local client folder.
Can someone help me troubleshoot this problem please. I can run the client program successfully from the installation location and am therefore certain that all required assemblies and dlls are present.
Thanks.
It sounds like you're encountering issues related to the DLL load path. A client application can load your COM DLL, but your COM DLL can't load its own dependencies (or dependencies of dependencies, etc) even through the dependencies exist in the same folder as the COM DLL. Is this correct?
If so, I believe this problem can be solved with a call to the AddDllDirectory function -- just have your COM DLL call this before loading any of its dependencies and call RemoveDllDirectory when it's done. For more information, see the Remarks section of the documentation for LoadLibrary.
The problem was caused by one of the referenced dlls being compiled using .Net 4.0, whereas the others were compiled using .Net 4.0 client. Recompiling with .Net 4.0 Client resolved the problem.
The problem seemed to occur when executing the application as a registered com component, with the client being executed from a different location. If the offending dlls were copied to the client directory, everything runs fine.

COM function fails on VBscript but not VB6 on Win64

I have written a COM control in c# .Net 4.5, this COM control uses a 3rd party dll to communicate with a USB device.
On Windows 7 32bit everything works 100% from both VBScript and the VB6 app. On Windows 7 64bit the VBScript fails when calling the 3rd party dll function that uses the USB device.
The exception is: "System.AccessViolationException" with message: "Attempted to read or write protected memory. This is often an indication that other memory is corrupt."
What I don't understand is that the same COM control (and the same USB driver) works when instantiated from the VB6 app, but not from the VBScript.
I have looked at the loaded assemblies and registry access using Process Monitor when running the VB6 app and the VBScript but I cannot see anything out of the ordinary.
Any suggestions of what I can troubleshoot or test next?
Here's the deal. Applications written from VB6 are 32-bit. Your application works on 32-bit Windows and from a VB6 app on Windows 64 (which is running as 32-bit, since VB6 produces 32-bits. So, we know that your DLL works with 32-bit applications.
The thing is, when you run a VB script on Windows 64, it runs as a 64-bit process and you have a mismatch with your 32-bit DLL. If you run the VB script with the 32-bit version of the VB script engine (c:\windows\syswow64\wscript.exe or c:\windows\syswow64\cscript.exe) does it work? It probably will.
Now, if you compiled your DLL with the AnyCPU processor setting, then you can still register your DLL and get it to work with a 64-bit process. Just be sure to use the regasm.exe that is in the 64-bit hive.
For example register your DLL as such,
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\regasm.exe /tlb /codebase c:\path\to\yourdll.dll

Is it possible to mix x64/x86 in a C# Project?

We have a WebService that's been running for a while, there's about 6~ projects on it.
Recently, we had to support a C++ 32 bit library, I tested and I had to set the project's target platform to x86 or I'd get the BadImageFormatException. So this new project is set to compile on x86, but everything else is set to AnyCPU.
After publishing the WebService, I get the error Unable to find ?.dll when calling the function.
Is there anyway I can add this new project as x86 without having to set my WCF to x86 as well, or am I doing something wrong and this should've worked?
It is possible but all binaries (.exe-s and .dll-s) must share the same target platform for it to work. You cannot load a 32-bit DLL into a 64-bit process or the other way around.
If you're hosting your web service under IIS, the target platform of the app pool determines what kind of DLL-s you can load.
If you have exported functions in your unmanaged DLL-s, your P/Invoke declarations must also match the target platform - specifically, if you pass pointers, those will have to be correctly mapped to 32/64-bit pointers. (Usually IntPtr takes care of this.) P/Invoke declarations really turn into possible problems if you support both platforms with a single source base (compiled into platform-specific binaries).
Depending on what you're trying to do, you may also need to deal with handling platform-specific references. This question has more detail about that.

Registration-free Interop between a 64-bit COM dll and a C#/.Net application

I am trying to get registration-free COM interop between a 64-bit COM dll and a C# app to work.
In the answers to a previous question of mine, I got help that allowed me to successfully call a HelloWorld method on the 64-bit COM dll for C#.
However, this was only possible by registering the COM dll globally using regsrv32.exe.
Based on this answer to a related question, I think that I need to set the Isolated flag on the reference of the COM dll to true. However, this leads to the following build error:
Problem isolating COM reference 'ComLibInteropLib':
No registered classes were detected for this component.
The answer to a question on MSDN social seems to indicate that there is a solution for this problem if one can compile a 32-bit version of the dll.
However, my COM interop library needs to link to a 'normal' C++ dll, for which I do not have the source and that is only available as x64.
So my question is: How can I enable the Isolated flag (or otherwise get side-by-side to work) between a 64-bit COM dll and a C# application?
I am happy to use regsrv32.exe on my machine or other developer's machine, but we cannot register any COM dlls on production machines, where the final application must run.
This is a side-effect of the original problem you had, the COM server wasn't getting registered properly. When you Isolated option to true, the build system auto-generates the required manifest entries for you. But the content of the manifest needs to come from somewhere, it uses the registry keys. Since they are not there, it can't generate the manifest.
You can write the manifest yourself but that requires enough insight in what the manifest should look like. With very high odds of making mistakes, the incantations are quite obscure. So avoid that, you just need to get the COM server registered to get ahead. Just on your build machine, it doesn't have to be registered on the client's machine since it will use the manifest.
You mentioned a 64-bit COM server, that's another possible failure mode. The build system is still 32-bit so you'll have high odds that it looks at the wrong keys. HKLM\Software\Wow6432Node instead of HKLM\Software. Battle that problem by building both flavors of the COM server. Beware of having the same kind of problem when you use Regsvr32.exe yourself, there are two of them. The one in c:\windows\syswow64 should be used to register the 32-bit version of the server, the one in c:\windows\system32 for the 64-bit version.

Categories

Resources