環境是Delphi XE2 Enterprise。排除COM錯誤「參數不正確」
有關use dispInterface in Delphi with no classid。重新發布作爲一個不同的問題,因爲我已經超越了以前的問題(感謝@EricBrown),現在有一個更具體的問題。
我有一個.NET的DLL,我已經註冊在計算機上的COM接口,並已作爲類型庫導入到Delphi中。我正在使用Delphi創建的tlb.pas文件。
使用我在IDispatch接口和TAutoIntf後代類中實現的一對dispInterfaces,我已經成功地初始化了我需要調用.NET庫的COM接口中的方法的類和接口。下面是一些代碼來說明申報/實施:
// COM Event Sink GUID
DIID_IResponseListener: TGUID = '{ABC29F08-B628-4747-BA9E-469D408E57B9}';
// *********************************************************************//
// DispIntf: IResponseListener
// Flags: (4096) Dispatchable
// GUID: {ABC29F08-B628-4747-BA9E-469D408E57B9}
// *********************************************************************//
IResponseListener = dispinterface
['{ABC29F08-B628-4747-BA9E-469D408E57B9}']
procedure RequestCompleted(const requestID: WideString; const responseObj: IResponse); dispid 1610744833;
procedure RequestFailed(const requestID: WideString; const error: WideString); dispid 1610744834;
procedure TablesUpdates(const responseObj: IResponse); dispid 1610744835;
end;
...my implementation:
IFXResponseListener = interface(IDispatch)
['{3204D3F7-5DF2-4470-89D5-D34F4F6F0381}']
procedure RequestCompleted(const requestID: WideString; const responseObj: IResponse); dispid 1610744833; safecall;
procedure RequestFailed(const requestID: WideString; const error: WideString); dispid 1610744834; safecall;
procedure TablesUpdates(const responseObj: IResponse); dispid 1610744835; safecall;
end;
TFXResponseListener = class(TAutoIntfObject,IFXResponseListener)
private
FDisp: IDispatch;
FResp: IResponse;
function GetResponseListIntf: IResponseListener;
public
constructor Create;
destructor Destroy;
published
procedure RequestCompleted(const requestID: WideString; const responseObj: IResponse); safecall;
procedure RequestFailed(const requestID: WideString; const error: WideString); safecall;
procedure TablesUpdates(const responseObj: IResponse); safecall;
property ResponseObj: IResponse read FResp;
property ListenerDispIntf: IResponseListener read GetResponseListIntf;
end;
...
{ TFXResponseListener }
constructor TFXResponseListener.Create;
var
TypeLib: ITypeLib;
begin
OleCheck(LoadRegTypeLib(LIBID_fxcore2_com,fxcore2_comMajorVersion,fxcore2_comMinorVersion,0,TypeLib));
inherited Create(TypeLib,DIID_IResponseListener);
end;
destructor TFXResponseListener.Destroy;
begin
inherited;
end;
function TFXResponseListener.GetResponseListIntf: IResponseListener;
begin
FDisp := Self as IFXResponseListener;
FDisp._AddRef;
Result := IResponseListener(FDisp);
end;
procedure TFXResponseListener.RequestCompleted(const requestID: WideString; const responseObj: IResponse);
begin
showmessage('Completed: ' + requestID);
FResp := responseObj;
end;
procedure TFXResponseListener.RequestFailed(const requestID: WideString; const error: WideString);
begin
showmessage('Failed: ' + requestID);
end;
procedure TFXResponseListener.TablesUpdates(const responseObj: IResponse);
begin
showmessage('TablesUpdates');
end;
這裏是我嘗試使用該接口:
FRespList := TFXResponseListener.Create;
try
FSess.subscribeResponse(FRespList.ListenerDispIntf);
except
// errors out here with 'The parameter is incorrect'
end;
跟蹤下來到System.Win.ComObj的腸子,在行1793年它調用:
Status := Dispatch.Invoke(DispID, GUID_NULL, 0, InvKind, DispParams, Result, @ExcepInfo, nil);
在這一點上,DISPID參數是有效的(1610743816),GUID_NULL是「(0,0,0,(0,0,0,0,0,0,0,0 ))',InvKind是'1',DispParams是'($ 2152FE8,零,1,0)',Resul t是'$ 12FE24',@ExcepInfo是'$ 12FDE0'。
在System.pas,行30133中,TInterfacedObject.QueryInterface被調用兩次。在第二次運行中,它返回結果'E_NOINTERFACE',並顯示可怕的'The parameter is incorrect'信息。
我真的不確定該從哪裏出發,但我希望COM專家和/或Delphi專家可以檢查這一點,並看到一些不妥之處。
我也想知道是否有一個.NET框架版本或其他問題。我正在使用框架版本4.5.1;不確定如何確定.NET程序集是否與此版本的框架兼容,或者它確實需要更早的版本。
任何相關的.NET/COM調試技術將不勝感激。
另請注意,我可以用不同的調度接口/ IDispatch/TAutoIntfObj後代類和類似的調用複製此問題,與'T'相同。
謝謝。
什麼是FRespList聲明爲? 'FSess.subscribeResponse()'? QueryInterface()在返回E_NOINTERFACE時被詢問是什麼?這個guid是一個標準的guid還是定義在類型庫中?另外,'TFXResponseListener.GetResponseListIntf()'的實現看起來對我來說是非常可疑的,你創建了那個還是讓Delphi自動生成它? –
FRespList被聲明爲TFXResponseListener。 FSess是來自類型庫的ISession接口。 Session subscribeResponse過程接受一個參數,一個被定義爲dispInterface的IResponseListener。 TFXResponseListener.GetResponseListIntf是我定義的東西,就像所有的TFXResponseListener類和IFXResponseListener接口一樣。 QueryInterface正在測試:(3288121758,43376,4562,(139,90,0,160,201,183,201,196))',我不知道如何將它轉換爲GUID。 – DeCoder
奇怪的是它碰到了兩次TInterfacedObject.QueryInterface。第一次被稱爲IID是'(0,0,0,(192,0,0,0,0,0,0,70))。第二個電話是上面列出的接口。在追蹤中,它是對subscribeResponse(IResponseListener)的調用,導致對QueryInterface的2次調用。在第一次調用時返回-0-(成功?)的結果 – DeCoder