RegasmおよびCom Interopの偽陰性
-
22-07-2019 - |
質問
COM経由でライブラリを公開しようとしていますが、実際の問題よりもツールと戦っているようです。 COM公開クラスの記述方法に関係なく、次の警告が表示されます。<!> quot; XXX.dllには、COM interop <!> quot;に登録できるタイプが含まれていません。 (プロジェクトプロパティでCOM相互運用機能の登録としてプロジェクトをマーク)。以下の単純なクラス(署名され、ComVisible(false)でマークされたアセンブリ内の唯一のクラス)でさえ、引き続き警告が続きます:
[Guid("77699130-7D58-4d29-BE18-385871B000D1")]
[ComVisible(true)]
public interface IExample
{
string GetText();
void SetText(string text);
}
[Guid("F91E5EE1-D220-43b5-90D1-A48E81C478B7")]
[ComVisible(true)]
public class Example : IExample
{
private string m_text = "default text";
public string GetText()
{
return m_text;
}
public void SetText(string text)
{
m_text = text;
}
}
<!> quot;タイプが正常に登録された<!> quot;と喜んで述べている出力のコマンドラインからregasmを実行しようとしました。ただし、/ verboseスイッチを使用して実行すると、追加の情報は表示されません(名前または登録されている型の数だけが表示されることを思い出すようです)。また、/ regfileスイッチでregasmを実行して、これを生成するregfileを生成しようとしました。
[HKEY_CLASSES_ROOT\ComExample.Example]
@="ComExample.Example"
[HKEY_CLASSES_ROOT\ComExample.Example\CLSID]
@="{F91E5EE1-D220-43B5-90D1-A48E81C478B7}"
[HKEY_CLASSES_ROOT\CLSID\{F91E5EE1-D220-43B5-90D1-A48E81C478B7}]
@="ComExample.Example"
[HKEY_CLASSES_ROOT\CLSID\{F91E5EE1-D220-43B5-90D1-A48E81C478B7}\InprocServer32]
@="mscoree.dll"
"ThreadingModel"="Both"
"Class"="ComExample.Example"
"Assembly"="COMInteropTesting, Version=1.0.0.0, Culture=neutral, PublicKeyToken=8568e57f6b170d6c"
"RuntimeVersion"="v2.0.50727"
[HKEY_CLASSES_ROOT\CLSID\{F91E5EE1-D220-43B5-90D1-A48E81C478B7}\InprocServer32\1.0.0.0]
"Class"="ComExample.Example"
"Assembly"="COMInteropTesting, Version=1.0.0.0, Culture=neutral, PublicKeyToken=8568e57f6b170d6c"
"RuntimeVersion"="v2.0.50727"
[HKEY_CLASSES_ROOT\CLSID\{F91E5EE1-D220-43B5-90D1-A48E81C478B7}\ProgId]
@="ComExample.Example"
[HKEY_CLASSES_ROOT\CLSID\{F91E5EE1-D220-43B5-90D1-A48E81C478B7}\Implemented Categories\{62C8FE65-4EBB-45E7-B440-6E39B2CDBF29}]
私はCOMウィザードではありませんが、登録は有効なようです。ただし、アセンブリでregasmを実行すると、レジストリに何も表示されないようです。
だから私の質問は、登録を動作させるために私の簡単な例で何かが欠けているかどうか、間違った兆候が見られ、登録が実際に正しいか、COM登録が実際に機能するかどうかをどのように判断できますか
編集: Kevによって提案された変更を使用すると、VS2008からの警告を避けることができませんでしたが、実際にはregasmを使用してレジストリに登録されたものを取得できました(VS2008統合のレジストリには何もありません)。
次に、単純なクラスを削除しようとしたため、空のアセンブリができました。これでregasmを実行しても、いかなる種類の警告も報告されず、<!> quot;タイプが正常に登録された<!> quot;のみが報告されました。 <!> quot; RegAsm:warning RA0000:型が登録されていません<!> quot; COMに誤って公開される可能性のある他のアセンブリの一部でRegAsmを実行する場合。ここで何が起こっているのですか、レジストリ以外のものを信頼できますか?また、regasmのオン/オフ警告はどうですか?
解決
次のように、コードに基づいてクラスライブラリプロジェクトを作成しました。
プロジェクトのプロパティページで、[署名]タブを選択します。 [アセンブリに署名する]チェックボックスをオンにして、[厳密な名前のキーファイルを選択する]ドロップダウンボックスから<New...>
を選択します。
次に、次のクラスを追加しました(Example.cs)
:
[Guid("77699130-7D58-4d29-BE18-385871B000D1")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
[ComVisible(true)]
public interface IExample
{
[DispId(1)]
string GetText();
[DispId(2)]
void SetText(string text);
}
[Guid("F91E5EE1-D220-43b5-90D1-A48E81C478B7")]
[ClassInterface(ClassInterfaceType.None)]
[ComVisible(true)]
public class Example : IExample
{
private string m_text = "default text";
[ComVisible(true)]
public string GetText()
{
return m_text;
}
[ComVisible(true)]
public void SetText(string text)
{
m_text = text;
}
}
次にプロジェクトをビルドし、ビルドからDLLが出力されたコマンドラインにドロップしました。
登録するには:
regasm.exe COMInteropTesting.dll /register /codebase /tlb
コンポーネントを複数のアプリケーションからアクセス可能にする必要がある場合:
gacutil.exe -i COMInteropTesting.dll
これはすべてWindows 2003 32ビット、Windows 2008 32ビット、およびWindows 7 64ビットで正常に機能しました。
1つの落とし穴は、64ビットシステムでCScriptを使用してコンポーネントをテストする場合、正しいCScriptインタープリターを実行する必要があるということです。 32ビットRegAsm.exe
(C:\Windows\Microsoft.NET\Framework\v2.0.50727
で)を使用してアセンブリを登録した場合、c:\Windows\SysWOW64
で32ビットCScriptインタープリターを実行する必要があります。