2

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;
4

0 に答える 0