我正在与供应商提供的非托管 DLL 合作,以与一些自定义硬件进行交互。不幸的是,我无法发布供应商代码,但希望下面的净化代码能够提供足够的信息来说明问题的原因。
供应商 SDK 需要为硬件事件通知注册回调函数。我有一个来自供应商的实用程序来确认这是否成功发生。硬件将自定义 WIN32 消息发送到窗口,SDK 将自身附加到消息循环并在收到这些自定义消息之一时调用回调函数。
当应用程序直接运行时,一切正常。当应用在 Visual Studio 中运行时,注册成功,但不会触发事件。无论有无调试 (F5 / Crlt+F5) 运行都是如此。我还尝试在项目属性中禁用 Visual Studio Hosting 进程,但没有任何区别。
在 C# 类库中,我使用以下代码包装了供应商 SDK:
public class Basic {
private delegate void Callback(UInt32 Event, Byte status, UInt16 type, UInt16 devno);
private Callback mInstance;
public delegate void EventHandler(String message);
public event EventHandler HardwareEvent;
[DllImport("VendorSDK.dll")]
private static extern Int32 Register_Callback(Callback shuttleproc, UInt16 type, UInt16 devno);
[DllImport("VendorSDK.dll")]
private static extern Int32 Unregister_Callback(UInt16 type, UInt16 devno);
public Basic() {
mInstance = new Callback(CallbackHandler);
if (Register_Callback(mInstance, 1, 1) != 0)
throw new Exception("Error registereing");
}
~Basic() {
Unregister_Callback(1, 1);
}
public void CallbackHandler(UInt32 Event, Byte status, UInt16 type, UInt16 devno) {
if (HardwareEvent != null)
HardwareEvent(String.Format("Message: {0}, {1}, {2}, {3}", Event, status, type, devno));
}
}
然后,在 WPF 应用程序中,我像这样使用这个包装器:
public partial class MainWindow : Window {
Basic hardware;
public MainWindow() {
InitializeComponent();
}
protected override void OnSourceInitialized(EventArgs e) {
base.OnSourceInitialized(e);
hardware = new Basic();
hardware.HardwareEvent += new Basic.EventHandler(HardwareEvent);
}
void HardwareEvent(string message) {
Messages.Dispatcher.Invoke(new Action(() => { Messages.Items.Insert(0, message); }));
}
}
供应商 SDK 在 C++ 中提供了一个非托管示例,该示例与我的托管包装具有相同的问题。该应用程序在 Visual Studio 之外运行良好,但从 Visual Studio 内部启动时未收到消息。
我相信这是由于 Visual Studio 妨碍了回调,或者更有可能是当非托管供应商 DLL 访问当前窗口句柄 (HWND) 时返回了错误的值。然而,我不确定这一点。