我是否需要一个包装类来 p/调用来自 user32 的一些函数.dll



所以我正在开发一个 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 plii)

起初,我将它们与所有主要表单代码一起放在文件中,作为public partial class MainForm的一部分,这一切都有效。然后,当我在Visual Studio Community 2015中运行代码分析时,它抱怨说:"因为它们是P/Invoke方法,所以应该在名为NativeMethods,SafeNativeMethods或UnsafeNativeMethods的类中定义。

因此,作为一个优秀的程序员,我总是服从他的IDE的突发奇想,我立即制作一个新的类文件并遇到第一个问题。

包含这些函数的类是否不安全(是否也是非托管的)?哪个名字 我应该使用并且应该使用 [DebuggerNonUserCode] 属性将类声明为internal static

当我做更多的阅读试图弄清楚这一点时,我不断遇到为代码制作包装类的引用,所以我开始研究它。这产生了大量关于安全性的东西和 c++ 或 c 的包装器、原型以及大量其他似乎没有帮助的信息,让我自己完全迷失了方向。

所以我想我想知道的是两件事。 第一,我需要(或 这样做是最好的做法)制作一个包装类来使用这些 方法,如果是这样,我将如何去做?

2nd,如果我使类不安全/安全本机方法,我应该调用它 安全还是不安全?所有方法都应该公开吗?还是应该做 将方法声明为私有并编写一些getter/setter,例如:

public IntPtr getGetForegroundWindow()
{
    return GetForegroundWindow()
}

public setSendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr, lParam)
{
    SendMessage(hWnd, Msg, wParam, lParam);
}

还是我需要使用委托或其他东西来代替二传手和获取者?

很抱歉这个问题有点脑残。每次我认为我找到了答案时,我最终都会提出更多的问题,所有关于安全/不安全/安全的讨论都让我担心。我不介意谷歌搜索和阅读主题,但只是为了弄清楚要阅读什么的阅读清单变得越来越大,所以我想我会停下来问这里,看看我是否问了正确的问题。提前谢谢。

我会创建一个静态类。

namespace NativeMethods
{
    public static class User32
    {
        [DllImport("user32.dll")]
        public static extern IntPtr SendMessage(IntPtr hWnd, UInt32 msg, IntPtr wParam, ref RECT lParam);
    }
}

仅在执行某些操作时创建包装器,例如保持参数转换/检查状态。


要包装 pInvoke 的情况

包装 PInvoke 方法的一个示例可能是本机方法分配内存并返回句柄。在这种情况下,您需要创建一个跟踪句柄的包装器。它应实现释放非托管资源的IDisposable

对于()示例:(您应该检查释放模式)

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);
    }    
}

最新更新