开发者

C# P/Invoke for keyboard layout and compiler warnings

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 recei开发者_JAVA技巧ves 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!


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.


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