2017-08-11 15 views
1

私は、OSに応じて使用していたDLL Importステートメントを変更する必要がある状況に遭遇しました。他の誰かがこれを観察したのか、それとも理由を知っているのか、これを処理する良い方法があるのだろうかと思います。GetAsyncKeyState DLLImportステートメント

ここに問題を示す最小限のコードスニペットがあります。それはシフトキーのステータスを出力するだけの簡単なコマンドラインアプリです。

using System; 
using System.Runtime.InteropServices; 

namespace Shift 
{ 
    class Program 
    { 
     [DllImport("user32.dll", SetLastError = true)] 
     public static extern short GetAsyncKeyState(ushort virtualKeyCode); 

     static void Main(string[] args) 
     { 
      Console.WriteLine("Shift is: " + GetAsyncKeyState(0x10)); 
     } 
    } 
} 

上記のWindows 8.1のx64またはときにWindows 7のx64上の32ビットおよび実行として構築に実行したときに私のために正常に動作します。ただし、x64用にコンパイルされたWindows 7システムでは動作しません。その場合GetAsyncKeyStateは常に0を返します。

DLLImportを以下に変更すると、x64用にコンパイルされたときにWindows 7システムで動作します。

[DllImport("user32.dll", SetLastError = true)] 
public static extern short GetAsyncKeyState(int virtualKeyCode); 
+1

最初の宣言にはバグがありました。 (ushortは16ビット、intは32ビットです - 32ビット版と64ビット版Windowsのすべてのバージョン)。それがうまく動作するような錯覚を含むバグが発生する可能性があります。あなたの質問は何ですか? –

+4

x64は非常に異なる呼び出し規約を持っています。 fastcallスタイルの規約では、最初の4つの引数はスタックの代わりにレジスタを通過します。 x86では16ビット値をスタックにプッシュすることはできないため、暗黙の整数昇格があります。宣言にバグを隠すものこの関数を宣言する最良の方法は、引数型としてKeysを使用することです。 Keys.ShiftKeyを渡すことができるので、列挙型はうまくいきます。 pinvoke.netのWebサイトと比較することは決して痛いことではありません。 –

+0

@SimonMourier問題を指摘してくれてありがとう。 – denver

答えて

2

元の宣言は間違っています。ドキュメントはここにある:

SHORT WINAPI GetAsyncKeyState(
    _In_ int vKey 
); 

正しいP /呼び出しがある:私はSetLastErrorの設定を削除した

[DllImport("user32.dll")] 
public static extern short GetAsyncKeyState(int vKey); 

https://msdn.microsoft.com/en-us/library/windows/desktop/ms646293.aspx

これは、宣言を与えます。このドキュメントでは、SetLastErrorが呼び出されていることには言及していません。