C# を使用して、ブラック ボックス化されたネイティブ Win32 アプリケーションの拡張機能を作成しています。実行時に、アプリケーションは拡張機能で Register という名前のエクスポートされた関数を呼び出し、COM オブジェクトを渡します。そして、その COM オブジェクトを介して、アプリケーションに対して何らかの作業を行うことができます。
問題は、このアプローチがかなり奇妙に機能していることです。COM インターフェイスにはいくつかのメソッドがあります。
[ComImport, Guid("75C46594-F6D6-4138-AC11-603C061ECC75")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IService
{
[return:MarshalAs(UnmanagedType.U4)]
uint GetVersion();
[return: MarshalAs(UnmanagedType.U4)]
uint GetLocale();
[return: MarshalAs(UnmanagedType.Bool)]
bool CheckVersion([In, MarshalAs(UnmanagedType.I4)]int version);
[return: MarshalAs(UnmanagedType.SysInt)]
IntPtr GetMainWindow();
}
また、ホスト アプリケーションによって呼び出される Register 関数は次のとおりです。
[return: MarshalAs(UnmanagedType.Bool)]
public static bool Register([In, MarshalAs(UnmanagedType.Interface)]IService service)
{
Log("Executing Register");
try
{
Log(service.GetVersion());
}
catch (Exception e)
{
Log(e.ToString());
}
Log("Exiting Register");
return true;
}
コードでこれらのメソッドを呼び出すと、予期しない値が返されることがあります (GetLocale は 0 またはロケール ID ではないランダムな値を返します。CheckVersion は true を返し、false を返すこともあります)。 UI はまだ応答していますが、その仕事をやめるだけです。) コードを再構築するか、アプリケーションを再起動すると、動作する可能性があります。
そこで、別のアプローチを試みました。その COM インターフェイスの関数をプロキシとして公開するネイティブ ライブラリを作成すると、拡張機能は P/Invoking ネイティブ ライブラリを介してアプリケーションを操作できます。正常に動作するので、C# での COM 相互運用性に問題があるのではないかと思います。誰かが問題を解決するのを手伝ってくれますか?
アップデート:
ホスト アプリケーションは COM を介していくつかのインターフェイスを公開し、それらのいくつかは複数の継承を持っていますが、IService は実際には IUnknown から継承されていますが、その一部のメソッドは他の COM オブジェクトを返します。メソッドの順序が重要であることを知りませんでした。たぶん、C# で定義を変更して再試行できます。
また、ホスト アプリケーションの作成者は IDL ファイルを提供してくれませんでした。Pascal ヘッダー ファイルだけです。
type IService = interface(IUnknown)
['{75C46594-F6D6-4138-AC11-603C061ECC75}']
function CheckVersion(Version: Integer): BOOL;
function GetVersion: Longword;
function GetLocaleID: Longword;
//These functions return other COM objects.
function GetQueryManager: IQueryManager;
function GetLogManager: ILogManager;
//......
function GetMainWindow: HWND;
function ExecuteCommand(Cmd: Integer; Param: Pointer): BOOL;
property LocaleID: Longword read GetLocaleID;
//These are properties encapsulate some functions above.
property QueryManager: IQueryManager read GetQueryManager;
property LogManager: ILogManager read GetLogManager;
property MainWindow: HWND read GetMainWindow;
//......
end;