Do not register calling an ActiveX Dll

Source: Internet
Author: User
Tags bool uuid

Do not register calling an ActiveX Dll
(by LINGLL completed on 2006-2-7 13:45)

Each ActiveX DLL should have a DllGetClassObject function that can be used to create the required COM object directly, without having to pass through the registry (or register).

Stdapi DllGetClassObject (
Refclsid Rclsid,//clsid for the class object
REFIID riid,//reference to the identifier of the interface
That communicates with the class object
LPVOID * PPV//address of output variable that receives the
interface pointer requested in RIID
);

Here you have to know two things, one rclsid, the CLSID of the COM object that needs to be created, and the other is the ID of riid, an interface to the object.
However, calling DllGetClassObject does not directly create the desired object, but can get the corresponding iclassfactory, and then iclassfactory.createinstance get the desired object.
The VB implementation code is probably as follows:
Need to use a library, Http://www.mvps.org/emorcillo/download/vb6/tl_ole.zip
(Citation page, http://www.mvps.org/emorcillo/en/code/vb6/wbframe.shtml)
In addition, the ActiveX DLL is referenced into the project, where it is not necessary to register it, but to facilitate the use of its method, because it does not use new to create the object,
The program compiles, even if you do not register that DLL file can be used normally.

Option Explicit

' Assume that the file name of the ActiveX Dll is DllDemo.dll and is in the same directory as the project
Private Declare Function dllgetclassobject Lib "DllDemo.dll" (_
Rclsid as UUID, riid as UUID, ByRef PPV as any) as Long

' Class ID
Private Const clsstr_obj as String = "{C1A334BA-D1A4-48D0-98D5-47FE934961DF}"
' Interface ID
Private Const iidstr_ins as String = "{231114d5-e046-4dae-b192-0ab49d493a85}"

' IClassFactory ID
Private Const striid_iclassfactory as String = "{00000001-0000-0000-c000-000000000046}"

Private Clsid_obj as UUID
Private Iid_ins as UUID
Private Iid_iunknow as UUID
Private Iid_iclassfactory as UUID


Private Sub Command1_Click ()
Dim Tobj as Olelib. IUnknown
Dim Tobj2 as Dlldemo.idemo
Dim TFac as Olelib. IClassFactory

Call DllGetClassObject (Clsid_obj, Iid_iclassfactory, TFac)

Tfac.createinstance Nothing, Iid_iunknow, tobj
Set TFac = Nothing
Set tobj2 = Tobj

' Call the object created by the Idemo.test test
Tobj2. Test
End Sub

Private Sub Form_Load ()
' Converts a string to a UUID
CLSIDFromString Clsstr_obj, Clsid_obj
CLSIDFromString Iidstr_ins, Iid_ins
CLSIDFromString Iidstr_iunknown, Iid_iunknow
CLSIDFromString Striid_iclassfactory, Iid_iclassfactory
End Sub

At this point, the problem seems to have been solved, as long as the different ActiveX DLLs to write the corresponding DllGetClassObject function can be, but when the file name is not determined when it is difficult, such as when writing plug-ins.
The workaround is to use LoadLibrary to dynamically invoke the DllGetClassObject on each DLL. Unfortunately, VB does not support function pointers. My approach is to use VC to solve. Write DLL with VC for VB call, the main code is as follows:

CrCom.cpp:Defines the entry point for the DLL application.
//

#include "stdafx.h"
#include <unknwn.h>
#include <objbase.h>

typedef int (CALLBACK *MYPROC) (refclsid,refiid,lpvoid *);

BOOL apientry DllMain (HANDLE hmodule,
DWORD Ul_reason_for_call,
LPVOID lpreserved
)
{
return TRUE;
}


if (riid==null) Riid=&iid_iunknown
int _stdcall Crcomobj (
LPCSTR Lpdll,
CLSID *rclsid,
IID *riid,
LPVOID * PPV)
{
HINSTANCE hInstLib;
MYPROC Procadd;

BOOL Ffreeresult, fruntimelinksuccess = FALSE;
int rtn=0;
Get a handle to the DLL module.


hInstLib = LoadLibrary (Lpdll);

If The handle is a valid, try to get the function address.

if (hinstlib! = NULL)
{
Procadd = (MYPROC) GetProcAddress (hInstLib, "DllGetClassObject");

If The function address is valid, call the function.

if (fruntimelinksuccess = (procadd! = NULL))
{
if (rclsid==null)
{
FreeLibrary (hInstLib);
return 0;
}

if (riid==null)
Riid= (IID *) &IID_IUnknown;

IClassFactory *pif;
Pif=null;
if (Procadd (*rclsid,iid_iclassfactory, (void * *) &pif) ==S_OK && pif!=null)
{
if (Pif->createinstance (NULL,*RIID,PPV) ==S_OK)
rtn= (int) hinstlib;
Pif->release ();
Pif=null;
}
}
Free the DLL module.

if (!rtn) Ffreeresult = FreeLibrary (hInstLib);
}
return RTN;
}


If strriid==null, use IID_IUnknown;
int _stdcall CrComObj2 (
LPCSTR Lpdll,
LPCSTR Strrclsid,
LPCSTR Strriid,
LPVOID * PPV)
{
HINSTANCE hInstLib;
MYPROC Procadd;

BOOL Ffreeresult, fruntimelinksuccess = FALSE;

int rtn=0;
Get a handle to the DLL module.


hInstLib = LoadLibrary (Lpdll);

If The handle is a valid, try to get the function address.

if (hinstlib! = NULL)
{
Procadd = (MYPROC) GetProcAddress (hInstLib, "DllGetClassObject");

If The function address is valid, call the function.

if (fruntimelinksuccess = (procadd! = NULL))
{
CLSID Rclsid;
IID riid;

if (strrclsid==null)
{
FreeLibrary (hInstLib);
return 0;
}
CLSIDFromString ((LPOLESTR) strrclsid,&rclsid);

if (strriid!=null)
CLSIDFromString ((LPOLESTR) strriid,&riid);
Else
Riid=iid_iunknown;

IClassFactory *pif=null;

if (Procadd (Rclsid,iid_iclassfactory, (void * *) &pif) ==S_OK && pif!=null)
{
if (Pif->createinstance (NULL,RIID,PPV) ==S_OK)
rtn= (int) hinstlib;
Pif->release ();
Pif=null;
}
}
Free the DLL module.

if (!rtn) Ffreeresult = FreeLibrary (hInstLib);
}
return RTN;
}


The use of VB in the method, Crcomobj Pass is the Uuid,crcomobj2 pass is a string,

' function declaration
Private Declare Function crcomobj Lib "CrCom.dll" (_
ByVal Lpdll as String, ByVal Rclsid as Long, ByVal riid as Long, ByRef PPV as any) as long
Private Declare Function CrComObj2 Lib "CrCom.dll" (_
ByVal Lpdll as String, ByVal Strrclsid as Long, ByVal strriid as Long, ByRef PPV as any) as long


Dim Tobj as Olelib. IUnknown
Dim Tobj2 as Dlldemo.idemo

Hlib = Crcomobj (App.Path & "/dlldemo.dll", VarPtr (Clsid_obj), 0, Tobj)
Set tobj2 = Tobj
Tobj2. Test

' OR

Hlib=crcomobj2 (App.Path & "/dlldemo.dll", StrPtr (Clsstr_obj), 0, Tobj)
Set tobj2 = Tobj
Tobj2. Test


Crcomobj and CrComObj2 return the return value of LoadLibrary, which needs to be released with FreeLibrary when necessary.


Postscript:
My multi-page browser Le, also implemented does not register to call the ActiveX Dll, I was directly using a book (Advanced Visual Basic) code, the code is quite long, it seems quite complex, the original use of the time is unclear, and then finally made clear, the principle is the same, But because VB does not support function pointers, it takes a lot of effort to deal with this problem. Compared to, I think it is better to borrow VC, so the words are more concise.


Lingll
Lingll_xl@163.com
2006-2-7

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.