P
paf
Unregistered / Unconfirmed
GUEST, unregistred user!
我的COM代码如下!我是照着 作者:吴剑明(foxnt) 的 "COM实现过程" 自己动手自己写的,但总是失败!
library MyCOM;
uses
windows, ACTIVEX, D_MinSysUtils, Registry, sysutils, comobj;
const
Class_MyCOM: TGUID = '{EC18BF9C-4885-4960-B985-B512BDF3082C}'; //用来标识COM组件
type
IMyCOMTest = interface(IUnknown) //定义我们的接口
['{F1CFFC4F-B36C-4B60-B408-A1CE759F6F1A}']
function msg: integer; stdcall;
end;
TMyCOMServer = class(TObject, IMyCOMTest)
protected
FLock: integer;
public
constructor Create;
function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
function _AddRef: Integer; stdcall;
function _Release: Integer; stdcall;
function msg: integer; stdcall;
end;
//类工厂
TClassFactory = class(TObject, IClassFactory)
protected
FLock: integer;
function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
function _AddRef: Integer; stdcall;
function _Release: Integer; stdcall;
public
constructor Create;
function CreateInstance(const unkOuter: IUnknown; const iid: TIID; out obj): HResult; stdcall;
function LockServer(fLock: BOOL): HResult; stdcall;
end;
var
MC: IMyCOMTest;
CF: IClassFactory; //IclassFactory是系统预先定义了的,在ACTIVEX单元有
constructor TMyCOMServer.Create;
begin
Inc(FLock);
end;
function TMyCOMServer._AddRef: Integer;
begin
Inc(FLock);
end;
function TMyCOMServer._Release: Integer;
begin
Dec(FLock);
if FLock = 0 then Free;
end;
function TMyCOMServer.QueryInterface(const IID: TGUID; out Obj): HResult;
begin
//在类工厂中实现的一个MC接口,在这里返回。由于我们只有一个接口,所以那个IID参数没有用。当然,如果我们实现了多个接口,就需要维护一个数组,用个CASE语句,根据不同的IID,来返回不同的接口。
Pointer(Obj) := Pointer(MC);
Result := S_OK;
end;
function TMyCOMServer.msg: integer;
begin
result := 1978;
end;
//-----------------------------------------------
// 类工厂
//-----------------------------------------------
function TClassFactory.CreateInstance(const UnkOuter: IInterface; const IID: TGUID; out Obj): HResult;
begin
//我们的自定义接口,就是在这里被创建的。
MC := TMyCOMServer.Create;
Pointer(Obj) := Pointer(MC);
end;
function TClassFactory.LockServer(fLock: BOOL): HResult; stdcall;
begin
end;
function TClassFactory._AddRef: Integer;
begin
Inc(FLock);
end;
function TClassFactory._Release: Integer;
begin
Dec(FLock);
if FLock = 0 then Free;
end;
function TClassFactory.QueryInterface(const IID: TGUID; out Obj): HResult;
begin
end;
constructor TClassFactory.Create;
begin
Inc(FLock);
end;
//-------------------------------------------------
// DLL接口
//-------------------------------------------------
function DllGetClassObject(const CLSID, IID: TGUID; var Obj): HResult;
begin
CF := TClassFactory.Create;
Pointer(obj) := Pointer(CF);
Result := S_OK;
end;
function DllCanUnloadNow: HResult;
begin
Result := S_OK;
end;
function DllRegisterServer: HResult;
var
lp: pchar;
ns: Dword;
Reg: TregisTry;
begin
Result := S_FALSE;
Reg := TRegistry.Create;
GetMem(lp, 255);
try
Reg.RootKey := HKEY_CLASSES_ROOT;
if Reg.OpenKey('/MyCOM.MyCOMTest', true) then
begin
Reg.CreateKey('CLSID');
if Reg.OpenKey('CLSID', true) then
Reg.WriteString('', GUIDToString(Class_MyCOM));
end;
if Reg.OpenKey('/CLSID/' + GUIDToString(Class_MyCOM), true) then
begin
if Reg.CreateKey('InprocServer32') = false or
Reg.CreateKey('ProgID') = false or
Reg.CreateKey('TypeLib') = false or
Reg.CreateKey('Version') = false then
Exit;
Reg.WriteString('', 'MyCOM');
if Reg.OpenKey('/CLSID/' + GUIDToString(Class_MyCOM) +
'/InprocServer32', false) then
begin
Windows.GetModuleFileName(HInstance, lp, 255);
Reg.WriteString('', lp);
Reg.WriteString('ThreadingModel', 'Single');
end;
if Reg.OpenKey('/CLSID/' + GUIDToString(Class_MyCOM) + '/ProgID', false) then
Reg.WriteString('', 'MyCOM.MyCOMTest');
if Reg.OpenKey('/CLSID/' + GUIDToString(Class_MyCOM) + '/Version', false) then
Reg.WriteString('', '1.0');
Reg.CloseKey;
Result := S_OK;
end;
finally
begin
FreeMem(lp);
Reg.Free;
end;
end;
end;
function DllUnRegisterServer: Hresult;
var
Reg: TregisTry;
begin
Result := S_False;
Reg := TRegistry.Create;
try
Reg.RootKey := HKEY_CLASSES_ROOT;
Reg.DeleteKey('/CLSID/' + GUIDToString(Class_MyCOM));
Reg.CloseKey;
finally
Reg.Free;
end;
end;
exports
DllGetClassObject, //返回类工厂接口
DllCanUnloadNow, //告诉客户端该COM是否可以被正常卸载
DllRegisterServer, //向系统注册COM组件信息。Regsvr32.exe 就是调用这个函数来进行注册的
DllUnregisterServer; //从系统中反注册一个COM。Regsvr32.exe 就是调用这个函数来进行反注册的
begin
end.
编译后,我用 regsvr32 MyCOM.dll 进行注册
之后就是调用了!
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ACTIVEX, ComObj;
type
IMyCOMTest = interface(IUnknown) //定义我们的接口
['{F1CFFC4F-B36C-4B60-B408-A1CE759F6F1A}']
function msg: integer; stdcall;
end;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
AAA: IMyCOMTest;
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
Class_MyCOM: TGUID = '{EC18BF9C-4885-4960-B985-B512BDF3082C}'; //用来标识COM组件
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
bbb: IMyCOMTest;
begin
bbb := createcomobject(Class_MyCOM) as IMyCOMTest; //这里总是出错!
end;
end.
我不清楚我错在哪里,请大家帮忙!
library MyCOM;
uses
windows, ACTIVEX, D_MinSysUtils, Registry, sysutils, comobj;
const
Class_MyCOM: TGUID = '{EC18BF9C-4885-4960-B985-B512BDF3082C}'; //用来标识COM组件
type
IMyCOMTest = interface(IUnknown) //定义我们的接口
['{F1CFFC4F-B36C-4B60-B408-A1CE759F6F1A}']
function msg: integer; stdcall;
end;
TMyCOMServer = class(TObject, IMyCOMTest)
protected
FLock: integer;
public
constructor Create;
function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
function _AddRef: Integer; stdcall;
function _Release: Integer; stdcall;
function msg: integer; stdcall;
end;
//类工厂
TClassFactory = class(TObject, IClassFactory)
protected
FLock: integer;
function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
function _AddRef: Integer; stdcall;
function _Release: Integer; stdcall;
public
constructor Create;
function CreateInstance(const unkOuter: IUnknown; const iid: TIID; out obj): HResult; stdcall;
function LockServer(fLock: BOOL): HResult; stdcall;
end;
var
MC: IMyCOMTest;
CF: IClassFactory; //IclassFactory是系统预先定义了的,在ACTIVEX单元有
constructor TMyCOMServer.Create;
begin
Inc(FLock);
end;
function TMyCOMServer._AddRef: Integer;
begin
Inc(FLock);
end;
function TMyCOMServer._Release: Integer;
begin
Dec(FLock);
if FLock = 0 then Free;
end;
function TMyCOMServer.QueryInterface(const IID: TGUID; out Obj): HResult;
begin
//在类工厂中实现的一个MC接口,在这里返回。由于我们只有一个接口,所以那个IID参数没有用。当然,如果我们实现了多个接口,就需要维护一个数组,用个CASE语句,根据不同的IID,来返回不同的接口。
Pointer(Obj) := Pointer(MC);
Result := S_OK;
end;
function TMyCOMServer.msg: integer;
begin
result := 1978;
end;
//-----------------------------------------------
// 类工厂
//-----------------------------------------------
function TClassFactory.CreateInstance(const UnkOuter: IInterface; const IID: TGUID; out Obj): HResult;
begin
//我们的自定义接口,就是在这里被创建的。
MC := TMyCOMServer.Create;
Pointer(Obj) := Pointer(MC);
end;
function TClassFactory.LockServer(fLock: BOOL): HResult; stdcall;
begin
end;
function TClassFactory._AddRef: Integer;
begin
Inc(FLock);
end;
function TClassFactory._Release: Integer;
begin
Dec(FLock);
if FLock = 0 then Free;
end;
function TClassFactory.QueryInterface(const IID: TGUID; out Obj): HResult;
begin
end;
constructor TClassFactory.Create;
begin
Inc(FLock);
end;
//-------------------------------------------------
// DLL接口
//-------------------------------------------------
function DllGetClassObject(const CLSID, IID: TGUID; var Obj): HResult;
begin
CF := TClassFactory.Create;
Pointer(obj) := Pointer(CF);
Result := S_OK;
end;
function DllCanUnloadNow: HResult;
begin
Result := S_OK;
end;
function DllRegisterServer: HResult;
var
lp: pchar;
ns: Dword;
Reg: TregisTry;
begin
Result := S_FALSE;
Reg := TRegistry.Create;
GetMem(lp, 255);
try
Reg.RootKey := HKEY_CLASSES_ROOT;
if Reg.OpenKey('/MyCOM.MyCOMTest', true) then
begin
Reg.CreateKey('CLSID');
if Reg.OpenKey('CLSID', true) then
Reg.WriteString('', GUIDToString(Class_MyCOM));
end;
if Reg.OpenKey('/CLSID/' + GUIDToString(Class_MyCOM), true) then
begin
if Reg.CreateKey('InprocServer32') = false or
Reg.CreateKey('ProgID') = false or
Reg.CreateKey('TypeLib') = false or
Reg.CreateKey('Version') = false then
Exit;
Reg.WriteString('', 'MyCOM');
if Reg.OpenKey('/CLSID/' + GUIDToString(Class_MyCOM) +
'/InprocServer32', false) then
begin
Windows.GetModuleFileName(HInstance, lp, 255);
Reg.WriteString('', lp);
Reg.WriteString('ThreadingModel', 'Single');
end;
if Reg.OpenKey('/CLSID/' + GUIDToString(Class_MyCOM) + '/ProgID', false) then
Reg.WriteString('', 'MyCOM.MyCOMTest');
if Reg.OpenKey('/CLSID/' + GUIDToString(Class_MyCOM) + '/Version', false) then
Reg.WriteString('', '1.0');
Reg.CloseKey;
Result := S_OK;
end;
finally
begin
FreeMem(lp);
Reg.Free;
end;
end;
end;
function DllUnRegisterServer: Hresult;
var
Reg: TregisTry;
begin
Result := S_False;
Reg := TRegistry.Create;
try
Reg.RootKey := HKEY_CLASSES_ROOT;
Reg.DeleteKey('/CLSID/' + GUIDToString(Class_MyCOM));
Reg.CloseKey;
finally
Reg.Free;
end;
end;
exports
DllGetClassObject, //返回类工厂接口
DllCanUnloadNow, //告诉客户端该COM是否可以被正常卸载
DllRegisterServer, //向系统注册COM组件信息。Regsvr32.exe 就是调用这个函数来进行注册的
DllUnregisterServer; //从系统中反注册一个COM。Regsvr32.exe 就是调用这个函数来进行反注册的
begin
end.
编译后,我用 regsvr32 MyCOM.dll 进行注册
之后就是调用了!
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ACTIVEX, ComObj;
type
IMyCOMTest = interface(IUnknown) //定义我们的接口
['{F1CFFC4F-B36C-4B60-B408-A1CE759F6F1A}']
function msg: integer; stdcall;
end;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
AAA: IMyCOMTest;
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
Class_MyCOM: TGUID = '{EC18BF9C-4885-4960-B985-B512BDF3082C}'; //用来标识COM组件
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
bbb: IMyCOMTest;
begin
bbb := createcomobject(Class_MyCOM) as IMyCOMTest; //这里总是出错!
end;
end.
我不清楚我错在哪里,请大家帮忙!