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

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();
  }
}
Imports System
Imports System.Runtime.InteropServices

Class Sample
  <DllImport("shell32.dll")> _
  Shared Function SHObjectProperties(ByVal hwnd As IntPtr, _
                                     ByVal shopObjectType As UInteger, _
                                     <MarshalAs(UnmanagedType.LPWStr)> ByVal pszObjectName As String, _
                                     <MarshalAs(UnmanagedType.LPWStr)> ByVal pszPropertyPage As String) As Boolean
  End Function

  Const SHOP_PRINTERNAME As UInteger = &H1
  Const SHOP_FILEPATH As UInteger = &H2
  Const SHOP_VOLUMEGUID As UInteger = &H4

  Public Shared Sub Main()

    ' プロパティを表示する対象のファイル・フォルダのパス
    Dim path As String = "C:\"

    If SHObjectProperties(IntPtr.Zero, SHOP_FILEPATH, path, String.Empty) Then
      Console.WriteLine("成功しました")
    Else
      Console.WriteLine("失敗しました")
    End If

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

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

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();
    }
}
Imports System
Imports System.Runtime.InteropServices

Class PropertiesDialog

    <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto, Pack:=4)> _
    Friend Structure SHELLEXECUTEINFO

        Public cbSize As Integer
        Public fMask As Integer
        Public hWnd As IntPtr
        <MarshalAs(UnmanagedType.LPTStr)> Public lpVerb As String
        <MarshalAs(UnmanagedType.LPTStr)> Public lpFile As String
        <MarshalAs(UnmanagedType.LPTStr)> Public lpParameters As String
        <MarshalAs(UnmanagedType.LPTStr)> Public lpDirectory As String
        Public nShow As Integer
        Public hInstApp As IntPtr
        Public lpIDList As IntPtr
        <MarshalAs(UnmanagedType.LPTStr)> Public lpClass As String
        Public hkeyClass As IntPtr
        Public dwHotKey As Integer
        Public hIcon As IntPtr
        Public hProcess As IntPtr

    End Structure

    Friend Const SEE_MASK_INVOKEIDLIST As Integer = &HC
    Friend Const SEE_MASK_NOCLOSEPROCESS As Integer = &H40
    Friend Const SEE_MASK_FLAG_NO_UI As Integer = &H400

    <DllImport("shell32.dll", EntryPoint:="ShellExecuteEx", CharSet:=CharSet.Auto)> _
    Friend Shared Function ShellExecuteEx(ByRef sei As SHELLEXECUTEINFO) As <MarshalAs(UnmanagedType.Bool)> Boolean
    End Function

    ''' <summary>ファイルが見つかりません。</summary>
    Friend Const SE_ERR_FNF As Integer = 2

    ''' <summary>パスが見つかりません。</summary>
    Friend Const SE_ERR_PNF As Integer = 3

    ''' <summary>ファイルアクセスが拒否されました。</summary>
    Friend Const SE_ERR_ACCESSDENIED As Integer = 5

    ''' <summary>メモリ不足です。</summary>
    Friend Const SE_ERR_OOM As Integer = 8

    ''' <summary>共有違反が発生しました。</summary>
    Friend Const SE_ERR_SHARE As Integer = 26

    ''' <summary>ファイル関連付けが完全ではないか無効です。</summary>
    Friend Const SE_ERR_ASSOCINCOMPLETE As Integer = 27

    ''' <summary>DDEトランザクションがタイムアウトにより中断されました。</summary>
    Friend Const SE_ERR_DDETIMEOUT As Integer = 28

    ''' <summary>DDEトランザクションが失敗しました。</summary>
    Friend Const SE_ERR_DDEFAIL As Integer = 29

    ''' <summary>他のDDEトランザクションが処理されていたためDDEトランザクションが終了できませんでした。</summary>
    Friend Const SE_ERR_DDEBUSY As Integer = 30

    ''' <summary>ファイル関連付けが不明です。</summary>
    Friend Const SE_ERR_NOASSOC As Integer = 31

    ''' <summary>DLLが見つかりません。</summary>
    Friend Const SE_ERR_DLLNOTFOUND As Integer = 32

    ''' <summary>
    ''' アプリケーションのメイン エントリ ポイントです。
    ''' </summary>
    Shared Sub Main(ByVal args() As String)

        ' プロパティを表示する対象のファイル
        Dim path As String = "C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\IDE\devenv.exe"

        Dim info As SHELLEXECUTEINFO

        info = New SHELLEXECUTEINFO

        info.cbSize = Marshal.SizeOf(info)
        info.fMask = SEE_MASK_NOCLOSEPROCESS Or SEE_MASK_INVOKEIDLIST Or 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(info)) Then

            Console.WriteLine("成功しました。")

        Else

            Console.WriteLine("失敗しました。")

        End If

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

    End Sub

End Class
実行例