Win32 API関数を用いてファイル・フォルダのプロパティを表示する方法について。

§1 SHObjectProperties

SHObjectPropertiesを使用すると、さまざまなオブジェクトのプロパティダイアログを表示できる。 任意のファイル・フォルダのプロパティを表示したい場合は、第2引数shopObjectTypeにSHOP_FILEPATHを指定する。 以下の例では引数hwndにIntPtr.Zeroを指定しているが、親ウィンドウが存在する場合はそのウィンドウのハンドルを指定する。

using System;
using System.Runtime.InteropServices;

class Sample {
  [DllImport("shell32.dll")]
  static extern bool SHObjectProperties(IntPtr hwnd,
                                        uint shopObjectType,
                                        [MarshalAs(UnmanagedType.LPWStr)] string pszObjectName,
                                        [MarshalAs(UnmanagedType.LPWStr)] string pszPropertyPage);

  const uint SHOP_PRINTERNAME = 0x1;
  const uint SHOP_FILEPATH = 0x2;
  const uint SHOP_VOLUMEGUID = 0x4;

  static void Main()
  {
    // プロパティを表示する対象のファイル・フォルダのパス
    var path = @"C:\";

    if (SHObjectProperties(IntPtr.Zero, SHOP_FILEPATH, path, string.Empty))
      Console.WriteLine("成功しました");
    else
      Console.WriteLine("失敗しました");

    Console.WriteLine("終了するにはEnterキーを押してください");
    Console.ReadLine();
  }
}

なお、引数shopObjectTypeとpszObjectNameに指定する値を変えることでファイル・フォルダ以外のプロパティも表示でき、例えばプリンタのプロパティなども表示することができる。

§2 ShellExecuteEx

ShellExecuteExはファイルのオープン・実行だけでなく、verbを指定することでファイルに様々な動作を行うことが出来る。 SHELLEXECUTEINFO.lpVerb に"properties"を代入することによって、ファイルを実行するのではなく、プロパティを表示することができる。

関数が失敗すると、falseが返されると同時に、SHELLEXECUTEINFO.hInstAppに32以下のエラー値が代入される。 エラー値とその具体的な意味はコード中のSE_ERR〜の定数にある通り。 この例ではSHELLEXECUTEINFO.hWndにIntPtr.Zeroを指定しているが、親ウィンドウが存在する場合はそのウィンドウのハンドルを指定する。

using System;
using System.Runtime.InteropServices;

class PropertiesDialog
{
    [StructLayout( LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 4 )]
    internal struct SHELLEXECUTEINFO
    {
        public int cbSize;
        public int fMask;
        public IntPtr hWnd;
        [MarshalAs(UnmanagedType.LPTStr)] public string lpVerb;
        [MarshalAs(UnmanagedType.LPTStr)] public string lpFile;
        [MarshalAs(UnmanagedType.LPTStr)] public string lpParameters;
        [MarshalAs(UnmanagedType.LPTStr)] public string lpDirectory;
        public int nShow;
        public IntPtr hInstApp;
        public IntPtr lpIDList;
        [MarshalAs(UnmanagedType.LPTStr)] public string lpClass;
        public IntPtr hkeyClass;
        public int dwHotKey;
        public IntPtr hIcon;
        public IntPtr hProcess;
    }

    internal const int SEE_MASK_INVOKEIDLIST   = 0x000C;
    internal const int SEE_MASK_NOCLOSEPROCESS = 0x0040;
    internal const int SEE_MASK_FLAG_NO_UI     = 0x0400;

    [DllImport("shell32.dll", EntryPoint = "ShellExecuteEx", CharSet = CharSet.Auto)]
    [return: MarshalAs(UnmanagedType.Bool)]
    internal extern static bool ShellExecuteEx( ref SHELLEXECUTEINFO sei );

    /// <summary>ファイルが見つかりません。</summary>
    internal const int SE_ERR_FNF = 2;

    /// <summary>パスが見つかりません。</summary>
    internal const int SE_ERR_PNF = 3;

    /// <summary>ファイルアクセスが拒否されました。</summary>
    internal const int SE_ERR_ACCESSDENIED = 5;
    
    /// <summary>メモリ不足です。</summary>
    internal const int SE_ERR_OOM = 8;
    
    /// <summary>共有違反が発生しました。</summary>
    internal const int SE_ERR_SHARE = 26;
    
    /// <summary>ファイル関連付けが完全ではないか無効です。</summary>
    internal const int SE_ERR_ASSOCINCOMPLETE = 27;
    
    /// <summary>DDEトランザクションがタイムアウトにより中断されました。</summary>
    internal const int SE_ERR_DDETIMEOUT = 28;
    
    /// <summary>DDEトランザクションが失敗しました。</summary>
    internal const int SE_ERR_DDEFAIL = 29;
    
    /// <summary>他のDDEトランザクションが処理されていたためDDEトランザクションが終了できませんでした。</summary>
    internal const int SE_ERR_DDEBUSY = 30;
    
    /// <summary>ファイル関連付けが不明です。</summary>
    internal const int SE_ERR_NOASSOC = 31;
    
    /// <summary>DLLが見つかりません。</summary>
    internal const int SE_ERR_DLLNOTFOUND = 32;

    /// <summary>
    /// アプリケーションのメイン エントリ ポイントです。
    /// </summary>
    [STAThread]
    static void Main(string[] args)
    {
        // プロパティを表示する対象のファイル
        string path = @"C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\IDE\devenv.exe";

        SHELLEXECUTEINFO info;

        info = new SHELLEXECUTEINFO();

        info.cbSize = Marshal.SizeOf(info);
        info.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_INVOKEIDLIST | SEE_MASK_FLAG_NO_UI;
        info.hWnd = IntPtr.Zero;
        info.lpFile = path;
        info.lpVerb = "properties";
        info.lpParameters = "\0";
        info.lpDirectory  = "\0";
        info.nShow = 0;
        info.hInstApp = IntPtr.Zero;
        info.lpIDList = IntPtr.Zero;
        info.lpClass = "\0";
        info.hkeyClass = IntPtr.Zero;
        info.dwHotKey = 0;
        info.hIcon = IntPtr.Zero;
        info.hProcess = IntPtr.Zero;

        if ( ShellExecuteEx( ref info ) )
        {
            Console.WriteLine( "成功しました。" );
        }
        else
        {
            Console.WriteLine( "失敗しました。" );
        }

        Console.WriteLine( "終了するにはEnterキーを押してください。" );
        Console.ReadLine();
    }
}
実行例