我正在使用 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();
}
主机应用程序要调用的注册函数:
[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;