質問
AutoCADのActiveX APIを.NET アプリケーションから実行すると「呼び出し先が呼び出しを拒否しました。 (HRESULT からの例外:0x80010001 (RPC_E_CALL_REJECTED))」エラーが発生することがある。
毎回同じAutoCADのAPIの実行でエラーが発生するわけではなく、また発生頻度もまちまち(発生せずに実行できる場合もある)で規則性は見られない状況。
回答
AutoCADがビジー状態(=何らかの処理中)にあるために、Remote Procedure Call (ここでは、カスタムアプリーケーションからの、AutoCADのAPIの呼び出し)を受け付けることが出来ない状態であるため、APIの呼出しが拒否されている可能性が高い状況です。 外部プロセスからのAcitveX APIの実行は、Windowsの低レベルレイヤーではクライアントアプリケーション(この場合は外部プロセスのカスタムアプリ)が、サーバ側のアプリケーション(この場合はAutoCAD)のメインスレッドに対してWindows Messageを送信する形で、プロセス間でのAPIの実行が行われています。
このため、AutoCAD側のメインスレッドが何らかの別の処理を行っている状態にある場合、Windows Messageが処理されず呼び出し元のアプリケーションは待ちの状態となります。
呼び出し元のアプリケーションが無限に処理待ちの状態となってしまうことを防ぐ機構として、一定時間の経過後に例外を送信する仕組みがActiveXに備わっており、タイトルにあるようなエラーとして出現いたします。
通常は、AcitveXの実行系のデフオルトのリトライ処理で問題なくAPIを実行することが出来ますが、実行環境の状態や処理内容に依存して、エラーが発生するケースがあります。このような場合カスタムプログラム側でIMessageFilterのRetryRejectedCallで、ActiveX APIの呼び出しをリトライをする機構を実装することにより、状況が改善する可能性があります。
以下のブログ記事にて、C#でのIMessageFilterのリトライ処理を実装のサンプルコードが掲載されております。
https://www.keanw.com/2010/02/handling-com-calls-rejected-by-autocad-from-an-external-net-application.html
また、以下のサンプルコードは、上記ブログ記事の IMessageFilterのリトライ処理部をVB.NETに置き換えたものとなります。
Imports System.Runtime.InteropServices
Imports Microsoft.Win32
Imports System
Imports Microsoft.VisualBasic
<ComImport(), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("00000016-0000-0000-C000-000000000046")>
Public Interface IMessageFilter
<PreserveSig()>
Function HandleInComingCall(ByVal dwCallType As Integer, ByVal hTaskCaller As IntPtr, ByVal dwTickCount As Integer, ByVal lpInterfaceInfo As IntPtr) As Integer
<PreserveSig()>
Function RetryRejectedCall(ByVal hTaskCallee As IntPtr, ByVal dwTickCount As Integer, ByVal dwRejectType As Integer) As Integer
<PreserveSig()>
Function MessagePending(ByVal hTaskCallee As IntPtr, ByVal dwTickCount As Integer, ByVal dwPendingType As Integer) As Integer
End Interface
Public Class Form1 Implements IMessageFilter
Public Sub New()
InitializeComponent()
Dim oldFilter As IMessageFilter = Nothing
CoRegisterMessageFilter(Me, oldFilter)
End Sub
Private Function IMessageFilter_HandleInComingCall(ByVal dwCallType As Integer, ByVal hTaskCaller As IntPtr, ByVal dwTickCount As Integer, ByVal lpInterfaceInfo As IntPtr) As Integer Implements IMessageFilter.HandleInComingCall
Return 0
End Function
Private Function IMessageFilter_RetryRejectedCall(ByVal hTaskCallee As IntPtr, ByVal dwTickCount As Integer, ByVal dwRejectType As Integer) As Integer Implements IMessageFilter.RetryRejectedCall
'retry in a second.
Return 1000
End Function
Private Function IMessageFilter_MessagePending(ByVal hTaskCallee As IntPtr, ByVal dwTickCount As Integer, ByVal dwPendingType As Integer) As Integer Implements IMessageFilter.MessagePending
Return 1
End Function
<DllImport("ole32.dll")>
Private Shared Function CoRegisterMessageFilter(ByVal lpMessageFilter As IMessageFilter, ByRef lplpMessageFilter As IMessageFilter) As Integer
End Function
End Class
記事全体を表示