为非托管代码提供托管控制句柄 - 访问冲突

Posted

技术标签:

【中文标题】为非托管代码提供托管控制句柄 - 访问冲突【英文标题】:Giving managed control handles to unmanaged code - Access Violation 【发布时间】:2011-09-01 19:33:23 【问题描述】:

所以我有这个由第三方提供的 SDK,用于查看来自远程源的流式视频。远程源运行第三方提供的捕获和存储视频的服务器,我可以连接到该服务器并通过 SDK 获取视频。我通过 COM 引用 SDK,基本的非图形操作(如连接服务器、选择视频源等)都可以正常工作。

问题在于,使用此 SDK 向用户实际显示视频的主要(唯一)方法是将 hWnd(作为 int)传递给一个方法,然后将视频异步绘制到该窗口的客户区域.据我所知,这里的“窗口”具有 GUI 窗口的含义,在 .NET 术语中,它是任何带有窗口句柄的 WinForms 控件。就我而言,我使用的是 PictureBox 控件(用户希望看到的每个提要一个)。

问题是我显然不能只将托管 PictureBox 控件的句柄放入此 SDK 方法中,因为当我这样做时,我会收到来自非托管线程的 AccessViolationException。我正在编写一个用 VB 6 编写的示例程序(它在我的计算机上针对测试服务器工作),它对 VB PictureBox 做同样的事情,而且效果很好,但显然无论 SDK 试图做什么我们漂亮的安全 .NET 沙箱对象没有随 CLR 一起飞行。

帮助?我希望我能提供更多信息或代码示例,但我无法提供任何经过充分清理的东西,以至于它可以在一般情况下工作,而且我不能透露正在使用的 SDK。我认为我需要的只是告诉 .NET 我的引用代码应该被信任以对窗口执行它想要的操作,或者以某种方式将窗口移动到我的程序舒适的沙箱之外的管理较少的内存空间。

编辑:好的,已经取得了一点进展。我现在正在验证控件的句柄是否已使用 IsHandleCreated 创建,然后再将句柄提供给该方法。然而,正如 Hans Passant 所说,一个 IntPtr 不是一个 int。那么,如何将这个方钉安装在圆孔中?我已经尝试过 ToInt32() 函数和显式转换为 (int)。即使在为 32 位架构编译我的库时,两者都不起作用。我是否要回去找第三方说他们的 SDK 是不让我传递指针的 POS?

【问题讨论】:

应该可以。 hWnd 不是 int,不要试图让它在 64 位操作系统上工作。否则,本机代码有很多方法可以在没有您帮助的情况下使用 AV 进行轰炸。 你知道吗?可能就是这样;我在Win7 64位开发,互操作需要一个int,我不能直接将IntPtr Control.Handle传递给它。 【参考方案1】:

这应该可以正常工作。 Windows 窗体控件的Control.Handle 只是来自 Windows API 的标准 HWND。许多 DirectX 示例都使用这种精确的技术。

话虽如此,请确保在创建控件之前不会将其传递到本机代码中。例如,如果您在表单的构造函数(加载之前)期间传递句柄,则该句柄将在此时无效。

【讨论】:

谢谢。包含相关 PictureBox 的整个 UserControl 将尝试在其 Load 事件中设置初始视频源集。这会不会太快了? 这是问题所在;控件的 IsHandleCreated 属性为 false,所以此时我不能依赖句柄的值。我添加了一个可以跳过通话的检查,但现在视频永远不会显示,因为显然没有句柄。更多帮助? @KeithS:请参阅:msdn.microsoft.com/en-us/library/… 这可能会有所帮助:) 谢谢。我发现虽然 PB 是可见的,但它们在一个不可见的面板上。确保该面板可见让我获得了有效的句柄。但是,我仍然收到 AccessViolationException,可能与投射窗口句柄有关。见编辑 @KeithS:您可以(也许)在ToInt32() 之前/之后检查 hte 窗口句柄指针的值,只是为了验证这是问题所在......话虽如此,将 HWND 作为 int 传递只是很糟糕,在各个方面:(

以上是关于为非托管代码提供托管控制句柄 - 访问冲突的主要内容,如果未能解决你的问题,请参考以下文章

将 HBITMAP 句柄从非托管代码传递到托管代码以创建 System.Drawing.Bitmap 的安全性

使用 ATL/COM 将托管字节 [] 转换为非托管字节数组

WPF 应用程序托管 WCF 访问冲突

使用 P/Invoke 时为非托管代码存储数据

从非托管 C++ 调用 WCF 服务会导致访问冲突

具有构建功能和源代码控制的 Asp.net 托管服务提供商