Re: Need help with COM dll registration at runtime
On Mar 12, 5:44 pm, "Igor Tandetnik" <itandet...@mvps.org> wrote:
"Suman" <skar...@gmail.com> wrote in message
[...]
My reference will be one
article found at:
http://www.codeproject.com/com/com_in_c1.asp
Realize that the article describes the hardest, most verbose and
inconvenient way of doing COM. It's great as a studying material, to
understand what's going on under the hood. But for writing everyday
code, there are better ways.
Thanks for the prompt reply! But I liked this article and I do think I
want to go ahead with this :)
I'd love to know about these better ways. Would you mind sharing a
couple
of pointers along those lines?
(I do know about CLSIDFromString() but somehow
just couldn't get past
converting char [] to OLESTR
MultiByteToWideChar. OLESTR is a typedef for WCHAR*, aka wchar_t* .
Yes of course!
Note, I call a function to do register this dll, and uptio this,
[...]
Check that the DLL is indeed registered successfully. Check in the
registry under
HKEY_CLASSES_ROOT\CLSID\{Your CLSID}
Yes, it's registered correctly.
In particular, there should be InprocServer32 subkey under this key,
whose default value contains full path to the DLL.
And, again the correct path is there.
fscanf(fp, "CLSID=%s%*", out);
%* is not a valid format specifier. Does this function succeed? Do you
get expected CLSID when this function returns?
From the [*]scanf man page:
* Suppresses assignment. The conversion that follows occurs as
usual, but no pointer is used; the result of the
conversion is
simply discarded.
Yes, this function does succeed. And I do get the expected CLSID.
My config file looks like this:
CLSID={70108A03-F9E4-4a88-8654-45483B9ADC9C}
....
and I am not interested in anything but the CLSID at this point of
time.
In fact, my interface file has this:
// Our interface implementor object's GUID
// {1A1E2B69-CAF0-4f6d-B08E-6B69D3355E84}
DEFINE_GUID(CLSID_IPTPlugin,
0x1a1e2b69, 0xcaf0, 0x4f6d, 0xb0, 0x8e, 0x6b, 0x69, 0xd3, 0x35, 0x5e,
0x84);
Iff, instead of ri, or some variable where I have copied the CLSID
from the file,
I use this CLSID_IPTPlugin, the code works like a charm. Which leads
me to
think that I am having problems retrieving the CLSID, until and unless
there is
some rule that says, you have to use the identifier declared in the
interface's
header (CLSID_IPTPlugin in this case) and not anything else
(e.g:pluginCLSID).
As I said, part of the code of the same tutorial: Here it is:
-----------------------
<-------------------------------------------------------------------
<--------------------------------------------
int CustomRegister(REFCLSID ri/*HINSTANCE hinstExe, HINSTANCE
hinstPrev, LPSTR lpszCmdLine, int nCmdShow*/)
{
int result;
TCHAR filename[MAX_PATH];
{
OPENFILENAME ofn;
// Pick out where our DLL is located. We need to know its location in
// order to register it as a COM component
lstrcpy(&filename[0], &OurDllName[0]);
ZeroMemory(&ofn, sizeof(OPENFILENAME));
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.lpstrFilter = &FileDlgExt[0];
ofn.lpstrFile = &filename[0];
ofn.nMaxFile = MAX_PATH;
ofn.lpstrTitle = &FileDlgTitle[0];
ofn.Flags = OFN_FILEMUSTEXIST|OFN_EXPLORER|OFN_PATHMUSTEXIST;
result = GetOpenFileName(&ofn);
}
if (result > 0)
{
HKEY rootKey;
HKEY hKey;
HKEY hKey2;
HKEY hkExtra;
TCHAR buffer[39];
DWORD disposition;
// Assume an error
result = 1;
// Open "HKEY_LOCAL_MACHINE\Software\Classes"
if (!RegOpenKeyEx(HKEY_LOCAL_MACHINE, &ClassKeyName[0], 0,
KEY_WRITE, &rootKey))
{
// Open "HKEY_LOCAL_MACHINE\Software\Classes\CLSID"
if (!RegOpenKeyEx(rootKey, &CLSID_Str[0], 0, KEY_ALL_ACCESS,
&hKey))
{
// Create a subkey whose name is the ascii string that represents
// our IPTPlugin2 object's GUID
stringFromCLSID(&buffer[0], (REFCLSID)(CLSID_IPTPlugin)/* ri*/);
if (!RegCreateKeyEx(hKey, &buffer[0], 0, 0,
REG_OPTION_NON_VOLATILE, KEY_WRITE, 0, &hKey2, &disposition))
{
// Set its default value to some "friendly" string that helps
// a user identify what this COM DLL is for. Setting this value
// is optional. You don't need to do it
RegSetValueEx(hKey2, 0, 0, REG_SZ, (const BYTE
*)&ObjectDescription[0], sizeof(ObjectDescription));
// Create an "InprocServer32" key whose default value is the path
of this DLL
if (!RegCreateKeyEx(hKey2, &InprocServer32Name[0], 0, 0,
REG_OPTION_NON_VOLATILE, KEY_WRITE, 0, &hkExtra, &disposition))
{
if (!RegSetValueEx(hkExtra, 0, 0, REG_SZ, (const BYTE
*)&filename[0], lstrlen(&filename[0]) + 1))
{
// Create a "ThreadingModel" value set to the string
"both" (ie, we don't need to restrict an
// application to calling this DLL's functions only from a
single thread. We don't use global
// data in our IPTPlugin functions, so we're thread-safe)
if (!RegSetValueEx(hkExtra, &ThreadingModel[0], 0, REG_SZ,
(const BYTE *)&BothStr[0], sizeof(BothStr)))
{
result = 0;
MessageBox(0, "Successfully registered IPTPlugin.DLL as a COM
component.", &ObjectDescription[0], MB_OK);
}
}
// Close all keys we opened/created.
RegCloseKey(hkExtra);
}
RegCloseKey(hKey2);
}
RegCloseKey(hKey);
}
RegCloseKey(rootKey);
}
// If an error, make sure we clean everything up
if (result)
{
cleanup();
MessageBox(0, "Failed to register IPTPlugin.DLL as a COM
component.", &ObjectDescription[0], MB_OK|MB_ICONEXCLAMATION);
}
}
return(0);
}
-----------------------
<-------------------------------------------------------------------
<--------------------------------------------
Note: cleanup() removes the reg. key in case of failure.
What does CustomRegister do? It is unusual for the client to register
the COM object it's about to use. Normally, the COM object is registered
at installation time.
Well as I explained in my previous post, I was trying to have the dlls
registered
when they are used.