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.
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.
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 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.
Right, initially ran:
c:\regsvr32 Amazing.dll
then, (accidentally - I might add) I must have run it again, and (indeed) again when new versions of 'Amazing.dll' were released. Yes - I know now I should've run:
c:\regsvr32 /u Amazing.dll
beforehand - but hey! I forgot.
To cut to the chase, when add the COM reference in VS, I can see 3 instances of 'Amazing' all pointing to the same location (c:\Amazing.dll), running regsvr32 /u removes one of the references, the second time - does nothing...
How do I get rid of these references?
Am I looking at a regedit scenario? - If so - what exactly happens if I delete one of the keys???
Cheers
Your object's GUID's should not be changing. In other words, once you register the COM object, re-registering shouldn't be adding anything additional to the registry.
Unless you added additional COM interfaces or objects to the project.
In any case, if this is a one time deal (and it sounds like it is), open regedit and delete the unneeded keys manually.
There's a tool by MS that is still floating around and has been since Win95 days which scans the registry and does stuff like finds COM keys that aren't pointing at a valid file anymore etc called RegClean (I found it here: http://downloads.zdnet.com/abstract.aspx?assetid=881470&node=2094) which I've seen some places still using particularly when messing with legacy COM stuff in VB which are generating new COM GUIDs after every build.
So if you got that, then unreg'd and deleted or moved the file, run the app and it will clean out the "orphaned" entries.
If you do decide to remove the keys using RegEdit, you might need to remove the class ids as well as the guid entries.
I've got myself into a horrible mess with COM before. I had to pick my way though the registry deleting each reference, unfortunately.