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
}
}