• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 2432
  • Last Modified:

Get CLSID from ocx filename

How can I get the CLSID of one control
when I just have the name/path of the ocx file?
0
jmartins71
Asked:
jmartins71
  • 7
  • 5
  • 5
  • +2
1 Solution
 
mikeblasCommented:
You can't.  The OCX file might implement more than one control.

..B ekiM
0
 
ShaunWildeCommented:
you can always search the registry - to see if it matches in there - not sensible to do in a program but you can use regedit
0
 
ShaunWildeCommented:
or if it has a typelibrary you could load that and parse it - I think there are tools available to do that - that could be a programmatical way
0
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
mikeblasCommented:
> not sensible to do in a program but you can use regedit

Why not?

 > or if it has a typelibrary you could load that and parse it

Again, there may be more than one typelib in the control.

There's no identity between an OCX file and a given CLSID. You can enumerate a list of CLSIDs that are in a given OCX. But that's not the question that's been asked here.

I think you'll find that most efficient way to build that list really is to enumerate entries in the registry.

..B ekiM
0
 
ShaunWildeCommented:
> Why not?

I was thinking of time to complete - if it isn't a problem then go for it - but if it is only for 1 (one) .ocx then use regedit and the find option.
0
 
wuxzCommented:
If you want to get to know this CLSID by your hands, you can use oleview to load this ocx file as a typelib file. But if you want to do this in your program, you should write a lot of codes to parse a typelib.

What do your actually want to do?
0
 
ShaunWildeCommented:
> What do your actually want to do?

that is a point - maybe if we knew what you wnated to do with it we could help :)
0
 
jmartins71Author Commented:
First of all thanks everybody!

In my application I need to switch between activex plugins.
Before I do this I need to get the CLSID from each ocx file the user wants to use. EACH OCX HAS ONLY ONE CONTROL.

Then I register this CLSID in my application registry entries.

The problem is of course how can I know the CLSID (or progID) just by knowing the ocx file that the user wants two use! Just one thing. I first register the control so the entries are in registry. but I am seing the filename like dos!!!

Mikeblas says I can not! That surprise me because if it is so how can Visual C++ wizard knows it when is creating one class for it (by doing add to project - activex)!!!!!

I have found on MSDN the following function:
"
GetClassFile
Supplies the CLSID associated with the given filename.

WINOLEAPI GetClassFile(
  LPCWSTR szFileName,
                  //Pointer to filename for which you are requesting
                  // a CLSID
  CLSID * pclsid  //Pointer to location for returning the CLSID
);

"

But I can not make it work! I am always getting the error code: MK_E_INVALIDEXTENSION

Maybe I am not using a good parameter for szFilename!?
What I am using is :
CString FileName; // with the filename and path of ocx file
BSTR temp = FileName.AllocSysString();

then use temp in szFileName.
0
 
ShaunWildeCommented:
> Mikeblas says I can not! That surprise me because if it is so how can Visual C++ wizard knows it when is creating one class for it (by doing add to project - activex)!!!!!

Visual Studio uses the typelibrary

>GetClassFile
>Supplies the CLSID associated with the given filename.

I thought that was for file extensions (read the remarks)

0
 
vachoohoCommented:
GetClassFile() used only for storage type files - like word's doc, excel's xls etc.

YOu can not use this function for exes.
BUt you always can search registry
HK_CLASSES_ROOT\CLSID\Inprocserver32 for file name of your OCX.
Be careful - path/filename may be converted to short.
0
 
jmartins71Author Commented:
Thanks,

I have found my file entry in win32 reg key!? Is this the same or was it generated by VStudio!?

Can I use this?

the path was HKEY_CLASSES_ROOT\typelib\(clsid)\1.0\0\win32


I have found as I say one file entry but has the ~chars (dos name files)

Two questions:
1) I do not know how to convert from my CString file to one dos filename.
2) How to begin one registry search?
Can you give me one api function for me to start.




0
 
vachoohoCommented:
all functions working with registry starts with Reg...
RegOpenKey
RegCreateKey
RegQueryValue
etc

