これは一種の複雑な質問であり、COM、CLR、および reg-free COM に関連するやや難解な領域に当てはまります。
まず、私のメイン アプリケーションは Python で書かれています。そのため、(開発中の) コードベースは、たとえば C:\mainapp\main.py にあります。
もちろん、Windows では、プログラムを実行するのは C:\Python27\python.exe です。
C:\mainapp\ManagedCOMObject.dll にある、私が制御する C# で記述された COM オブジェクトと通信する (IDispatch を使用して) python から reg-free COM を (win32com を使用して) 使用したいと考えています。
注: python / pythoncom を話せない場合は、Dispatch() の呼び出しが最終的に CoCreateInstance() になることに注意してください。
試行 1
#main.py:
import win32com.client
CLSID_ManagedComObject_MyClass = "{zzzzz....}" #This is correct
myclass = win32com.client.Dispatch(CLSID_ManagedComObject_MyClass)
結果
オブジェクトがレジストリにないため (予想どおり)、マニフェスト ファイルについては何も言及していませんでした。また、python.exe のマニフェストは明らかにオブジェクトについて認識していません。
試行 2
#main.py:
ac = ActivationContext("C:\mainapp\myapp.manifest", asm_dir="C:\mainapp")
with ac.activate():
#The above two lines fill in a ACTCTX structure, call CreateActCtx, and call ActivateActCtx
import win32com.client
CLSID_ManagedComObject_MyClass = "{zzzzz....}" #This is correct
myclass = win32com.client.Dispatch(CLSID_ManagedComObject_MyClass)
-
#myapp.manifest:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity type="win32"
name="My.Main.App"
version="1.0.0.0"
processorArchitecture="x86"
/>
<dependency>
<dependentAssembly>
<assemblyIdentity
name="ManagedComObject"
version="1.0.0.0"
processorArchitecture="msil"
/>
</dependentAssembly>
</dependency>
</assembly>
ManagedCOMObject には、clrClass タグを使用して COM オブジェクトを宣言するマニフェストが埋め込まれていることに注意してください。
結果
ActicateActCtx 呼び出しは成功し、myapp.manifest と ManagedComObject.dll のマニフェストを正しく解析します。sxstrace.exe を使用してこれを確認しました。
C:\Python27\ManagedComObject.dll をプローブした後、CoCreateInstance の呼び出しが FileNotFound で失敗します。Fusion のログは、PrivatePath が設定されていないと主張しており (python.exe.config が存在しないためと考えられます)、単純に C:\mainapp で C# オブジェクトを探しません。
質問
なぜこれが失敗するのですか?CLR COM ローダー スタブが C# アセンブリをインポートできないためだと思います。このステップの前に失敗した場合、CLR は読み込まれません。そのため、CLR が ManagedCOMObject.dll を見つけられないことが原因であると信じてしまいます。
CLR が読み込まれていることに注意してください。これは、COM が現在のアクティベーション コンテキストを正常に調べて登録を見つけたことを意味すると思います。マニフェストで clrClass が何をするのか正確にはわかりませんが、おそらく CLR が正常に読み込まれました。
問題は、アセンブリをロードするときに CLR が ActCtx に注意を払っていないことだと思います。マネージ コードを作成している場合は、AppDomain.CurrentDomain.AssemblyResolve イベントにフックして、自分で DLL を見つけることができます。代わりに、アンマネージ コードを作成し、CLR を暗黙的にのみホストしているため、アプリケーションの PrivatePath やアセンブリのプローブ方法を何らかの方法で変更できますか?