IMessageFilterを使う
AutoCAD2012を外部からコントロールして自動処理するプログラムを作成してて遭遇したんですが、不定期なタイミングでRPC_E_CALL_REJECTEDが発生するんです。
調べて見るとAutoCAD2010のSP1かな?辺りから発生するようになっているようで、IMessageFilter(COMのインターフェースの方です)を実装してリトライ掛けるようにすれば解決するという事なんで実装してみました。
HandleInComingCallは、COMサーバー側で呼ばれる関数らしい。MessagePendingは、良く判りません。
RetryRejectedCallは、COMサーバーのHandleInComingCallからSERVERCALL_REJECTEDかSERVERCALL_RETRYLATERが返ってきた時に呼ばれる関数らしい。0以上の値を返すと処理のリトライを出来るようなので、dwRejectTypeがSERVERCALL_RETRYLATERの時に1000を返してリトライを実行するようにしたらエラーも出なくなりました。
uses Classes, Windows, ActiveX; type TMessageFilter = class(TInterfacedObject, IMessageFilter) private FOldFilter: IMessageFilter; public constructor Create; // フィルタの登録 procedure RegisterFilter; // フィルタの登録解除 procedure RevokeFilter; function HandleInComingCall(dwCallType: Longint; htaskCaller: HTask; dwTickCount: Longint; lpInterfaceInfo: PInterfaceInfo): Longint; stdcall; function RetryRejectedCall(htaskCallee: HTask; dwTickCount: Longint; dwRejectType: Longint): Longint; stdcall; function MessagePending(htaskCallee: HTask; dwTickCount: Longint; dwPendingType: Longint): Longint; stdcall; end; implementation constructor TMessageFilter .Create; begin inherited; FOldFilter := Nil; end; function TMessageFilter .HandleInComingCall(dwCallType: Integer; htaskCaller: HTask; dwTickCount: Integer; lpInterfaceInfo: PInterfaceInfo): Longint; begin Result := 0; end; function TMessageFilter .MessagePending(htaskCallee: HTask; dwTickCount, dwPendingType: Integer): Longint; begin Result := PENDINGMSG_WAITNOPROCESS; end; procedure TMessageFilter.RegisterFilter; begin CoRegisterMessageFilter(Self, FOldFilter); end; function TMessageFilter .RetryRejectedCall(htaskCallee: HTask; dwTickCount, dwRejectType: Integer): Longint; begin if dwRejectType = SERVERCALL_RETRYLATER then Result := 1000 else Result := -1; end; procedure TMessageFilter.RevokeFilter; var dmy: IMessageFilter; begin CoRegisterMessageFilter(FOldFilter, dmy); end;