はじめに
ある日、筆者が特定のプロセスのウィンドウをC#でアクティブにできなくて困っていたところ、「Win32APIを使えばできるよ!」ということを教えてもらいました。
しかし、筆者はWin32APIというものを使ったことがなかったし、それがどういうものなのかも一切知りませんでした。
「もしかして、C#で開発してるエンジニアにとっては常識だったりする……?」
というわけで、ちょっと調べてみました。
誤りがあれば教えていただけますと幸いです。
Win32APIって何?
WindowsのOSの機能に、Windows上で動作するプログラムからアクセスするときに利用できる、Windowsの機能やリソースにアクセスするための関数やデータ構造を提供するAPIです。
C言語やC++のプログラムからアクセスすることができます。
Windows NT(32bitOS)が登場したころから存在するAPIであるため、かなり歴史は長いです。
何ができるの
Win32APIはコンピュータを制御・操作するための基本的な機能を提供しているため、Win32APIを利用すれば、Windowsの動作する環境であれば実行できるアプリケーションを作ることができます。
筆者はウィンドウをアクティブにするために使いましたが、他にも以下のリストに書かれているようなことができます。
https://learn.microsoft.com/ja-jp/windows/win32/apiindex/windows-api-list
それこそUIの作成からファイルアクセス、印刷、再起動やシャットダウンまで、WindowsのOSの機能をだいたい使えるようです。
どうやって使うの
筆者はC#で開発を行っています。
C言語とC++で使えるというWin32APIは、C#環境で使えるのでしょうか?
実は.NETにはそれを実現する仕組みがあります。
P/Invoke(プラットフォーム呼び出し)
P/Invokeはマネージドコード(.NET Framework等の.NET実行環境で実行が管理される、.NETの共通中間言語で記述されたプログラム)からアンマネージドコード(.NET実行環境で実行が管理されないプログラム)を呼び出すための仕組みです。マネージドコードからアンマネージドコードを呼び出す仕組みがあることで、Win32APIのような、OSの機能と深く関連づいているライブラリの機能を利用することができるのです。
System.Runtime.InteropServices名前空間を利用して、以下のように記述することでwin32APIを利用できます。
System.Runtime.InteropServices
[DllImport("user32.dll")]
static extern bool SetForegroundWindow(IntPtr hWnd);
呼び出したいAPIを、DllImport属性を付けて呼び出します。
DllImport属性の引数には、利用するライブラリのdll名を記載します。
また、Win32APIのメソッドはuser32.dll内にある(→プログラム内にない)ため、メソッドが外部にあることを示すextern修飾子を付ける必要があります。
ちなみに、例で紹介しているメソッドの引数のIntPtr hWnd
はウィンドウハンドルです。
ウィンドウハンドルはWindowsが各ウィンドウに割り振る管理番号(ポインタ)のことです。
さいごに
新しい武器を手に入れた気持ちです。まだウィンドウをピョコピョコさせただけですが……。
P/Invokeは、C#の学習を始めたばっかりの頃に書籍で学習した覚えはあったのですが、実際に使うことになって改めて調べ直しました。当時よりは理解できた気がします。
(externとかポインタとか、C言語の勉強をした時以来だなあ……)