Solved

Get CLSID from ocx filename

Posted on 2000-05-18
20
2,366 Views
Last Modified: 2013-11-20
How can I get the CLSID of one control
when I just have the name/path of the ocx file?
0
Comment
Question by:jmartins71
  • 7
  • 5
  • 5
  • +2
20 Comments
 
LVL 11

Expert Comment

by:mikeblas
Comment Utility
You can't.  The OCX file might implement more than one control.

..B ekiM
0
 
LVL 9

Expert Comment

by:ShaunWilde
Comment Utility
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
 
LVL 9

Expert Comment

by:ShaunWilde
Comment Utility
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
 
LVL 11

Expert Comment

by:mikeblas
Comment Utility
> 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
 
LVL 9

Expert Comment

by:ShaunWilde
Comment Utility
> 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
 
LVL 2

Expert Comment

by:wuxz
Comment Utility
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
 
LVL 9

Expert Comment

by:ShaunWilde
Comment Utility
> 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
 

Author Comment

by:jmartins71
Comment Utility
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
 
LVL 9

Expert Comment

by:ShaunWilde
Comment Utility
> 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
 
LVL 5

Expert Comment

by:vachooho
Comment Utility
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
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 

Author Comment

by:jmartins71
Comment Utility
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
 
LVL 5

Expert Comment

by:vachooho
Comment Utility
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
 

Author Comment

by:jmartins71
Comment Utility
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
 
LVL 11

Accepted Solution

by:
mikeblas earned 100 total points
Comment Utility
> 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
 

Author Comment

by:jmartins71
Comment Utility
thank you mikeblas
0
 
LVL 9

Expert Comment

by:ShaunWilde
Comment Utility
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
 
LVL 11

Expert Comment

by:mikeblas
Comment Utility

 > 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
 
LVL 9

Expert Comment

by:ShaunWilde
Comment Utility
> 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
 

Author Comment

by:jmartins71
Comment Utility
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
 
LVL 11

Expert Comment

by:mikeblas
Comment Utility
> 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

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

Join & Write a Comment

Introduction: Database storage, where is the exe actually on the disc? Playing a game selected randomly (how to generate random numbers).  Error trapping with try..catch to help the code run even if something goes wrong. Continuing from the seve…
Introduction: The undo support, implementing a stack. Continuing from the eigth article about sudoku.   We need a mechanism to keep track of the digits entered so as to implement an undo mechanism.  This should be a ‘Last In First Out’ collec…
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
Internet Business Fax to Email Made Easy - With eFax Corporate (http://www.enterprise.efax.com), you'll receive a dedicated online fax number, which is used the same way as a typical analog fax number. You'll receive secure faxes in your email, fr…

771 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

7 Experts available now in Live!

Get 1:1 Help Now