Shell32を利用するには、参照にCOMの[Microsoft Shell Controls And Automation]を追加します。
[STAThread]
static void Main()
{
string path = @"C:\sample.mp3";
string directoryName = Path.GetDirectoryName(path);
string fileName = Path.GetFileName(path);
Shell32.Shell shell = new Shell32.Shell();
Shell32.Folder folder = shell.NameSpace(directoryName);
Shell32.FolderItem folderItem = folder.ParseName(fileName);
// すべてのプロパティを列挙
for (int i = 0; i < 1000; i++)
{
Console.WriteLine("{0}:{1},{2}",
i,
folder.GetDetailsOf(null, i),
folder.GetDetailsOf(folderItem, i));
}
// 指定のプロパティを取得
string prop0 = folder.GetDetailsOf(folderItem, 0);
string prop1 = folder.GetDetailsOf(folderItem, 1);
}
アプリケーションのエントリポイントにSTAThread属性を指定しないと、「型 'System.__ComObject' の COM オブジェクトをインターフェイス型 'Shell32.Shell' にキャストできません。IID '{286E6F1B-7113-4355-9562-96B7E9D64C54}' が指定されたインターフェイスの COM コンポーネント上での QueryInterface 呼び出しのときに次のエラーが発生したため、この操作に失敗しました: インターフェイスがサポートされていません (HRESULT からの例外:0x80004002 (E_NOINTERFACE))。」としてSystem.InvalidCastException例外が発生します。
フォルダ内の項目の詳細を取得できます。
string GetDetailsOf(
object vItem, // 取得対象のShell32.FolderItem
int iColumn // 取得対象のインデックス
)
Folder.GetDetailsOf method (Windows) | MSDN
vItemをnullとすると、プロパティ名が返されます。
Microsoft.WindowsAPICodePackに含まれるMicrosoft.WindowsAPICodePack.Shell.ShellFileクラスから、プロパティを取得できます。
string path = "sample.mp3"; ShellFile shellFile = ShellFile.FromFilePath(path); ShellProperties shellProperties = shellFile.Properties; // すべてのプロパティを列挙 ShellPropertyCollection shellPropertyCollection = shellProperties.DefaultPropertyCollection; foreach (IShellProperty shellProperty in shellPropertyCollection) { Console.WriteLine("{0},{1}", shellProperty.CanonicalName, shellProperty.ValueAsObject ); } // 指定のプロパティを取得 ShellProperties.PropertySystem propertySystem = shellProperties.System; string title = propertySystem.Title.Value; string[] authors = propertySystem.Author.Value;
一方でプロパティへ設定するには、取得に用いたValueプロパティへ設定します。
propertySystem.Title.Value = "sample";
propertySystem.Author.Value = new[] { "sample1", "sample2" };
無効な設定をしても例外などは発生しないため、設定が反映されたかどうかは取得して確認します。設定できない原因についてはエクスプローラのプロパティから設定してみることで、「エラー 0xC00D3E8D: 要求されたプロパティは見つかりませんでした。」のように確認できます。
複数のプロパティへ一括して設定するならば、ShellPropertyWriter.WriteProperty()を用います。ただしこの方法だと、無効な設定が1つでも含まれていると、すべての設定に失敗します。
using (ShellPropertyWriter shellPropertyWriter = shellProperties.GetPropertyWriter())
{
shellPropertyWriter.WriteProperty(SystemProperties.System.Title, "Sample");
shellPropertyWriter.WriteProperty(SystemProperties.System.Author, new[] { "Sample1", "Sample2" });
} // shellPropertyWriter.Close()は、Dispose()から呼ばれる
Solution 2016 - c# - How to set extended file properties? - Stack Overflow
無効なファイルに設定しようとすると、GetPropertyWriter()の呼び出し時に「Unable to get writable property store for this property.」としてMicrosoft.WindowsAPICodePack.Shell.PropertySystem.PropertySystemExceptionが投げられます。そのときInnerExceptionは、
となります。
WriteProperty()では内部でIPropertyStore::SetValue()が呼ばれることで値が設定され、Close()ではIPropertyStore::Commit()により保存されます。
書き換えの処理ではファイルの内容が変更されるのではなく、実際には一時ファイルが作成された上でリネームされます。たとえばC:\sample.wmvのプロパティを書き換えると、次のように処理されます。
このうち工程3以降のファイルの置換の処理は、File.Replace()と同じです。