「拡張」ファイルプロパティの読み取り/書き込み(C#)


104

Windowsエクスプローラーで確認できるC#の拡張ファイルプロパティ(コメント、ビットレート、アクセス日、カテゴリなど)の読み取り/書き込みの方法を見つけようとしています。これを行う方法はありますか?編集:私は主にビデオファイル(AVI / DIVX / ...)への読み取り/書き込みを行います


3
受け入れられた回答は拡張プロパティを取得する方法を示し、それらを設定する方法を示していないため、この質問は明らかに回答されていません
Dmitri Nesteruk 2013

1
拡張プロパティの設定については、stackoverflow.com
questions / 5337683 /…

回答:


83

VBに夢中でない人のために、ここにそれはc#にあります:

参照ダイアログのCOMタブからMicrosoft Shell Controls and Automationへの参照を追加する必要があることに注意してください。

public static void Main(string[] args)
{
    List<string> arrHeaders = new List<string>();

    Shell32.Shell shell = new Shell32.Shell();
    Shell32.Folder objFolder;

    objFolder = shell.NameSpace(@"C:\temp\testprop");

    for( int i = 0; i < short.MaxValue; i++ )
    {
        string header = objFolder.GetDetailsOf(null, i);
        if (String.IsNullOrEmpty(header))
            break;
        arrHeaders.Add(header);
    }

    foreach(Shell32.FolderItem2 item in objFolder.Items())
    {
        for (int i = 0; i < arrHeaders.Count; i++)
        {
            Console.WriteLine(
              $"{i}\t{arrHeaders[i]}: {objFolder.GetDetailsOf(item, i)}");
        }
    }
}

3
これらの値の1つをどのように設定しますか?たとえば、.txtファイルの作成者または発行者。私は勝つ7日午前、これを使用し、それが空白の著者と出版社と282個の他のプロパティを示してい
バイバブガーグ

1
@Vainbhav-これらを設定することはできません。
csharptest.net 2010

26
[参照]ダイアログの[COM]タブから、Microsoft Shell Controls and Automationへの参照を追加する必要があります。
csharptest.net 2011

2
どのようにそれらを設定するために、より良いこの質問に覆われている:stackoverflow.com/questions/5337683/...
ニコララウル

1
Windows 10では、フレームレート、フレームの高さ、幅などを含まない52のフィールドのみが返されます。
Minh Nguyen


26

ソリューション2016

次のNuGetパッケージをプロジェクトに追加します。

  • Microsoft.WindowsAPICodePack-Shell マイクロソフトによる
  • Microsoft.WindowsAPICodePack-Core マイクロソフトによる

プロパティの読み取りと書き込み

using Microsoft.WindowsAPICodePack.Shell;
using Microsoft.WindowsAPICodePack.Shell.PropertySystem;

string filePath = @"C:\temp\example.docx";
var file = ShellFile.FromFilePath(filePath);

// Read and Write:

string[] oldAuthors = file.Properties.System.Author.Value;
string oldTitle = file.Properties.System.Title.Value;

file.Properties.System.Author.Value = new string[] { "Author #1", "Author #2" };
file.Properties.System.Title.Value = "Example Title";

// Alternate way to Write:

ShellPropertyWriter propertyWriter =  file.Properties.GetPropertyWriter();
propertyWriter.WriteProperty(SystemProperties.System.Author, new string[] { "Author" });
propertyWriter.Close();

重要:

ファイルは、割り当てられた特定のソフトウェアによって作成された有効なファイルである必要があります。すべてのファイルタイプには特定の拡張ファイルプロパティがあり、それらのすべてが書き込み可能であるとは限りません。

デスクトップ上のファイルを右クリックしてプロパティを編集できない場合は、コードでそのファイルを編集することもできません。

例:

  • デスクトップにtxtファイルを作成し、拡張子をdocxに変更します。AuthorまたはTitleプロパティを編集することはできません。
  • Wordで開き、編集して保存します。今できます。

だから、いくつかを使用することを確認してください try catch

その他のトピック: MSDN:プロパティハンドラーの実装


Microsoftからのこれらの名前のパッケージはありません
Jacob Brewer

1
@JacobBrewerこれは、実際には「acdvorak」によってアップロードされたものです:nuget.org/packages/Microsoft.WindowsAPICodePack-Shell。Visual Studio NuGet-Package-Managerでは、「Microsoftによって」と表示されます。同様の名前を持つ他のパッケージは、そのフォークであり、適切に動作するか、さらには動作します。わからない...
Martin Schneider

25

VB.NETのこのサンプルは、すべての拡張プロパティを読み取ります。

Sub Main()
        Dim arrHeaders(35)

        Dim shell As New Shell32.Shell
        Dim objFolder As Shell32.Folder

        objFolder = shell.NameSpace("C:\tmp")

        For i = 0 To 34
            arrHeaders(i) = objFolder.GetDetailsOf(objFolder.Items, i)
        Next
        For Each strFileName In objfolder.Items
            For i = 0 To 34
                Console.WriteLine(i & vbTab & arrHeaders(i) & ": " & objfolder.GetDetailsOf(strFileName, i))
            Next
        Next

    End Sub

参照ダイアログのCOMタブからMicrosoft Shell Controls and Automationへの参照を追加する必要があります。


2
(少なくとも)Windows 7では、arrHeadersのサイズを280をわずかに超えて、追加のメタデータを大量に取得できることに注意してください。これは、WTVファイル(Windows 7 Media Centerで録画されたテレビ番組)からメタデータを取得する方法を探していたときにわかりました。
Richard

1
最初のi = 0から34までのループは、i = 0からInteger.MaxValueまでです。次に、objFolder.GetDetailsOf(objFolder.Items、i)の戻り値をテストします。nullまたは空白スペースが返される場合は、すべてのヘッダーがあります。
ティムマーフィー、

@TimMurphy、残念ながら、それは正しくありません(少なくともWindows 10または7では)。一部のヘッダーは空なので、すべてのインデックスをループする必要があります。(もちろん、数百万ではないため、ループを1,000に制限することができます。)
skst

8

このスレッドをありがとう!それは私がexeのファイルバージョンを理解したかったときに私を助けました。ただし、拡張プロパティと呼ばれるものの最後の部分を自分で理解する必要がありました。

Windowsエクスプローラーでexe(またはdll)ファイルのプロパティを開くと、[バージョン]タブが表示され、そのファイルの拡張プロパティが表示されます。それらの値の1つにアクセスしたいと思っていました。

これに対する解決策は、プロパティインデクサーFolderItem.ExtendedPropertyであり、プロパティの名前にすべてのスペースをドロップすると、値が取得されます。たとえば、File VersionはFileVersionになり、そこにあります。

これが他の人の役に立つことを願って、この情報をこのスレッドに追加したいと思っていました。乾杯!


2
これにより、コードが(少なくともほとんどの場合)英語以外の言語のマシンでも動作することが保証されます。
Ed Norris

1
ここでの小さな改善の1つは、FolderItemにExtendedProperty()が含まれていないことです。ただし、FolderItem2にはあります。
Mixxiphoid 2014

この答えは他よりも少し単純です。ここで機能するサンプルコードを提供しました:stackoverflow.com/a/46648086/661933
nawfal

8

GetDetailsOf()メソッド-フォルダー内のアイテムに関する詳細を取得します。たとえば、サイズ、タイプ、最後に変更された時刻などです。ファイルのプロパティは、Windows-OSバージョンによって異なる場合があります。

List<string> arrHeaders = new List<string>();

 Shell shell = new ShellClass();
 Folder rFolder = shell.NameSpace(_rootPath);
 FolderItem rFiles = rFolder.ParseName(filename);

 for (int i = 0; i < short.MaxValue; i++)
 {
      string value = rFolder.GetDetailsOf(rFiles, i).Trim();
      arrHeaders.Add(value);
 }

上記と同じコードをコピーして使用しました。しかし、ここでrunimeでCOM例外が発生しますFolder rFolder = shell.NameSpace(_rootPath);。ちなみに、私はWindows 8 OSを使用しています。
DonMax 2014年

1
そのエラーは何ですか?Shell32.dllの正しいバージョンを使用していることを確認してください。これをチェックして、多分役に立つ
RajeshKdev

1
上記のリンクの+1。提案したリンクは正常に機能しています。あなたからもう1つ助けが必要です。つまり、メタデータを取得するために単一のファイルをどのように渡すことができますか?それ以来、それはフォルダだけを渡すことを受け入れます。
DonMax 2014年

6
  • このスレッドや他の場所でいくつかのソリューションを検討した後、次のコードがまとめられました。これはプロパティを読み取るためだけです。
  • Shell32.FolderItem2.ExtendedProperty関数を機能させることができませんでした。文字列値を取り、そのプロパティの正しい値と型を返すはずです...これは常にnullであり、開発者の参照リソースは非常に薄いものでした。
  • WindowsApiCodePackは、私たちに以下のコードをもたらしたMicrosoftが放棄されているようです。

使用する:

string propertyValue = GetExtendedFileProperty("c:\\temp\\FileNameYouWant.ext","PropertyYouWant");
  1. 指定したファイルとプロパティ名の文字列として、必要な拡張プロパティの値を返します。
  2. 指定したプロパティが見つかるまでループするだけです-サンプルコードのようにすべてのプロパティが見つかるまでループしません
  3. 通常、Shell32オブジェクトを作成しようとすると、Windows Server 2008のようなWindowsバージョンで動作し、「タイプが「System .__ ComObject」のCOMオブジェクトをインターフェースタイプが「Shell32.Shell」にキャストできません」というエラーが発生します

    public static string GetExtendedFileProperty(string filePath, string propertyName)
    {
        string value = string.Empty;
        string baseFolder = Path.GetDirectoryName(filePath);
        string fileName = Path.GetFileName(filePath);
    
        //Method to load and execute the Shell object for Windows server 8 environment otherwise you get "Unable to cast COM object of type 'System.__ComObject' to interface type 'Shell32.Shell'"
        Type shellAppType = Type.GetTypeFromProgID("Shell.Application");
        Object shell = Activator.CreateInstance(shellAppType);
        Shell32.Folder shellFolder = (Shell32.Folder)shellAppType.InvokeMember("NameSpace", System.Reflection.BindingFlags.InvokeMethod, null, shell, new object[] { baseFolder });
    
        //Parsename will find the specific file I'm looking for in the Shell32.Folder object
        Shell32.FolderItem folderitem = shellFolder.ParseName(fileName);
        if (folderitem != null)
        {
            for (int i = 0; i < short.MaxValue; i++)
            {
                //Get the property name for property index i
                string property = shellFolder.GetDetailsOf(null, i);
    
                //Will be empty when all possible properties has been looped through, break out of loop
                if (String.IsNullOrEmpty(property)) break;
    
                //Skip to next property if this is not the specified property
                if (property != propertyName) continue;    
    
                //Read value of property
                value = shellFolder.GetDetailsOf(folderitem, i);
            }
        }
        //returns string.Empty if no value was found for the specified property
        return value;
    }

1
InvokeMember()を使用する代わりにshellIShellDispatchインターフェース(1〜6)のいずれかにキャストして、メンバーを直接呼び出すことができます。Shell32.IShellDispatch ishell = (Shell32.IShellDispatch)shell; Shell32.Folder shellFolder = ishell.NameSpace(baseFolder);
skst 2018年

5

ジャーカーの答えは少し単純です。MSで動作するサンプルコードを次に示します。

var folder = new Shell().NameSpace(folderPath);
foreach (FolderItem2 item in folder.Items())
{
    var company = item.ExtendedProperty("Company");
    var author = item.ExtendedProperty("Author");
    // Etc.
}

shell32を静的に参照できない場合は、次のように動的に呼び出すことができます。

var shellAppType = Type.GetTypeFromProgID("Shell.Application");
dynamic shellApp = Activator.CreateInstance(shellAppType);
var folder = shellApp.NameSpace(folderPath);
foreach (var item in folder.Items())
{
    var company = item.ExtendedProperty("Company");
    var author = item.ExtendedProperty("Author");
    // Etc.
}

1

プロパティを書き込もうとしているファイルの種類はわかりませんが、taglib-sharpは、このすべての機能を適切にラップする優れたオープンソースのタグ付けライブラリです。ほとんどの一般的なメディアファイルタイプをサポートしていますが、ほとんどすべてのファイルでより高度なタグ付けを行うことができます。

編集: 私はtaglibシャープへのリンクを更新しました。古いリンクは機能しなくなりました。

編集: kzuのコメントごとにリンクをもう一度更新しました。


これは非常に興味深いように見えます。主にビデオファイル(AVI、DIVXなど)を見ていきます。ポインタをありがとう
デビッド・ヘイズ

taglib-sharpリンクは
無効

おかげで、SteveC、私がこれを投稿した時点では両方のリンクが有効であり、どちらが正式な場所なのかはわかりませんでした。今、このlibにアクセスするのに適したサイトはノベルです。
モックオブジェクト2009

ヘッドアップkzuのおかげで、githubの場所も指すように元の回答のリンクを更新しました。
mockobject 2012年

1

これは、私がこのページで見つけたものとshell32オブジェクトのヘルプに基づいて拡張プロパティを読み取るためのソリューションです(書き込みではありません)。

明確にするために、これはハックです。このコードはWindows 10でも動作するようですが、いくつかの空のプロパティにヒットします。以前のバージョンのWindowsでは、次のものを使用する必要があります。

        var i = 0;
        while (true)
        {
            ...
            if (String.IsNullOrEmpty(header)) break;
            ...
            i++;

Windows 10では、読み取る必要のあるプロパティは約320あると想定し、空のエントリをスキップします。

    private Dictionary<string, string> GetExtendedProperties(string filePath)
    {
        var directory = Path.GetDirectoryName(filePath);
        var shell = new Shell32.Shell();
        var shellFolder = shell.NameSpace(directory);
        var fileName = Path.GetFileName(filePath);
        var folderitem = shellFolder.ParseName(fileName);
        var dictionary = new Dictionary<string, string>();
        var i = -1;
        while (++i < 320)
        {
            var header = shellFolder.GetDetailsOf(null, i);
            if (String.IsNullOrEmpty(header)) continue;
            var value = shellFolder.GetDetailsOf(folderitem, i);
            if (!dictionary.ContainsKey(header)) dictionary.Add(header, value);
            Console.WriteLine(header +": " + value);
        }
        Marshal.ReleaseComObject(shell);
        Marshal.ReleaseComObject(shellFolder);
        return dictionary;
    }

前述のとおり、ComアセンブリInterop.Shell32を参照する必要があります。

STA関連の例外が発生した場合の解決策は次のとおりです。

Shell32を使用してファイル拡張プロパティを取得するときの例外

これらのプロパティ名が外部システムでどのようになるかわかりません。また、辞書にアクセスするために使用するローカライズ可能な定数に関する情報が見つかりませんでした。また、返された辞書に[プロパティ]ダイアログのすべてのプロパティが含まれているわけではないこともわかりました。

ところでこれはひどく遅いです-少なくともWindows 10では-取得した文字列の日付を解析するのは難しいので、これを使うのは最初から悪い考えのようです。

Windows 10では、SystemPhotoProperties、SystemMusicPropertiesなどを含むWindows.Storageライブラリを必ず使用する必要があります。https: //docs.microsoft.com/en-us/windows/uwp/files/quickstart-getting-file-properties

そして最後に、私は投稿の用途がWindowsAPICodePackことをはるかに優れたソリューションをそこに

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.