#62 【C#】Win32APIのDllImportを簡略化した
C#でWin32APIを利用する際、一々DllImportを記述するのが非常に面倒だったので、手軽に利用できる方法を調べました。
没案1: PInvoke.net Visual Studio Extensionを使用する
PInvoke.net Visual Studio Extension は、DllImportの入力を補助してくれるVisualStudioの拡張機能のようです。残念ながら、私が使用している Visual Studio 2022 はサポートしていないらしく、Visual Studio上のマーケットプレイスでヒットせず、直接ダウンロードしてのインストールも失敗しました。
試していませんが、こちらを参考にサポートバージョンを無理やり書き換えればインストールできるかもしれません。
没案2: PInvoke.netからコピペする
PInvoke.netは、Win32APIのDllImport文がまとまっているサイトのようです。こちらのページで該当のWin32APIを検索し、import文をコピペするよう促している記事がいくつかありました。
ただし、筆者が確認した2024年3月時点では404エラーが出てしまいページ自体開けませんでした。
結論: CsWin32を使う
Microsft が提供する CsWin32 というパッケージを使用して、呼び出したい Win32APIをプロジェクト内に生成することができました。
手順1
VisualStudio の ツール > Nugetパッケージマネージャー > ソリューションのNugetパッケージの管理 から CsWin32 をインストールする
※プレリリースを含める にチェックを入れないと見つかりません
手順2
NativeMethods.txt という名前のテキストファイルを作成し、使用したいAPI名を記述する
WH_KEYBOARD_LL
SetWindowsHookEx
GetModuleHandle
手順3
ソリューションをビルドする
========== ビルド: 成功 1、失敗 0、最新の状態 0、スキップ 0 ==========
ビルド成功したら、完了です。
あとは、主に PInvoke.*** の形で使用したいAPIを呼び出せるはずです。
APIの呼び出し箇所から、定義へのジャンプもできるようになります。
修正前後比較
参考までに、修正前後のコードの一部を記載します。
NativeMethods.txt への追記が必要とはいえ、非常に手間が省けたのが分かるかと思います。
protected const int WH_KEYBOARD_LL = 0x000D;
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook, KeyboardProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curModule.ModuleName), 0);
PInvoke.SetWindowsHookEx(WINDOWS_HOOK_ID.WH_KEYBOARD_LL, proc, PInvoke.GetModuleHandle(curModule.ModuleName), 0);
注意点
-
自動生成されたコードの要求バージョンに応じて、C#のバージョンアップが必要になる可能性があります。
- C#バージョン不足によるビルドエラーが表示された場合、.csprojファイルの<PropertyGroup>内 に、C#バージョンを追記
<LangVersion>9.0</LangVersio
- C#バージョン不足によるビルドエラーが表示された場合、.csprojファイルの<PropertyGroup>内 に、C#バージョンを追記
-
元々Dllimportを使用していた箇所は型の見直しが必要になる可能性があります。
- IntPtr型にしてたところをenumにする等。
以上です。
最後まで読んでいただきありがとうございます。
Discussion