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

发布于 2024-11-18 22:11:57 字数 1035 浏览 0 评论 0原文

我不习惯 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 Platform SDK 文档以帮助确定 应该使用什么数据类型而不是“long”。

并且(我认为这不太重要,因为键盘布局名称只是数字):

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

我尝试使用 IntPtr 来处理第一个警告,但这并不能解决问题。有人可以帮我指出这些声明的正确形式吗? 谢谢!

I'm not used to P/Invoke but I should declare a couple of WinAPI functions for getting or setting the keyboard layout. I declared the functions like:


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

But when I compile this (in a C# WPF application) I get the warnings:

CA1901
Microsoft.Portability
As it is declared in your code, the return type of P/Invoke
will be 4 bytes wide on 64-bit platforms.
This is not correct, as the actual native declaration of
this API indicates it should be 8 bytes wide on 64-bit platforms.
Consult the MSDN Platform SDK documentation for help determining
what data type should be used instead of 'long'.

and (I suppose this is of less concern as keyboard layout names are just digits):

CA2101
Microsoft.Globalization
To reduce security risk, marshal parameter 'pwszKLID' as Unicode, by setting DllImport.CharSet to CharSet.Unicode, or by explicitly marshaling the parameter as UnmanagedType.LPWStr. If you need to marshal this string as ANSI or system-dependent, specify MarshalAs explicitly, and set BestFitMapping=false; for added security, also set ThrowOnUnmappableChar=true.

I tried using IntPtr for the first warning, but this does not solve the issue. Could anyone help by pointing me to the correct form for these declarations?
Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

晚雾 2024-11-25 22:11:57

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

[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。

You can try using the following declarations:

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

The CharSet specification will clear up CA2101. Adjusting the returns of both methods to the correct return types and adding the MarshalAs for the return on the GetKeyboardLayoutName will clear up the CA1901.

酒几许 2024-11-25 22:11:57

LoadKeyboardLayout返回HKL,实际上是void*。

typedef PVOID HANDLE;
typedef HANDLE HKL;

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

LoadKeyboardLayout returns HKL, which is actually void*.

typedef PVOID HANDLE;
typedef HANDLE HKL;

GetKeyboardLayoutName returns BOOL, which is actually 32-bit int. So, you need to define
LoadKeyboardLayout return type as IntPtr, and GetKeyboardLayoutName return type as int.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文