我是不是需要一个包装类来从 user32.dll 中 p/invoke'ing 一些函数
Posted
技术标签:
【中文标题】我是不是需要一个包装类来从 user32.dll 中 p/invoke\'ing 一些函数【英文标题】:Do I need a wrapper class for p/invoke'ing a few functions from user32.dll我是否需要一个包装类来从 user32.dll 中 p/invoke'ing 一些函数 【发布时间】:2016-07-09 20:50:16 【问题描述】:所以我正在开发一个 c# Windows 窗体应用程序,我的部分代码使用了一些来自 user32.dll 的方法。在下面列出它们。
public static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam); public static extern bool ReleaseCapture(); public static extern IntPtr GetForegroundWindow(); public static extern int GetWindowText(IntPtr hWnd, [MarshalAs(UnmanagedType.LPWStr)] StringBuilder lpString, int nMaxCount); public static extern uint GetWindowThreadProcessId public static extern bool GetLastInputInfo(ref LASTINPUTINFO pii)起初我将它们与所有主要表单代码一起作为public partial class MainForm
的一部分放在文件中,这一切都有效。然后,当我在 Visual Studio Community 2015 中运行代码分析时,它抱怨说“因为它们是 P/Invoke 方法,它们应该在名为 NativeMethods、SafeNativeMethods 或 UnsafeNativeMethods 的类中定义。
因此,作为一名优秀的程序员,我总是听从他的 IDE 的一时兴起,我立即制作了一个新的类文件并遇到了第一个问题。
包含这些函数的类会是不安全的(它也是非托管的)吗?哪个名字 我应该使用并且应该使用
[DebuggerNonUserCode]
属性将类声明为internal static
?
当我阅读更多内容试图弄清楚这一点时,我不断遇到为代码制作包装类的参考资料,因此我开始研究它。这产生了大量关于 c++ 或 c 的安全性和包装器、原型以及大量其他似乎没有帮助的信息,让我完全迷失了方向。
所以我想我想知道两件事。第一,我需要(或 这样做是否是最佳实践)制作一个包装类来使用这些 方法,如果是这样,我将如何去做?
第二,如果我创建类 Unsafe/SafeNativeMethods 我应该调用它吗 安全还是不安全?所有方法都应该公开吗?还是应该 将方法声明为私有并编写一些 getter/setter,例如:
public IntPtr getGetForegroundWindow()
return GetForegroundWindow()
或
public setSendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr, lParam)
SendMessage(hWnd, Msg, wParam, lParam);
或者我是否需要使用委托或其他东西来代替 setter 和 getter?
很抱歉这个问题有点脑残。每次我认为我找到了答案时,我都会遇到更多问题,所有关于安全/不安全/安全的讨论都让我担心。我不介意谷歌搜索和阅读主题,但只是为了弄清楚要阅读什么的阅读清单越来越大,所以我想我会停下来问这里,看看我是否问对了问题。提前致谢。
【问题讨论】:
【参考方案1】:我会创建一个静态类。
namespace NativeMethods
public static class User32
[DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hWnd, UInt32 msg, IntPtr wParam, ref RECT lParam);
仅在执行某些操作时创建包装器,例如保持参数转换/检查状态。
要包装 pInvokes 的情况
包装 PInvoke 方法的一个例子可能是本地方法分配内存并返回句柄。在这种情况下,您需要创建一个跟踪句柄的包装器。它应该实现IDisposable
来释放非托管资源。
for (pseudo) 示例:(你应该检查 dispose 模式)
public class MyWrapper : IDisposable
[DllImport("MyLibrary.dll")]
private static extern IntPtr DoAllocSomeMemory(int size);
[DllImport("MyLibrary.dll")]
private static extern void ReleaseMe(IntPtr handle);
private IntPtr _handle;
public MyWrapper()
_handle = DoAllocSomeMemory(8000);
public void Dispose()
ReleaseMe(_handle);
【讨论】:
应该和MainForm在同一个命名空间吗? 通常你想在多个项目中重用这些类,所以我会把它们放在一个单独的库中。 就我而言,它们永远不会被重复使用,但我想确保我遵循最佳实践。澄清一下,您是在建议我创建一个类库的第二个项目,然后在原始项目中引用这个新的类库? 是的,这样您就可以将该库重用于其他项目。以上是关于我是不是需要一个包装类来从 user32.dll 中 p/invoke'ing 一些函数的主要内容,如果未能解决你的问题,请参考以下文章