I have a COM DLL written in unmanged C++, and compiled with VS 2010. I can register the DLL using regsvr32 and I can invoke it via VBscript.
When I try to add a reference to it, while creating a C# client, I don't see the COM object listed in Add Reference -> COM tab. If I manually browse to the DLL and try to select it, it says that the DLL is not a valid assemlby or COM component.
Now, I can use tlbimp tool to generate an interop DLL and use that to add as a reference to my C# client. And everything works fine.
My questions are:
Why the original COM is not listed in COM tab in Add Reference dialog when it's registered via regsvr32?
Why does VS IDE think that it's not a valid COM when I can invoke it from VBScript and C++ native code?
What exactly does tlbimp do which the IDE can't do?
What do I need to read further to improve my understanding of the
type libraries and interoperability at play here?
Looks like a typelib issue -- your COM classes may be have been registered correctly, but your typelib probably is not. Maybe you forgot to invoke RegisterTypeLib from within your DllRegisterServer function?
Referring to your questions:
The dialog looks for registered typelibs, not for COM classes
VBscript invokes IDispatch and does not care about typelibs. tlbimp does not care about IDispatch and requires a typelib
You passed the DLL name to tlbimp -- so tlbimp knew how to get hold of the typelib. VS, in contrast, refers to the registry which lacks the approriate registration data
Related
In Visual Studio (C#), ticking 'Register for COM interop' updates the Windows environment such that my Visual Studio project, its dependent Visual Studio projects (in same solution) & dependent DLL files are all available for another COM-consuming application on the same machine. This COM-consuming application works with no issue.
If I want the same COM objects to be available to a consuming application on another machine, what must I do?
I assume I still build with the same flag set (so that the DLL files have COM content)? I assume I must register the COM DLL file (e.g. regasm) - Unfortunately this doesn't work - do I register every DLL file that I am constructing & every DLL file library they reference?
Please make no assumptions about my COM knowledge.
You don't quite provide enough information to answer with certainty, but there are enough hints to guess at what you are doing.
When your client app asks for the COM object, the .NET runtime is invoked and it locates the COM-exposing assembly DLL from the information stored by RegAsm (specifically by the /codebase parameter). But after that, it's all .NET assembly loading rules - including the loading of dependencies.
If your COM assembly has dependencies, the dependent assemblies must be locatable from the client process. It doesn't matter whether the dependencies are in the same folder as the COM DLL - the one loading those dependencies is the process, not your COM DLL. The .NET runtime uses a process called Fusion to decide where to look for .NET assemblies.
You have two practical choices:
Put the COM DLL, its dependencies and the client EXE all in the same folder. This works if there is only one client, and you control the client (so, don't do this if the client is IIS, for example). It's the simplest solution.
Give all the .NET components a strong name and deploy them to the GAC1. You still have to run RegAsm; but don't use the /codebase argument.
It is also possible to customize the Fusion rules by giving the client app a manifest with the proper entries, but that's too much of a hassle. The other options are more practical.
If this doesn't describe your problem, then I would use a combination of SysInternals' (now Microsoft's) Process Monitor and the .NET fusion log functionality to look into where the process is seeking the different DLLs.
1Technically you don't have to put the main COM DLL in the GAC, but it makes no sense to use /codebase for the COM DLL when you have to deal with GAC anyway. At that point you might as well put them all in the GAC
I have a COM DLL (MyWrapper), with a COM ATL Object (class) defined inside. This COM dll is basically to be an interface between my WPF .exe and native MFC DLLs.
Everything works perfectly fine until I put the COM DLL in my source control to check in the code. I put the Pre and post build events to copy the DLL to our desired location. when I compiled I got the error.
Unable to register the dll. Try enabling per user redirection
I enabled the option in linker. The DLL compiled and copied to the directory successfully. Then I tried to add the reference to the WPF project, it gave me the following error
A reference to MyWrapper.dll" could not be added. Please make sure that the file is accessible and that it is a valid assembly or COM component
When I remove the pre/post build events and then add the reference, everything works great. I loaded the DLL in Dependency walker it shows IESHIMS.dll is missing.
I have tried to register the DLL using regsvr32 but that returns an error:
The module 'MyWrapper.dll' was loaded but the call to DllRegisterserver failed with error code 0x80070715.
I have admin rights on my machine and am running Visual Studio as administrator.
In the postBuild events, I created a Proxy dll of the COM and added that dll in my WPF application. This solved my problem.
I have an ATL COM component(.exe) (VC++ ) in VS2008. Through VB6 client, i use CreateObject and get the object.
But once the component is updated to VS2010 SP1, the VB6 client no longer is able to create the COM object.
If I compile the VS2010 COM component in debug mode and get the .exe, VB6 client is working fine.
In release mode, .exe is generated without any errors, and VB6 client fails saying ActiveX component cannot be created.
Please help me in resloving this.
Finding out why COM refuses to create an instance of some CoClass is really a PITA. All you get is some generic error code that won't help you very much. If you use the run-time library via Dlls, you should check whether those can be found outside of the debugger. I use the COM/OLE viewer to check whether I can create objects of a CoClass, so that I can rule out that the problem has anything to do with VB. Good luck.
Stuart
I have a Visual C# Project that is fairly basic (no more than 100 lines) but it includes some 3rd party DLL references. Running the project on the computer it was developed on has it run just fine.
In Microsoft Visual C# 2010 Express, I go to Project->Publish <project name> and it builds some files including a setup.exe installer.
When I move those files to another computer and run the setup.exe, it correctly installs the program.
But when I run the program, it simply closes out saying:
ProjectName.exe has encountered a problem and needs to close. We are sorry for the inconvenience.
The command window also appears for a brief second with some errors, but it's hard to make out what it is saying. It looks something like:
Unhandled Exception: System.Runtime.InteropServices.COMException: Retrieving the COM class factory for the component with CLSID { ....... } failed due to the following error: .....
I'm unable to get the command window to stay, so I cannot get the full message. But I assume this is due to the other computer not having those 3rd party DLLS.
How can I have Visual C# 2010 package everything including DLLs so this error does not appear? Or if that may not be the actual issue, how can I stop the command window from instantly vanishing? (I do not know the full list of DLLs required)
Or if the DLL is a registered DLL under C:\Windows\system32, is the project never going to build that into the package? Is there a way to see what it depends on?
Visual Studio 2010 Express doesn't create fully functional installers, but only ClickOnce installers, and those also with limited functions. This kind of installer can't register COM DLLs.
What seems to be wrong in your case is that you are using a COM DLL which isn't registered on the target system. You could try to check that in your own program (like trying to create the class and catch any exceptions that are thrown by the CreateObject function), and call RegSvr32.exe /s in order to register it. Or you just do this when the program starts the first time, before you create any object from the DLL... haven't tried that, though.
You could also make sure that you register the DLL manually on the target system before you run your program.
Moreover, when .Net uses a COM DLL, it usually creates a compatibility assembly which wraps the COM DLL and makes it accessibly to .Net. In case the DLL you use is only this compatibility assembly, you might have to locate the COM DLL it depends on manually on your system and to include it explicitly in your project's files.
In order to debug, it should be enough to put try / catch blocks around CreateObject. If that doesn't help, try adding an eventhandler for the event that is raised when an exception isn't handled by the application (this might be different according to the kind of application you create).
Using the VS2008 wizard, I have created a Service (That does nothing currently other than Start and Stop)
I wish to use an (out of process) COM object
If I add a #import "object.tlb", then recompilation gives
error C2812: #import is not supported with /clr:pure and /clr:safë
Changing properties to use /clr (not pure or safe), allows compilation, but install of the service fails with "Ättempt to load an unverifiable executable with fixups"
Any advice appreciated
Peter
It is explicitly mentioned in the MSDN article for InstallUtil.exe:
Note that you cannot deploy a Windows service created using C++ with
Installutil.exe. Installutil.exe cannot recognize the embedded native
code that is produced by the C++ compiler. If you attempt to deploy a
C++ Windows service with Installutil.exe, an exception such as
BadImageFormatException will be thrown. To work with this scenario,
move the service code to a C++ module. Then, write the installer
object in C# or Visual Basic.