📌

#62 【C#】Win32APIのDllImportを簡略化した

2024/09/25に公開

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
      
  • 元々Dllimportを使用していた箇所は型の見直しが必要になる可能性があります。

    • IntPtr型にしてたところをenumにする等。

以上です。
最後まで読んでいただきありがとうございます。

参考

Discussion