I have developed an integration for an ActiveX control. The problem is that during development, a new build was created, which means there is a different ActiveX Class ID.
Is there any way to determine the Program ID and ActiveX class ID of a COM object without contacting the developer?
Researching online, I found reference to OLE/COM Object Viewer, but there doesn't seem to be any way to do a search outside of expanding every node.
Thank you in advance for any suggestions.
You can certainly see the CLSIDs if you have a type library for the COM server and can look at it with Oleview.exe. You don't have to look at every node in the tree, only the coclass nodes are relevant.
You however cannot see the ProgId in the type library. One way to find it is to use the Edit + Find command in Regedit.exe, paste the CLSID guid you got from the type library.
You get everything when you use SysInternals' ProcMon utility. Start it up, then register the server with Regsvr32.exe. You'll see the trace of the program writing the registry keys in the ProcMon output.
Related
I have created a basic COM DLL with ATL on VS2012. It's called testCOM.dll and it only has one class called CSimpleObj. CSimpleObj has just one method called addValues which adds two values.
I've registered the DLL with Windows 7 64-bit. In VBA, I manually add a reference to the DLL and the below code works properly
Dim Obj As New testCOMLib.SimpleObj
MsgBox Obj.addValues(1,2)
And it give a message with number 3.
Now If I run the vbs which includes:
Dim Obj
Set Obj = CreateObject("testCOMLib.SimpleObj")
It constantly gives an error and is not able to create the object. But if I use the "Excel.Application" ProgID (as an example) for the CreateObject method, it works fine.
I think there is an issue with registering the DLL. I've checked the registry, and the keys for the COM and the type library is already there.
What should I do?
There are three basic requirements to get your COM server to be usable from VBScript:
You need to implement IDispatch so late binding is supported. Not usually a problem with ATL, it implements it by default when you use the wizards.
Your registry script (.rgs) must write the ProgId to the registry. Notable is that you didn't report finding it (look for HKCR\testCOMLib.SimpleObj with Regedit.exe to verify). Its CLSID subkey must match the CLSID in the registry so COM can find your DLL. The ATL Simple Object wizard has a trap, it fills in all the fields when you type the short name. Except for the ProgID field. So very easy to forget.
On the 64-bit version of Windows, you'll execute the 64-bit version of cscript.exe by default. It will not be able to find your 32-bit COM server. You'll need to either build the x64 version of your server or you'll need to use the 32-bit version of cscript.exe, located in c:\windows\syswow64. Not usually a problem with VBA since it tends to be used from a 32-bit version of Office.
The SysInternals' Process Monitor utility is very useful to diagnose these kind of problems. You'll see cscript.exe searching the registry for the keys that your server registered. And probably not finding them, you were however not explicit enough about actual error message you got.
(Note: Names and GUID have been changed from original values)
While debugging an application, I found that a likely culprit for a bug I had was in a library my application was linking with, in the function
pAgent->raw_Open()
agent is declared in our C++ code as
XX::IAgentPtr pAgent
All Visual Studio can tell me about IAgentPtr is that its type is
_com_ptr_t<_com_IIID<XX::IAgent,&_GUID_deadbeef_1234_1234_1234_1234deadbeef> >
And my debugger cannot step into the code of agent->raw_Open() to see what's going on. I'd like to know which DLL defines XX:IAgent, as I may be able to get debugging information or source code for that DLL.
I've figured out that IAgent is a COM interface, and through searching elsewhere, I found that I might be able to find the location of the DLL file by looking in the registry (HKEY_CLASSES_ROOT\CLSID\{guid}). However, I could not find the GUID I'm looking for there.
How might I find the DLL that contains the definition for IAgent given that I know IAgent's GUID?
(Note: Although they have similar titles, this question is not a duplicate of this question, as the asker of the linked question knows the DLL which defines the interface with the GUID)
A program that can search through binary files to find plain text data will work.
I used Windows Grep and searched all DLL files for "deadbeef-1234-1234-1234-1234deadbeef" and found the DLL which defined IAgent.
However, there is a better way to find this information. HKEY_CLASSES_ROOT\CLSID\ has subkeys for objects, but IAgent is an interface. If you know the GUID of the interface, you can look in HKEY_CLASSES_ROOT\Interface\{guid}. There, if you find a key TypeLib, the default value is a GUID that you can find in HKEY_CLASSES_ROOT\TypeLib, and from there you can find the path to the dll. If that isn't there, the default value in a key called ProxyStubClsid or ProxyStubClsid32 is a GUID that can be found in HKEY_CLASSES_ROOT\CLSID.
I have a vb6 program that needs to use MSOLAP80.dll to display its pivot tables properly. But because MSOLAP90.dll has some compatibility issues with this I cannot use MSOLAP90.dll and still have the pivot tables display.
I have registered MSOLAP90.dll and then registered MSOLAP80.dll again and everything seems to be fine. I however don't know if both are actually registered or if MSOLAP80.dll is the only one registered, because I have no reference point as to what is new in MSOLAP90.dll. Is it possible that both are registered and the program is just using MSOLAP80.dll and if there are programs that need MSOLAP90.dll then it will know to use that one?
I guess I am just confused about how registering DLL's work and if it is possible to have both of these registered at the same time. Can somebody help with an explanation?
If you want to know for sure which one is registered, you can:
Look at the References dialogue for a type library which matches your DLLs' paths.
Open up RegEdit, and search for MSOLAP80.DLL or MSOLAP90.DLL (uncheck "Match whole string only").
If you find references for both DLLs, then you are safe because you can bind to a specific version. If you find a reference to the wrong DLL, then unregister the wrong one, and register the right one.
COM originall only allowed one version of a set of CLSIDs (which uniquely identify classes), IIDs (which uniquely identify classes' interfaces) at any one time. It is possible to have more than one reference to a LIBID (which identifies a type library - a resource embedded in the DLLL) but they have to have different versions.
From Windows XP onwards, it became possible to do side by side DLL access in which an executable can access a specific version of a DLL, overriding the value in the registry. You need to embed or have a .manifest file in the same folder as the EXE file.
Unfortunately, the documentation for this seems to have disappeared from MSDN, and is only referred to by a couple of Knowledge Base articles:
http://support.microsoft.com/kb/828629
http://support.microsoft.com/kb/843524
I have a native app that has an .OCX file that needs to be registered for it to be used in a .NET application.
Now currently there's different versions of this .OCX on the machine. Can someone please explain how this can affect the registration of this new (updated) .OCX file registration?
And how does my .NET app know which object to create from which .OCX file?
COM servers are required to change their CLSID guids if their interfaces are no longer compatible. So if your supplier did it right, you should be able to register both of them and get the right one when you use the right reference in your project.
Like any rule, this one got violated often and is presumably the reason you started this question in the first place. The back-up plan is to use registry-free COM, you write a manifest and add it to your program so it always uses the local copy of the COM server DLL instead of the one that was registered. Find out how to do this by googling "regfree COM", I see many relevant and useful hits at the top.
I believe COM class registrations include the entire path to the "server" providing the COM component. If the two versions of the .OCX have different class GUIDs, then there should be no issues.
I have been trying to load a OCX file into one of my VB6 projects for most of the day today. I've tried checking the COM registration in the registry the best that I know how, and have attempted several times using REGSVR32 on the file to no avail. All I keep getting from VB6 when I try to load the component (Under Project --> Components) is 'FilePath\FileName.ocx' could not be loaded. Has anyone else seen this before, and if so, any ideas how to fix it?
Just a couple of tips to help isolate the problem....
Look at the control with OleView
Examine the name: if it is one of the reserved words such as 'Menu', vb6 will fail to load it. (Although vb6 will happily let you create (and use) one with a bad name until it is saved and reloaded)
Examine the interface: does it describe the functionality? You may have a damaged or unlicensed ocx.
Attempt to load it with the ActiveX Control Test Container...
If you can, the problem is with VB6 and not the ocx.
This it may be a dependency issue -- some other component needed by the OCX is not present. Dependency Walker will find any static dependencies.
We fixed similar error recently. In our case the error was in the Visual Basic project (.vbp) file. Project file had been edited outside standardized build machine and contained references to OCX components - including workstation specific paths & versions of the components.
You can either edit the the project file in text editor or get a working version from version control.
Un-registering and registering again worked for me too.
Please note that you need to register this component using this syntax:
regsvr32 /i:design olch2x8.ocx
When you say you have used "REGSVR32 on the file to no avail" do you mean that you get a file name succeeded message, or an error message? If registering the file succeeds CMB is likely right about the ocx being unlicensed.
Licensing aside, there are a couple of other trip points with vb6. Especially if the OCX was developed in VB6.
If so, the 'officially' system registered version may conflict with the specific ocx you're using. In other words, both of them might have the same proper name (or classid) but the one you're attempting to use may not implement all the functionality described in the system registered one (i.e. you have a less evolved version). This arises when the author desires to maintain binary compatibility while enhancing the functionality of a control. As long as the public interfaces remain compatible, vb will not recalculate the classid.
You can fix this by forcibly unregistering the specific control (actually unregister all instances of the control). (regsvr32 /u control.ocx ) Then re-register the one you intend to use. Be certain that no running instance of VB6 exists when you do this or the results might not work. (Check your task list)
Hope that helps...
The control may be reliant on another DLL or OCX that may be missing or not registered and this could manifest itself as VB reporting that the control you're trying to use is missing. However, I'm not sure how you would identify the dependencies. As far as I know, dependency walker identifies static dependencies; I'm not sure if it can identify COM dependencies.
Un register the Ocx
re register the ocx
then loaded the project again in VB6, it worked for me.
Thanks everyone