COM互操作奇怪

时间:2012-12-05 11:54:47

标签: c# com interop

我正在使用C#为黑盒子本机Win32应用程序编写扩展。 在运行时,应用程序将在extesion中调用名为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等),有时甚至会崩溃主应用程序(实际上不是崩溃, 用户界面仍在响应但只是停止做它的工作。)重建代码或重新启动应用程序后,它可能会有效。

所以我尝试了另一种方法。我创建一个本机库公开该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;

0 个答案:

没有答案