.NET TIPS

実行ファイルからアプリケーションのアイコンを取得するには?

デジタルアドバンテージ 一色 政彦
2005/03/25

 Windowsアプリケーションの実行ファイル(.EXEファイル)には、アプリケーション内容を示すアイコン(以降、アプリケーション・アイコン)が割り当てられていることが一般的だ。例えば次の画面にある「notepad.exe」には「メモ帳(の絵)」のアイコンが割り当てられている。このアプリケーション・アイコンのおかげで、ユーザーはエクスプローラなどでファイルを参照するときにも、すぐに目的のファイルを識別することができる。

notepad.exeに割り当てられているアプリケーション・アイコン
エクスプローラで「C:\WINDOWS」を開いたところ。
  notepad.exeには「メモ帳」のアイコンが割り当てられている。

 本稿では、このようなアプリケーション・アイコンを実行ファイルから取得する方法を紹介する。

アプリケーション・アイコンをファイルから取得する方法

 アプリケーション・アイコンは、.NET用のリソースではなく、Win32システム用のリソースである(「Win32リソース」と呼ばれる。Win32リソースについては「TIPS:VS.NETで画像などのリソースを利用するには?(組込編)」のコラムを参照してほしい)。このWin32リソースのアイコンをファイルから読み出す手段は、.NETには用意されていないようだ。従って、Win32 APIを用いて取得するしかない。具体的にはWin32 APIのSHGetFileInfo関数を使用する。

 以下は、実際にそのSHGetFileInfo関数を用いてnotepad.exeのアプリケーション・アイコンを取得するためのサンプル・コードである。

using System.Runtime.InteropServices;

private void Form1_Load(object sender, System.EventArgs e)
{
  // アプリケーション・アイコンを取得
  SHFILEINFO shinfo = new SHFILEINFO();
  IntPtr hSuccess = SHGetFileInfo(@"C:\WINDOWS\notepad.exe", 0, ref shinfo, (uint)Marshal.SizeOf(shinfo), SHGFI_ICON | SHGFI_LARGEICON);
  if (hSuccess != IntPtr.Zero)
  {
    Icon appIcon = Icon.FromHandle(shinfo.hIcon);
    // ピクチャーボックスにアプリケーション・アイコンをセット
    this.pictureBox1.Image = appIcon.ToBitmap();
  }
}

// SHGetFileInfo関数
[DllImport("shell32.dll")]
private static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbSizeFileInfo, uint uFlags);

// SHGetFileInfo関数で使用するフラグ
private const uint SHGFI_ICON = 0x100; // アイコン・リソースの取得
private const uint SHGFI_LARGEICON = 0x0; // 大きいアイコン
private const uint SHGFI_SMALLICON = 0x1; // 小さいアイコン

// SHGetFileInfo関数で使用する構造体
private struct SHFILEINFO
{
  public IntPtr hIcon;
  public IntPtr iIcon;
  public uint dwAttributes;
  [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
  public string szDisplayName;
  [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
  public string szTypeName;
};
アプリケーション・アイコンを取得するサンプル・コード(C#)
 
Imports System.Runtime.InteropServices

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
  ' アプリケーション・アイコンを取得
  Dim shinfo As New SHFILEINFO()
  Dim hSuccess As IntPtr = SHGetFileInfo("C:\WINDOWS\notepad.exe", 0, shinfo, Marshal.SizeOf(shinfo), SHGFI_ICON Or SHGFI_LARGEICON)
  If hSuccess.Equals(IntPtr.Zero) = False Then
    Dim appIcon As Icon = Icon.FromHandle(shinfo.hIcon)
    ' ピクチャーボックスにアプリケーション・アイコンをセット
    Me.PictureBox1.Image = appIcon.ToBitmap()
  End If
End Sub

' SHGetFileInfo関数
Private Declare Ansi Function SHGetFileInfo Lib "shell32.dll" (ByVal pszPath As String, ByVal dwFileAttributes As Integer, ByRef psfi As SHFILEINFO, ByVal cbFileInfo As Integer, ByVal uFlags As Integer) As IntPtr

' SHGetFileInfo関数で使用するフラグ
Private Const SHGFI_ICON As Integer = &H100 ' アイコン・リソースの取得
Private Const SHGFI_LARGEICON As Integer = &H0 ' 大きいアイコン
Private Const SHGFI_SMALLICON As Integer = &H1 ' 小さいアイコン

' SHGetFileInfo関数で使用する構造体

Private Structure SHFILEINFO
  Public hIcon As IntPtr
  Public iIcon As IntPtr
  Public dwAttributes As Integer
  <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=260)> _
  Public szDisplayName As String
  <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=80)> _
  Public szTypeName As String
End Structure
アプリケーション・アイコンを取得するサンプル・コード(VB.NET)
厳密には、C#のサンプル・コードでuint型になっている個所はUInt32型にするのが好ましいが、そうした場合、VB.NETではUInt32型変数に数値を代入するときにConvert.ToUInt32メソッドなどを使ってデータ型を変換しなければならないので、コード量が増える。本稿の例では、同じ32ビット整数型のInteger(Int32型)でも問題ないため、ここではInteger型で代用している。

