ファイルパスから PIDL(シェルネームスペースITEM ID)を取得する - C#

C#でファイルパスから(シェルネームスペースITEM ID(PIDL)を取得するコードを紹介します。

UI

下図のUIを作成します。フォームにボタン一つ、テキストボックス2つを配置します。

コード

下記のコードを記述します。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using ShellNamespace;
using System.Runtime.InteropServices;

namespace ShellNamespaceDemo
{
  public partial class Form_GetPidlFromPath : Form
  {
    private WindowsAPI.IShellFolder m_DesktopShellFolder = null;

    public Form_GetPidlFromPath()
    {
      InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
      string PathString = textBox1.Text;

      int hRes = WindowsAPI.SHGetDesktopFolder(ref m_DesktopShellFolder);
      if (hRes != 0) {
        Marshal.ThrowExceptionForHR(hRes);
      }

      uint pchEaten;
      IntPtr ppidl;
      WindowsAPI.SFGAOF attr = WindowsAPI.SFGAOF.SFGAO_FOLDER | WindowsAPI.SFGAOF.SFGAO_HASSUBFOLDER
        | WindowsAPI.SFGAOF.SFGAO_STREAM | WindowsAPI.SFGAOF.SFGAO_DROPTARGET 
        | WindowsAPI.SFGAOF.SFGAO_FILESYSTEM | WindowsAPI.SFGAOF.SFGAO_LINK 
        | WindowsAPI.SFGAOF.SFGAO_SYSTEM | WindowsAPI.SFGAOF.SFGAO_NONENUMERATED;
      m_DesktopShellFolder.ParseDisplayName(IntPtr.Zero, IntPtr.Zero, PathString, out pchEaten, out ppidl, ref attr);

      WindowsAPI.SHFILEINFO shinfo = new WindowsAPI.SHFILEINFO();
      IntPtr ret = WindowsAPI.SHGetFileInfo(ppidl, 0, out shinfo, 
        (uint)Marshal.SizeOf(typeof(WindowsAPI.SHFILEINFO)), 
        WindowsAPI.SHGFI.SHGFI_DISPLAYNAME | WindowsAPI.SHGFI.SHGFI_PIDL);
      textBox2.Text += shinfo.szDisplayName;

    }
  }
}

解説

  int hRes = WindowsAPI.SHGetDesktopFolder(ref m_DesktopShellFolder);
  if (hRes != 0) {
    Marshal.ThrowExceptionForHR(hRes);
  }
上記コードが、デスクトップシェルフォルダーの取得コードです。SHGetDesktopFolderでデスクトップシェルフォルダーを取得します。戻り値が0以外の場合はデスクトップシェルフォルダーの取得に失敗しているため、例外を発生させます。

  uint pchEaten;
  IntPtr ppidl;
  WindowsAPI.SFGAOF attr = WindowsAPI.SFGAOF.SFGAO_FOLDER | WindowsAPI.SFGAOF.SFGAO_HASSUBFOLDER
    | WindowsAPI.SFGAOF.SFGAO_STREAM | WindowsAPI.SFGAOF.SFGAO_DROPTARGET 
    | WindowsAPI.SFGAOF.SFGAO_FILESYSTEM | WindowsAPI.SFGAOF.SFGAO_LINK 
    | WindowsAPI.SFGAOF.SFGAO_SYSTEM | WindowsAPI.SFGAOF.SFGAO_NONENUMERATED;
  m_DesktopShellFolder.ParseDisplayName(IntPtr.Zero, IntPtr.Zero, PathString, out pchEaten, out ppidl, ref attr);
上記コードにより、ファイルパスからPIDL(シェルネームスペースITEM ID)を取得します。PIDLの取得は、IShellFolderのParseDisplayNameメソッドを利用します。IShellFolderはデスクトップシェルフォルダーを使用しています。

  WindowsAPI.SHFILEINFO shinfo = new WindowsAPI.SHFILEINFO();
  IntPtr ret = WindowsAPI.SHGetFileInfo(ppidl, 0, out shinfo, 
    (uint)Marshal.SizeOf(typeof(WindowsAPI.SHFILEINFO)), 
    WindowsAPI.SHGFI.SHGFI_DISPLAYNAME | WindowsAPI.SHGFI.SHGFI_PIDL);
  textBox2.Text += shinfo.szDisplayName;
取得したPIDLから、情報を取得するコードです。ファイル情報の取得は、SHGetFileInfo()を利用します。

実行結果

プロジェクトを実行します。下図のウィンドウが表示されます。


上部のテキストボックス(textBox1)にファイルパスを入力します。


[button1]をクリックします。ファイルパスからPIDLを取得し、そのPIDLを利用してエクスプローラでの表示名を取得しテキストボックスに表示します。


"c:\windows\system32"を入力した場合の結果です。"Sytem32"とSが大文字になっており、シェルネームスペースの表示名であることが確認できます。(パスを加工した結果でない)


著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用
最終更新日: 2020-03-21
作成日: 2015-09-29
iPentec all rights reserverd.