動作確認環境:C# 8.0(.NET Core 3.1)、C# 9.0(.NET 5.0)
- SHGetKnownFolderIDList→アイテムIDリスト→SHGetFileInfoW→表示名・型名
Win32 APIのSHGetKnownFolderIDList
とSHGetFileInfoW
を使用してKnown Folderの表示名と型名を取得するサンプルコードです。型名は常に""
です。なお、別の方法としてSHGetNameFromIDList
関数(Microsoft Docs)があります。
クラス | 概要 |
---|---|
Program | Main関数 |
ShellKnownFolderIDList | Known FolderのアイテムIDリスト(LPITEMIDLIST)をSafeCoTaskMemPointer型で取得する機能を提供するクラスです。SHGetKnownFolderIDListのラッパーです。 |
SafeCoTaskMemHandle | アンマネージドリソースのMarshal.FreeCoTaskMem関数による解放を保証するためのクラスです。SafeHandleの派生クラスです。 |
ShellFileStringInfoForPIDL | アイテムIDリスト(LPITEMIDLIST)からシェルのファイル情報を取得する機能を提供するクラスです。SHGetFileInfoWのラッパーです。 |
C# 9(トップレベルステートメント)
using System; using System.Runtime.InteropServices; // デスクトップの表示名を取得する。 { using var pidl = ShellKnownFolderIDList.GetDesktopIDList(); var displayName = ShellFileStringInfoForPIDL.GetDisplayName(pidl, null); var typeName = ShellFileStringInfoForPIDL.GetTypeName(pidl, null); // "" Console.WriteLine((displayName, typeName)); // (デスクトップ, ) } // 更新プログラムフォルダの表示名を取得する。 { using var pidl = ShellKnownFolderIDList.GetAppUpdatesIDList(); var displayName = ShellFileStringInfoForPIDL.GetDisplayName(pidl, null); var typeName = ShellFileStringInfoForPIDL.GetTypeName(pidl, null); // "" Console.WriteLine((displayName, typeName)); // (インストールされた更新プログラム, ) } static class ShellKnownFolderIDList { static Guid FOLDERID_Desktop => new Guid("{B4BFCC3A-DB2C-424C-B029-7FE99A87C641}"); static Guid FOLDERID_AppUpdates => new Guid("{a305ce99-f527-492b-8b1a-7e76fa98d6e4}"); public static SafeCoTaskMemHandle GetDesktopIDList() => SHGetKnownFolderIDList(FOLDERID_Desktop); public static SafeCoTaskMemHandle GetAppUpdatesIDList() => SHGetKnownFolderIDList(FOLDERID_AppUpdates); public static SafeCoTaskMemHandle SHGetKnownFolderIDList(in Guid folderId) { NativeMethods.SHGetKnownFolderIDList(folderId, 0, default, out var pidl); return pidl; } static class NativeMethods { [DllImport("shell32.dll")] public static extern int SHGetKnownFolderIDList( in Guid rfid, uint dwFlags, IntPtr hToken, out SafeCoTaskMemHandle ppidl); } } sealed class SafeCoTaskMemHandle : SafeHandle { SafeCoTaskMemHandle() : base(default, true) { } public SafeCoTaskMemHandle(IntPtr handle, bool ownsHandle) : base(handle, ownsHandle) { } public override bool IsInvalid => handle == default; protected override bool ReleaseHandle() { Marshal.FreeCoTaskMem(handle); return true; } } static class ShellFileStringInfoForPIDL { const uint SHGFI_PIDL = 0x000000008; const uint SHGFI_DISPLAYNAME = 0x000000200; const uint SHGFI_TYPENAME = 0x000000400; //public static string GetDisplayName(SafeHandle pidl) //{ // var ret = NativeMethods.SHGetFileInfoW( // pidl, out var shfi, SHGFI_DISPLAYNAME); // if (ret == default) // Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error()); // return shfi.szDisplayName; //} public static string GetDisplayName(SafeHandle pidl, string defaultValue) { var ret = NativeMethods.SHGetFileInfoW( pidl, out var shfi, SHGFI_DISPLAYNAME); return (ret != default) ? shfi.szDisplayName : defaultValue; } //public static string GetTypeName(SafeHandle pidl) //{ // var ret = NativeMethods.SHGetFileInfoW( // pidl, out var shfi, SHGFI_TYPENAME); // if (ret == default) // Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error()); // return shfi.szTypeName; //} public static string GetTypeName(SafeHandle pidl, string defaultValue) { var ret = NativeMethods.SHGetFileInfoW( pidl, out var shfi, SHGFI_TYPENAME); return (ret != default) ? shfi.szTypeName : defaultValue; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] struct SHFILEINFOW { public IntPtr hIcon; public int iIcon; public uint dwAttributes; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] public string szDisplayName; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)] public string szTypeName; } static class NativeMethods { [DllImport("shell32.dll", ExactSpelling = true, CharSet = CharSet.Unicode)] public static extern IntPtr SHGetFileInfoW( SafeHandle pszPath, uint dwFileAttributes, out SHFILEINFOW psfi, uint cbFileInfo, uint uFlags); public static IntPtr SHGetFileInfoW(SafeHandle pidl, out SHFILEINFOW psfi, uint flags) => SHGetFileInfoW(pidl, 0, out psfi, (uint)Marshal.SizeOf<SHFILEINFOW>(), flags | SHGFI_PIDL); } }
Main関数(C# 8)
using System; using System.Runtime.InteropServices; class Program { static void Main() { // デスクトップの情報を取得する。 { using var pidl = ShellKnownFolderIDList.GetDesktopIDList(); var displayName = ShellFileStringInfoForPIDL.GetDisplayName(pidl, null); var typeName = ShellFileStringInfoForPIDL.GetTypeName(pidl, null); Console.WriteLine((displayName, typeName)); // (デスクトップ, ) } // 更新プログラムフォルダの情報を取得する。 { using var pidl = ShellKnownFolderIDList.GetAppUpdatesIDList(); var displayName = ShellFileStringInfoForPIDL.GetDisplayName(pidl, null); var typeName = ShellFileStringInfoForPIDL.GetTypeName(pidl, null); Console.WriteLine((displayName, typeName)); // (インストールされた更新プログラム, ) } } } internal static class ShellKnownFolderIDList { static Guid FOLDERID_Desktop => new Guid("{B4BFCC3A-DB2C-424C-B029-7FE99A87C641}"); static Guid FOLDERID_AppUpdates => new Guid("{a305ce99-f527-492b-8b1a-7e76fa98d6e4}"); public static SafeCoTaskMemHandle GetDesktopIDList() => SHGetKnownFolderIDList(FOLDERID_Desktop); public static SafeCoTaskMemHandle GetAppUpdatesIDList() => SHGetKnownFolderIDList(FOLDERID_AppUpdates); public static SafeCoTaskMemHandle SHGetKnownFolderIDList(in Guid folderId) { NativeMethods.SHGetKnownFolderIDList(folderId, 0, default, out var pidl); return pidl; } static class NativeMethods { [DllImport("shell32.dll")] public static extern int SHGetKnownFolderIDList( in Guid rfid, uint dwFlags, IntPtr hToken, out SafeCoTaskMemHandle ppidl); } } internal sealed class SafeCoTaskMemHandle : SafeHandle { SafeCoTaskMemHandle() : base(default, true) { } public SafeCoTaskMemHandle(IntPtr handle, bool ownsHandle) : base(handle, ownsHandle) { } public override bool IsInvalid => handle == default; protected override bool ReleaseHandle() { Marshal.FreeCoTaskMem(handle); return true; } } internal static class ShellFileStringInfoForPIDL { const uint SHGFI_PIDL = 0x000000008; const uint SHGFI_DISPLAYNAME = 0x000000200; const uint SHGFI_TYPENAME = 0x000000400; //public static string GetDisplayName(SafeHandle pidl) //{ // var ret = NativeMethods.SHGetFileInfoW( // pidl, out var shfi, SHGFI_DISPLAYNAME); // if (ret == default) // Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error()); // return shfi.szDisplayName; //} public static string GetDisplayName(SafeHandle pidl, string defaultValue) { var ret = NativeMethods.SHGetFileInfoW( pidl, out var shfi, SHGFI_DISPLAYNAME); return (ret != default) ? shfi.szDisplayName : defaultValue; } //public static string GetTypeName(SafeHandle pidl) //{ // var ret = NativeMethods.SHGetFileInfoW( // pidl, out var shfi, SHGFI_TYPENAME); // if (ret == default) // Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error()); // return shfi.szTypeName; //} public static string GetTypeName(SafeHandle pidl, string defaultValue) { var ret = NativeMethods.SHGetFileInfoW( pidl, out var shfi, SHGFI_TYPENAME); return (ret != default) ? shfi.szTypeName : defaultValue; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] struct SHFILEINFOW { public IntPtr hIcon; public int iIcon; public uint dwAttributes; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] public string szDisplayName; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)] public string szTypeName; } static class NativeMethods { [DllImport("shell32.dll", ExactSpelling = true, CharSet = CharSet.Unicode)] public static extern IntPtr SHGetFileInfoW( SafeHandle pszPath, uint dwFileAttributes, out SHFILEINFOW psfi, uint cbFileInfo, uint uFlags); public static IntPtr SHGetFileInfoW(SafeHandle pidl, out SHFILEINFOW psfi, uint flags) { return SHGetFileInfoW(pidl, 0, out psfi, (uint)Marshal.SizeOf<SHFILEINFOW>(), flags | SHGFI_PIDL); } } }