I have a COM .dll registered successfully with regsvr32 but somehow CoCreateInstance() fails to create one of its interfaces. Is there a freeware tool which can determine the reason for the failure?
First of all, check the return value of the CoCreateInstance() call. Second, you can use a tool like Regmon or Process Monitor to see what registry lookup fails. This way, you can quickly determine what exactly wasn't registered the way you'd expect it to be.
If your com dll is implemented in C++ & has debug info, you could also try debugging with MSVC to step into CoCreateInstance.
My guess is that you missed associating your class with one of the interfaces properly. I've done that a number of times by mistake. If you're using ATL you need to make sure your implementing class derives from the interface & also you have added COM_INTERFACE_ENTRY(I____) for your interface in the COM_MAP:
BEGIN_COM_MAP(CFileHelper)
COM_INTERFACE_ENTRY(IFileHelper)
COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(IStream)
COM_INTERFACE_ENTRY(ISupportErrorInfo)
END_COM_MAP()
Or maybe the GUID differs between the IDL file and what's in the implementing C++ file. MSVC6 has an annoying bug where if the wizard fails to create a new class because of file permissions (e.g. some of the files it wants to change are read-only) but it has already added a GUID to the IDL file, and you fix the file permissions and go to do it again, there will be an inconsistency in the GUIDs and it's a pain to catch this. In an ideal world, the GUID definitions would reside ONLY in one file and then you wouldn't have to worry about this.
If not that, sometimes there are weird errors regarding marshaling & apartments but that only pops up if you've got multiple threads and are sending interface pointers across thread or interface boundaries.
Related
I am working on greatly simplifying an old MFC application, and I'd like to use that opportunity to remove a dependency on a certain third-party ActiveX library that has been causing headaches. I first simply tried to remove all references to these controls in the cpp code. It compiles fine, but when installed on a new computer, it crashes if the library .msm file is not included in the setup project.
The problem now is that I don't know where any remaining references to these objects in the project is, and therefore have no easy way of tracking them down and removing them. Simply using the Find-functionality in VS only returns results in cpp files which I've already cleaned up, not any control instances in f.ex. dialog resource files. Is there a way to search for all these objects in the project, or check for them compile-time so that I can use compile errors to see where any library objects remain?
First of all: CoCreateInstance, CoGetClassObject are the normal ways how COM Objects are created. Should be easy to set break points here or to set a hook to monitor what's going on.
Seams that you have a bad error handling in you software. Otherwise you application should show an error message if an object could not be created.
Try to debug.... use remote debugging, even a crash dump will lead you to the code location.
Easiest approach: In your development machine. Try to look into the output window and see if any of the old ActiveX DLLs gets loaded. Trigger down to the location were any of those objects is created.
You can do the same with remote debugging on the test machine.
http://s4.postimg.org/bkprrelpp/6210.gif
Can someone explain this to me? I set my MCMS.Primary output as instructed by this page.
http://mdc.custhelp.com/app/answers/detail/a_id/19889/~/using-visual-studio-2013-professional-to-build-a-microsoft-visual-basic
I set the registration type to Extract COM information, the Scan At Build to Dependencies and Properties, and checked the COM Interop. But I'm getting an error and a warning after trying to build the project. I tried the help page that pops out after clicking the error message. But I can't find the components view it was referring to. What I want to know is how much important this COM Interop is. And also why sometimes when I build the project the error does not appear. But mostly it does.
One suggestion of that help page told me to register the item mentioned in the error message. An .exe file.
COM extraction is useful for turning self-registration routines into Windows Installer table data. COM Interop is the equivalent for registering managed assemblies for use via COM Interop. In both cases, the resulting registry keys are used to allow other DLLs to instantiate your COM server.
So the fundamental question you have to answer here is whether MCMS.exe is a COM server and registers any such data. If it is and does, then something is wrong with the extraction, and this is a problem. However if MCMS.exe is not a COM server, or does not actually register any relevant COM data, you may need to disable COM extraction.
I have a unmanaged C++/ATL in-process COM object (in Unmanaged.dll) that I'm trying to use from a managed C# DLL (Managed.dll). However, I want I want to use registration free COM. I have it down to these steps:
Register the COM object on the development machine. The in-process server must have a properly registered type library.
Add a reference to the COM object within the C# project, and then set the Reference Properties to Isolated = True.
This produces Unmanaged.dll, Managed.dll, and Native.Managed.manifest. Opening the manifest, it's pretty clear how the system uses it to load the COM object in a registration-free way.
Here's the rub. I have a managed EXE (Managed.exe) which dynamically loads Managed.dll to access public types. What I mean by "dynamically" is, it uses Assembly.LoadFrom("Managed.dll"). When the code inside Managed.dll tries to create the COM object, it gets a "class not registered" exception. It appears the activation context doesn't get setup correctly when Managed.dll gets loaded.
Is there a way to get registration free COM to work in this scenario?
Two days without an answer, so here's what I've come up with in that time...
It does indeed look like the activation context is setup by the OS at process launch based on the manifest associated with the main EXE. That means all registration-free COM related elements must be in the Main.exe.manifest at the time the process is started. This breaks the isolation between EXE and DLLs. If a DLL is responsible for creating COM objects, you wouldn't expect the EXE manifest to have to contain the reg-free COM information. You might have expected the manifest associated with the DLL to be merged into the process activation context at the time the DLL gets loaded, but it does not.
To work around this, the DLL must configure a new activation context before creating the COM object. To make things worse, there is currently (as of .NET 4.0) no managed way to do this. So, the DLL will have to PInvoke the following Win32 functions:
CreateActCtx
ActivateActCtx
DeactivateActCtx
ReleaseActCtx
I wrapped these calls with a managed class that calls CreateActCtx and ActivationActCtx in the constructor and DeativateActCtx and ReleaseActCtx in IDisposable::Dispose.
A change needs to be made in a DLL. The DLL was originally coded in VB6 (not by me), and the source code lost.
It is very simple in its functionality, so I recreated it from scratch, but I only have access to VB Express 2008.
I created it first as a normal DLL then realized it had to be a COM DLL. Fortunately, an excellent article at http://www.codeproject.com/KB/COM/nettocom.aspx tells me how.
But, I don't know anything about GUIDs...
Should I use the same GUID as the original DLL or not? Does it make any difference?
Edit: Does it really matter since it's a COM DLL? It is called into by an Active X control & I can see no reference in the web page to the GUI ... (but I'm just a n00b, so what do I know? ;-)
If you want this library to be a direct replacement of the original and it is fully binary compatible (all interfaces are unchanged) - then yes, you should use the same GUIDs for the class ids and interface ids. If you don't do that users of the original library will not be able to use yours without recompiling their programs.
Beware that binary compatibility is a must for reusing the GUIDs. If you break any interface - change its id and the id of the class implementing it and recompile the client.
The GUIDs acts as a kind of identifier for your COM object and DLL. If you use the same GUID you need to register your new DLL so that the location is updated (i.e. if you don't place it exactly in the same spot and have recreated all interfaces the old DLL previously had registered).
The cleaner approach is to generate a new GUID and modify the caller to use the new GUID/DLL instead.
I want to create a small app to add and remove user defined context menu entries from the registry. To make this, somehow I need to get the CLSID of an arbitrary DLL so I can back up previous entries if they exist before writing new ones.
Although regsrv32 somehow manages to create this magical number, I didn't find any way to get that number myself.
I hope there is something better than this:
scanning registry for the DLL name
if not found, register it, scan again, and then unregister it again
If the DLL has been renamed, I can see a possibility for problems.
You could consider calling LoadTypeLibEx on the DLL specifying REGKIND_NONE and then examine get the TypeLibInfo information available via the ITypeLib interface passed back to you.
There's some information about this sort of thing on MSDN. It's an old VB6-focused link but has useful information about inspecting COM components in this way.
You could try to use RegOverridePredefKey() to intercept what regsvr32 does to the registry - call RegOverridePredefKey(), then reproduce what regsvr32 does - LoadLibrary() the COM server, call DllRegisterServer() - then inspect the changes done. With RegOverridePredefKey() you will isolate the changes and not let them become persistent.