2011-09-07 8 views
5

Excel(2007)VBAでCOMサーバーオブジェクトへの参照を強制的に解除する方法を教えてください。Excel VBAからinprocess COMサーバーオブジェクトを解放する方法

私は開発マシン上のExcel 2007 VBAコードからインスタンス化されたVisual Foxpro 9 SP2でinprocess(シングルインスタンスDLL)COMサーバーを作成しました。 ExcelはCOMオブジェクト/ dllへの参照を保持しているようですが、それは何も設定しません。これは、変更を加えてテストするたびにExcelを終了するまで、「File access is Testied.dllが拒否されました」というメッセージが表示されるため、DLLを再構築できなくなります。

私がダウンして非常に簡単なテスト・セットアップのコードを煮ています: 次のようにVFP9プロジェクト(TESTCOM)は

DEFINE CLASS TestClass As Session OLEPUBLIC 

ENDDEFINE 

次の内容でただ一つの.prgファイルは、VBAコードでいます

Sub Test() 

    Set objTest = CreateObject("TestCOM.TestClass") 
    Set objTest = Nothing 

End Sub 

私はVBAプロジェクトでCOMサーバーライブラリへの参照を削除しようとしましたが、これは何の違いもありません。 私は、オブジェクト変数をDIMINGしてみると無しで試しましたが、違いはありません。 新しいVFP DLLプロジェクトを作成しようとしましたが、問題は解決しません。

VBAアプリケーション/ dllをINPROCESS/DLLとしてビルドしてVBAコードを実行すると、この問題が発生しますが、OUTOFPROCESS/EXEとしてビルドしてVBAコードを実行すると、この問題は発生しません。

COM Object Cleanupで非常によく似た問題が見つかりましたが、私のCOM ServerはVisual Foxpro 9 SP2で書かれていますが、C#に関連していますが、OPで詳しく解説されていないので、周りを回る。それが可能であれば。

+0

コピーとpasteable宣言ですVBA/Excelのタイプライブラリへの参照がない場合は、Excelを終了しないでください。 – Caltor

答えて

6

DLL内のコードからCOMクラスをインスタンス化する手順は、ExcelがCOMライブラリレイヤを呼び出して、ProgIDまたはClassIDのいずれかを使用して実装を見つけることです。 Inprocサーバーがある場合、これはDLLへのパスを検出し、LoadLibraryを使用してそれをクライアントプロセスにロードし、クラスファクトリを作成してDLL内のメソッドを呼び出します。したがって、最終結果は、ExcelがDLLのLoadLibraryを呼び出し、Excelがハンドル上のFreeLibraryを呼び出すまでファイルをロックします。

COMインターフェイスを使用すると、これを制御することはできません。 CoCreateInstance()を呼び出します(または、このWin32 APIを下に呼び出すNewまたはCreateObjectでオブジェクトを作成するVBAから)。これの実装は、あなたが作業するためのインターフェイスポインタを渡すまで、LoadLibraryとその他すべてを処理します。一部のアプリケーションでは、CoFreeUnusedLibraries()を定期的に呼び出して、現在使用されていないロード済みのCOM DLLを解放しようとします。デフォルトのクラスファクトリの実装では、DLLが使用されているかどうかを判断するために使用できるオブジェクトのカウンタが保持されますが、COMクラスの作者が規則に従わないため、常に信頼できるわけではありません。 Excelを終了すると、明らかにファイルのロックが解除されます。

アウトオブプロセスサーバーとしてCOMクラスを作成すると、COMクラスは独立した実行可能ファイルまたはDLLで動作し、その寿命は別に管理されます。 ExcelはもはやDLLのロックを保持せず、COMインスタンスを解放すると、ホスティングプロセスが終了する可能性があります。

DLLをDllHostでホストするようにアレンジすることで、ローカルサーバーとして使用するように変換できます(プロセス外)。 OleViewユーティリティを使用してProgIdクラスを見つけると、代理プロセス(dllhost)でホスティングを有効にすることができます。私はそれをしてからしばらくしているが、サロゲートホスティングの使用についてのウェブ上の情報があるはずである。明らかに、COMオブジェクトをプロセス外でホストすると、すべての処理が遅くなり、さまざまなマーシャリングの問題が発生する可能性があります。あなたがオレオスタイル互換のインターフェイスを保つのであれば、それはうまくいくはずです。短い答えを追加

+0

あなたの優れた詳細なテクニカル返信ありがとうございます。つまり、基本的にはCOMインターフェイスではクライアントの慈悲を受けています。この場合はExcelですが、DLLのリリースを強制する方法はありません。私は私の質問では、VFPの別のコピーからCOMサーバーが呼び出されたときにこの問題が発生しないようにする必要があります。そのため、フォールトはサーバーではなくクライアントであるように見えます。回避策として、このプロジェクトを開発中にアウトプロセスサーバー(EXE)として構築し、最終テストとリリースのためにインプロセス(DLL)に切り替えます。 – Caltor

+2

追加成分が1つ必要です。 COMサーバーは、そのDllCanUnloadNow()エントリポイントからS_OKを返す必要があります。 VBA + Foxpro環境でのテストは簡単ではありません。 –

1

.... DLLを解放

は節の問題とExcelで使用するためのプロセスでCOMコンポーネントの開発者に馴染みのものです。

1満たされる必要がある2つの条件)の代わりに遅延バインディングを使用、事前バインディングライブラリ参照(ツール - >参照)を使用しないでくださいがあります。早期バインディングツールのリファレンスはロックを保持します。

2)クライアントがなくなったCOMサーバをアンロードするには、CoFreeUnusedLibrariesに電話してください。

サンプルコードから、あなたはすでにレイトバインディングしていますが、参照を確認してください。ポイント2)はpayyhoyts answerに記載されているが、コードは与えられていない。ここで

は、私はその後、プロジェクトはプロセスのうち(EXE)COMサーバとして構築されているならば、あなただけのプロジェクトを再構築することができますことを実現したこのスレッドを読んだ他のもののために

Private Declare Sub CoFreeUnusedLibraries Lib "ole32.dll"() 
関連する問題