用于键盘布局和编译器警告的 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 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您可以尝试使用以下声明:
CharSet
规范将清除 CA2101。将两个方法的返回值调整为正确的返回类型并在GetKeyboardLayoutName
上添加MarshalAs
返回值将清除 CA1901。You can try using the following declarations:
The
CharSet
specification will clear up CA2101. Adjusting the returns of both methods to the correct return types and adding theMarshalAs
for the return on theGetKeyboardLayoutName
will clear up the CA1901.LoadKeyboardLayout返回HKL,实际上是void*。
GetKeyboardLayoutName返回BOOL,实际上是32位int。所以,你需要定义
LoadKeyboardLayout 返回类型为 IntPtr,GetKeyboardLayoutName 返回类型为 int。
LoadKeyboardLayout returns HKL, which is actually void*.
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.