実行ファイルにアイコンを設定することができますが、このアイコンを実行ファイルから抜き出すことはできないのでしょうか?

またこのようにdllのなかにもアイコンがあります。これらを抜き出すことはできないのでしょうか?

実はExtractIconEx関数というAPI関数を使えば可能です。

ExtractIconEx

では以下のような説明がされています。

ExtractIconEx関数は

指定された実行可能ファイル、ダイナミックリンクライブラリ(DLL)、またはアイコンファイルからアイコンのハンドルを取得し、配列変数に格納する。

アイコンの総数を調べたいときはnIconIndex パラメータに -1 、phIconLarge パラメータに 0 (NULL) 、phIconSmall パラメータに 0 (NULL) を指定する。

大きいアイコンと小さいアイコンも取得できる。

実行ファイルやdllからアイコンを抜きとるプログラム

まず指定されたファイルにアイコンが存在するのかを調べます。

これが0以外を返せば戻り値の値だけアイコンが存在することがわかります。

次にアイコンを取得します。16×16のアイコンと32×32のアイコンを取得できるのですが、32×32のアイコンだけで十分なので、

第4引数はIntPtr.Zeroにしています。16×16のアイコンは取得できません。

アイコンのハンドルが配列のなかに取得できたらループ文でアイコンのハンドルからBitmapを取得してpngファイルにして保存しています。

処理が終わったらアイコンオブジェクトも破棄しないといけないのですが、上記処理の場合、

とやっているのでアイコンオブジェクトは破棄されます。またアイコンのハンドルから取得されたBitmapもDisposeされています。しかしアイコンのハンドルはそのままでは破棄されません。そこでAPI関数のDestroyIcon関数を使って後始末しなければなりません。

アイコンを所得して保存するメソッドができたので、あとは呼び出すだけです。

取得できたアイコン画像

ところで C:\Windows\System32\imageres.dll ならアイコンが取得できるのですが、このファイルをコピーして別のフォルダ内でアイコンを取り出そうとしてもうまくいきません。なぜだろう・・・