 上記のコードでは、フォームのLoadイベント・ハンドラ(form1_Loadメソッド)で、まずWin32 APIのSHGetFileInfo関数によりアプリケーションのアイコン・リソース情報(SHFILEINFO構造体データ)を取得している。

SHFILEINFO shinfo = new SHFILEINFO();
IntPtr hSuccess = SHGetFileInfo(@"C:\WINDOWS\notepad.exe", 0, ref shinfo, (uint)Marshal.SizeOf(shinfo), SHGFI_ICON | SHGFI_LARGEICON);

 次に、そのアイコン・リソース情報の中に含まれているアイコン・ハンドル(hIcon)をパラメータに指定してIconクラス(System.Drawing名前空間)のFromHandleメソッドを呼び出している。

Icon appIcon = Icon.FromHandle(shinfo.hIcon);

 そのメソッドの戻り値としてIconオブジェクトを取得し、そのToBitmapメソッドによりアイコンをビットマップ化して、それをピクチャボックス・コントロールに指定している。

this.pictureBox1.Image = appIcon.ToBitmap();

 Win32 APIであるSHGetFileInfo関数の戻り値とパラメータの内容を次の表にまとめた(なおWin32 APIの宣言方法や呼び出し方法については、「TIPS:Win32 APIやDLL関数を呼び出すには?」を参照してほしい)。

項目 説明
戻り値 パラメータ5のuFlagsの値によって戻り値のルールは変化する。本稿の例では、アイコン・リソース情報の取得に成功すれば0以外が返り、失敗すれば0が返る
パラメータ1(pszPath) アプリケーション・アイコンを含むファイルへのパス
パラメータ2(dwFileAttributes) パラメータ5のuFlagsにSHGFI_USEFILEATTRIBUTESを指定した場合に使用する。本稿ではこのフラグを指定しないので、この値は無視される(つまり使われていない)
パラメータ3(psfi) SHFILEINFO構造体のデータ(詳細後述)。ここからアイコン・リソース情報が得られる
パラメータ4(cbFileInfo) SHFILEINFO構造体のサイズ(バイト数)
パラメータ5(uFlags) 取得するファイル情報の内容を細かく指定するためのフラグ。本稿では、SHGFI_ICONフラグを指定してアイコン・リソースが取得できるようにし、さらにSHGFI_LARGEICONフラグも指定して、そのリソースが「大きなアイコン」となることを設定している
SHGetFileInfo関数の戻り値とパラメータ

 上記表のパラメータ5にはフラグを指定するようになっているが、サンプル・コードではこのフラグとして指定できる値を定数として記述している(実際にはもっと多くのフラグが存在するが、ここでは本稿に関連する必要最小限のものしか記載していない)。

 またパラメータ3には、SHFILEINFO構造体を指定するようになっているが、Win32 APIの構造体を宣言および使用する方法については、「TIPS:Win32 APIやDLL関数に構造体を渡すには?」を参照してほしい。

 本稿で使用している構造体メンバのhIconはアイコンのハンドルを示すためのものだ。これ以外のメンバは本稿では利用していないので、その説明は割愛する。

 上記のサンプル・コードを実行すると、次の画面のようになる。

サンプル・プログラムの実行結果
notepad.exeのアプリケーション・アイコンがピクチャボックス・コントロール上に表示されているところ。

 この画面を見ると、フォーム上に配置したピクチャボックス・コントロールにnotepad.exeのアプリケーション・アイコンが表示されているのが確認できる。End of Article

カテゴリ:Windowsフォーム 処理対象:リソース
カテゴリ:クラス・ライブラリ 処理対象:リソース
使用ライブラリ:Iconクラス(System.Drawing名前空間)
関連TIPS:VS.NETで画像などのリソースを利用するには?(組込編)
関連TIPS:Win32 APIやDLL関数を呼び出すには?
関連TIPS:Win32 APIやDLL関数に構造体を渡すには?
 
この記事と関連性の高い別の.NET TIPS
Win32 APIやDLL関数を呼び出すには?
ファイルに関連付けられたアイコンを取得するには?
Win32 APIやDLL関数に構造体を渡すには?
ドライブをフォーマットするためのダイアログを表示するには?
Win32 API呼び出しを手軽に記述するには?
このリストは、(株)デジタルアドバンテージが開発した
自動関連記事探索システム Jigsaw(ジグソー) により自動抽出したものです。
generated by

「.NET TIPS」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間