c# P/Invoke用于键盘布局和编译器警告



我不习惯p/Invoke,但我应该声明几个WinAPI函数来获取或设置键盘布局。我这样声明函数:


[DllImport("user32.dll")]
private static extern long LoadKeyboardLayout(
    string pwszKLID,    // input locale identifier
    uint Flags          // input locale identifier options
    );
[DllImport("user32.dll")]
private static extern long GetKeyboardLayoutName(
    StringBuilder pwszKLID  //[out] string that receives the name of the locale identifier
    );

但是当我编译这个(在c# WPF应用程序中)时,我得到警告:

CA1901 微软。可移植性正如在代码中声明的那样,P/Invoke的返回类型在64位平台上将为4字节宽。的实际本地声明是不正确的这个API表明它在64位平台上应该是8字节宽。请查阅MSDN平台SDK文档以获得帮助用什么数据类型代替'long'

和(我想这是不太关心的键盘布局名称只是数字):

CA2101 微软。全球化为了降低安全风险,通过设置DllImport将参数'pwszKLID'封送为Unicode。CharSet到CharSet。或显式地将参数封送为UnmanagedType.LPWStr。如果您需要封送此字符串作为ANSI或系统相关的,请显式指定MarshalAs,并设置BestFitMapping=false;为了增加安全性,还可以设置ThrowOnUnmappableChar=true。

我尝试使用IntPtr作为第一个警告,但这并不能解决问题。谁能告诉我这些声明的正确表格是什么吗?谢谢!

您可以尝试使用以下声明:

[DllImport("user32.dll", CharSet=CharSet.Unicode)]
private static extern IntPtr LoadKeyboardLayout(
    string pwszKLID,    // input locale identifier
    uint Flags          // input locale identifier options
    );
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
[return : MarshalAs(UnmanagedType.Bool)]
private static extern bool GetKeyboardLayoutName(
    StringBuilder pwszKLID  //[out] string that receives the name of the locale identifier
    );

CharSet规范将澄清CA2101。将这两种方法的返回值调整为正确的返回类型,并在GetKeyboardLayoutName的返回值上添加MarshalAs,将清除CA1901。

LoadKeyboardLayout返回HKL,这实际上是void*.

<>之前typedef PVOID HANDLE;typepedef HANDLE;之前

GetKeyboardLayoutName返回BOOL,它实际上是32位整型。所以,你需要定义LoadKeyboardLayout返回类型为IntPtr, GetKeyboardLayoutName返回类型为int.

最新更新