or you can examine ATL's CRegKey class
it simplifies work with registry


http://www.codeguru.com/system/CRegKey.shtml
0
 
jmartins71Author Commented:
Ok,
I know CRegKey. But here is what I have found for my control:

HKEY_CLASSES_ROOT\CLSID\Inprocserver32
with "E:\TEMP\DUMMYP~1\DEBUG\DUMMYP~1.OCX"

Now I have "E:\TEMP\DUMMYPlatform\DEBUG\DUMMYplatform.OCX"

How to :
1)convert to string woth the dos limitations.
2) Query this key when I do not know the clsid to open it!?

Sorry but I am not understanding how to make registry queries on subkeys when I do not know the keys!?

0
 
mikeblasCommented:
> That surprise me because if it is so how can Visual C++ wizard knows it when
 > is creating one class for it (by doing add to project - activex)!!!!!

I'm sorry: I can't understand what you're saying.  You seem to be talking about the wizard that lets you add some wrapper classess from an ActiveX control.  That doesn't seem to be relevant to your problem, as using that feature involves selecting a control by it's registered object name, not by selecting a file name.  You're asking about selecting a file name.

 >  2) Query this key when I do not know the clsid to open it!?  

You can use the RegEnumKeyEx() API. I guess I'm becoming more and more lenient--I normally never write code for so few points.  But let me help you out. Here is a program you can build from the command line:

-- begin file findctl.cpp --

// compile with
//   cl findctl.cpp



#include <windows.h>
#include <stdio.h>

#define ELEMENTS(x)  (sizeof(x)/sizeof(x[0]))

#pragma comment(lib, "advapi32.lib")

const char* stristr(const char* pstrLeft, const char* pstrRight)
{
   int nRightLen = strlen(pstrRight);

   while (*pstrLeft)
   {
      if (toupper(*pstrLeft) == toupper(*pstrRight))
      {
         if (strnicmp(pstrLeft, pstrRight, nRightLen) == 0)
            return pstrLeft;
      }
      pstrLeft++;
   }

   return NULL;
}

int main(int argc, char* argv[])
{
   // check the arguments, print usage if no arg
   if (argc != 2)
   {
      printf("Usage:\n");
      printf("\tfindctl <matchname>\n");
      return 1;
   }

   LONG lRetVal;
   DWORD dwIndex = 0;

   // try to open the HKCR\CLSID hive for enumeration
   HKEY hKeyCLSID;
   lRetVal = RegOpenKeyEx(HKEY_CLASSES_ROOT, "CLSID", 0, KEY_READ, &hKeyCLSID);
   if (lRetVal != ERROR_SUCCESS)
   {
      printf("Couldn't open HKCR\\CLSID!\n");
   }
   else
   {
      // enumerate each CLSID on this system
      do
      {
         char szBuffer[1024];
         DWORD dwBufLen = ELEMENTS(szBuffer);

         lRetVal = RegEnumKeyEx(hKeyCLSID, dwIndex, szBuffer, &dwBufLen, 0, NULL, NULL, NULL);

         if (lRetVal == ERROR_SUCCESS)
         {
            // if we've got one, try to open its InProcServer32 key
            char szFullName[1024];
            strcpy(szFullName, "CLSID\\");
            strcat(szFullName, szBuffer);
            strcat(szFullName, "\\InProcServer32");
//          printf("%s\n", szFullName);

            HKEY hKeyCurrent;
            LONG lOpened = RegOpenKeyEx(HKEY_CLASSES_ROOT, szFullName, 0, KEY_QUERY_VALUE, &hKeyCurrent);

            if (lOpened == ERROR_SUCCESS)
            {
               // if there's an InProcServer32 key, get its value
               char szFileName[1024];
               DWORD dwType;
               DWORD dwNameLen = ELEMENTS(szFileName);

               if (ERROR_SUCCESS == RegQueryValueEx(hKeyCurrent, NULL, NULL, &dwType,
                     (LPBYTE) szFileName, &dwNameLen))
               {
                  if (dwType == REG_SZ || dwType == REG_EXPAND_SZ)
                  {
                     // compare the server's file name with the name we were offered
                     // print 'em out, if there's a match
                     if (stristr(szFileName, argv[1]) != NULL)
                     {
                        printf("%s: %s\n", szBuffer, szFileName);
                     }
                  }
               }
               RegCloseKey(hKeyCurrent);
            }
         }

         dwIndex++;
      } while (lRetVal == ERROR_SUCCESS);

      RegCloseKey(hKeyCLSID);
   }

   return 0;
}


