using System; using System.IO; using System.Runtime.InteropServices; namespace NaGet.InteropServices { /// /// PEファイルの種類 /// public enum PEFileType : uint { /// /// 不明な形式、あるいはPEファイルヘッダを持たない /// Unknown = 0, /// /// Windowsコンソールアプリケーション /// WinConsole = 1, /// /// Windows GUIアプリケーション /// WinGUI = 2, /// /// MS-DOS(及びコマンドプロンプト)でのCOMファイル /// MSDosCom = 3, } public sealed class PEFileInfoUtils { // 呼び出し禁止 private PEFileInfoUtils() { } /// /// 渡された実行ファイルの種類を返す。内部でSHGetFileInfoを使用。 /// /// 実行ファイル(*.exe,*.dll)へのパス /// 実行ファイルの種類 public static PEFileType GetPEFileType(string path) { PEFileType fileType; try { SHFILEINFO info = new SHFILEINFO(); int type = (int) shGetFileInfo(path, 0, ref info, SHGFI.ExeType); const int MZ = 0x5a4d; const int NE = 0x504e; const int PE = 0x4550; switch (type) { case MZ: fileType = PEFileType.MSDosCom; break; case PE: fileType = PEFileType.WinConsole; break; default: int loWord = type & 0xffff; int hiWord = (type >> 16) & 0xffff; if (((loWord == PE) || (loWord == NE)) && ((hiWord == 0x0300) || (hiWord == 0x0350) || (hiWord == 0x0400))) { fileType = PEFileType.WinGUI; } else { fileType = PEFileType.Unknown; } break; } } catch (FileNotFoundException e) { throw new FileNotFoundException(e.Message, e); } catch (IOException) { fileType = PEFileType.Unknown; } return fileType; } #region SHGetFileInfo [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] 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; } private enum SHGFI : uint { Icon = 256, DisplayName = 512, TypeName = 1024, Attributes = 2048, IconLocation = 4096, ExeType = 8192, SysIconIndex = 16384, LinkOverlay = 32768, Selected = 65536, AttrSpecified = 131072, LargeIcon = 0, SmallIcon = 1, OpenIcon = 2, PIDL = 8, UseFileAttributes = 16 } [DllImport("shell32.dll", CharSet=CharSet.Auto)] private static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbFileInfo, uint uFlags); /// /// SHGetFileInfoを呼び出す便利メソッド。ファイル読み込みなどに失敗したり、 /// 実行ファイルでない場合はIOExceptionを投げます。 /// /// ファイルパス /// ファイル属性 /// ファイル情報 /// フラグ private static IntPtr shGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, SHGFI uFlags) { if (! File.Exists(pszPath)) { throw new FileNotFoundException(null, pszPath); } IntPtr hSuccess = SHGetFileInfo(pszPath, dwFileAttributes, ref psfi, (uint)Marshal.SizeOf(psfi), (uint) uFlags); if (hSuccess == IntPtr.Zero) { throw new IOException(string.Format("Maybe {0} is not a executable file.", pszPath)); } return hSuccess; } #endregion } }