-- end file findctl.cpp --

This does what you want, but it also proves my point. On my machine, I have an OLE Control called Threed32.OCX.  It registers several different class IDs. My program finds them all:

{0BA686AA-F7D3-101A-993E-0000C0EF6F5E}:      C:\WINNT\System32\Threed32.OCX
{0BA686AE-F7D3-101A-993E-0000C0EF6F5E}:      C:\WINNT\System32\Threed32.OCX
{0BA686AF-F7D3-101A-993E-0000C0EF6F5E}:      C:\WINNT\System32\Threed32.OCX
{0BA686B3-F7D3-101A-993E-0000C0EF6F5E}:      C:\WINNT\System32\Threed32.OCX
{0BA686B4-F7D3-101A-993E-0000C0EF6F5E}:      C:\WINNT\System32\Threed32.OCX
{0BA686B8-F7D3-101A-993E-0000C0EF6F5E}:      C:\WINNT\System32\Threed32.OCX
{0BA686B9-F7D3-101A-993E-0000C0EF6F5E}:      C:\WINNT\System32\Threed32.OCX
{0BA686BD-F7D3-101A-993E-0000C0EF6F5E}:      C:\WINNT\System32\Threed32.OCX
{0BA686BE-F7D3-101A-993E-0000C0EF6F5E}:      C:\WINNT\System32\Threed32.OCX
{0BA686C2-F7D3-101A-993E-0000C0EF6F5E}:      C:\WINNT\System32\Threed32.OCX
{0BA686C3-F7D3-101A-993E-0000C0EF6F5E}:      C:\WINNT\System32\Threed32.OCX
{0BA686C7-F7D3-101A-993E-0000C0EF6F5E}:      C:\WINNT\System32\Threed32.OCX
{2F155EE4-C332-11CD-B23C-0000C0058192}: C:\WINNT\System32\Threed32.OCX


Like I said, there's on one-to-one mapping between a server executable and OLE objects. A module can support more than one OLE control class--and, in efficient designs, often does!
You can't know "the" CLSID of an ole control given the file name.

..B ekiM

0
 
jmartins71Author Commented:
thank you mikeblas
0
 
ShaunWildeCommented:
If these are in-house objects and you still have the source you could always add a new exported function called something like GetOCXCLSID(CLSID * pCLSID) or something like that and make your task easier
0
 
mikeblasCommented:

 > If these are in-house objects and you still have the
 > source you could always add a new exported function
 > called something like GetOCXCLSID(CLSID * pCLSID) or
 > something like that and make your task easier

I guess that might make the task a little easier, but it makes it very inefficient. Pawing through the whole HKCR\CLSID hive of the registry is going to be faster than loading a DLL, initializing it, and calling an entry point on it.

..B ekiM
0
 
ShaunWildeCommented:
> Pawing through the whole HKCR\CLSID hive of the registry is going to be faster than loading a DLL, initializing it, and calling an entry point on it

Really - I'd have thought it would be the other way round. I may do some tests if I ever need to do such a thing
0
 
jmartins71Author Commented:
I just want to make the following comment about How I have done it.

I have followed ShaunWilde comment because:

Since I have to register the control
I need to Load the DLL. The only thing I must do is to invoke another export function!
So, at least in my case is really better then parsing the registry.
0
 
mikeblasCommented:
> Since I have to register the control

Oh. If you've got to load and install the control anyway, then it probably is better just to go poking for that extra export.

..B ekiM
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 7
  • 5
  • 5
  • +2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now