Читання / запис властивостей "розширених" файлів (C #)


104

Я намагаюся дізнатися, як читати / записувати до розширених властивостей файлів у C # напр., Коментар, швидкість передачі даних, дата звернення, категорія тощо, які можна побачити в Windows Explorer. Будь-які ідеї, як це зробити? EDIT: Я в основному буду читати / писати у відеофайли (AVI / DIVX / ...)


3
На це питання явно не дано відповіді, оскільки прийнята відповідь лише показує, як отримати розширені властивості, а не як їх встановити .
Дмитро Нестерук

1
Для установки розширених властивостей см stackoverflow.com/questions/5337683 / ...
VoteCoffee

Відповіді:


83

Для тих, хто не божевільний на VB, ось він у c #:

Зауважте, вам потрібно додати посилання на управління Microsoft Shell і автоматизацію на вкладці COM діалогового вікна Посилання.

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
як би встановити одне з цих значень? наприклад, автор або видавець для .txt-файлу. Я на виграш 7 і використовував це, і це показує порожнього автора та видавця та 282 інших властивостей
Vaibhav Garg

1
@Vainbhav - Ви не можете їх встановити.
csharptest.net

26
На вкладці COM діалогового вікна «Відбиття» потрібно додати посилання на Microsoft Shell Controls and Automation.
csharptest.net

2
Як їх встановити, краще висвітлюється в цьому питанні: stackoverflow.com/questions/5337683/…
Nicolas Raoul

1
У Windows 10 він повертає лише 52 поля, не включаючи частоту кадрів, висоту кадру, ширину, ....?
Minh Nguyen

27

Там же виріб для CodeProject для читача ID3. І нитка на kixtart.org, яка містить більше інформації про інші властивості. В основному, вам потрібно викликати GetDetailsOf()метод на об'єкті оболонки папки для shell32.dll.


Дякую, я маю змогу зібрати разом те, що мені потрібно з цього
Девід Хейс,

26

Рішення 2016 року

Додайте наступні пакети NuGet до свого проекту:

  • Microsoft.WindowsAPICodePack-Shell від Microsoft
  • Microsoft.WindowsAPICodePack-Core від Microsoft

Властивості читання та запису

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". Інші пакети з подібними назвами - це вилки, і вони також можуть працювати належним чином або навіть краще. Я не знаю ...
Мартін Шнайдер

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

Ви повинні додати посилання на елементи управління Microsoft Shell і автоматизацію з COM вкладки Посилання діалогового вікна.


2
Варто зазначити, що в Windows 7 (принаймні) ви можете збільшити розмір arrHeaders до трохи більше 280 і отримати багато додаткових метаданих. Я дізнався це, коли шукав спосіб отримати метадані з файлу WTV (телевізійне шоу, записане в Windows 7 Media Center).
Річард

1
Перший для циклу i = 0 до 34 повинен бути для i = 0 до Integer.MaxValue. Потім перевірити значення повернення objFolder.GetDetailsOf (objFolder.Items, i). Якщо він повертає нульовий або пробільний простір, то у вас є всі заголовки.
Тім Мерфі

@TimMurphy, на жаль, це не правильно (принаймні, в Windows 10 або 7). Деякі заголовки порожні, тому вам потрібно провести цикл через усі індекси. (Звичайно, оскільки їх немає мільйонів, ви можете обмежити цикл до 1000.)
skst

8

Дякую, хлопці, за цю тему! Це допомогло мені, коли я хотів з’ясувати версію файлу exe. Однак мені потрібно було з’ясувати останній шматочок із того, що називається Extended Properties.

Якщо ви відкриєте властивості файлу exe (або dll) у Windows Explorer, ви отримаєте вкладку "Версія" та перегляд "Розширені властивості" цього файлу. Я хотів отримати доступ до одного з цих значень.

Рішенням цього є індекс індексу властивостей FolderItem.ExtendedProperty, і якщо ви скинете всі пробіли в ім'я власності, ви отримаєте значення. Наприклад, версія файлу переходить у FileVersion, і там у вас є.

Сподіваюся, це допомагає комусь іншому, я просто подумав, що я додам цю інформацію до цієї теми. Ура!


2
Це також гарантує, що ваш код (принаймні здебільшого) все ще працює на машинах, які не володіють англійською мовою.
Ед Норріс

1
Одне невелике вдосконалення тут, FolderItem не містить ExtendedProperty (). FolderItem2, однак, робить.
Mixxiphoid

Ця відповідь є простішою за інших. Я дав приклад коду , який працює тут: stackoverflow.com/a/46648086/661933
Навфал

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);
 }

Я скопіював і використовував той самий код вище. Але тут я отримую виняток COM під час роботи Folder rFolder = shell.NameSpace(_rootPath);. FYI, я використовую ОС Windows 8.
DonMax

1
Що це за помилка? Переконайтеся, що ви використовуєте правильну версію Shell32.dll. Перевірте це, можливо, Корисно
RajeshKdev

1
+1 для вищезазначеного посилання. Посилання, яке ви запропонували, працює нормально. Мені потрібна ще одна допомога від вас. тобто як я можу передати єдиний файл, щоб отримати метадані ?? оскільки він приймає передачу лише папки.
DonMax

6
  • Переглянувши ряд рішень на цій темі та інших місцях, наступний код був зібраний разом. Це лише для читання властивості.
  • Я не міг змусити функцію Shell32.FolderItem2.ExtendedProperty працювати, він повинен приймати значення рядка та повертати правильне значення та тип для цього властивості ... для мене це завжди було нульовим, і довідкові ресурси розробника були дуже тонкими.
  • WindowsApiCodePack , схоже, відмовилися від Microsoft , яка приносить нам код нижче.

Використання:

string propertyValue = GetExtendedFileProperty("c:\\temp\\FileNameYouWant.ext","PropertyYouWant");
  1. Поверне вам значення розширеного властивості, яке ви хочете як рядок для заданого імені файла та власності.
  2. Тільки циклів, поки він не знайде вказане властивість - не до тих пір, поки всі властивості не будуть виявлені як деякий зразок коду
  3. Працюватимуть у версіях Windows, таких як Windows Server 2008, де ви отримаєте помилку "Неможливо передати COM-об'єкт типу" Система .__ ComObject "до інтерфейсу типу" Shell32.Shell "", якщо просто намагатиметься створити об'єкт Shell32 нормально.

    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 () , ви можете shellпередати будь-який з IShellDispatchінтерфейсів (1-6) та подзвонити учаснику безпосередньо. Shell32.IShellDispatch ishell = (Shell32.IShellDispatch)shell; Shell32.Folder shellFolder = ishell.NameSpace(baseFolder);
skst

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

Я не впевнений, для яких типів файлів ви намагаєтеся записати властивості, але чіткі таліби - це відмінна бібліотека тегів з відкритим кодом, яка добре завершує всю цю функціональність. Він має вбудовану підтримку більшості популярних типів мультимедійних файлів, але також дозволяє робити більш розширені теги з майже будь-яким файлом.

Редагувати: Я оновив посилання на гострий таліб. Стара посилання більше не працювала.

EDIT: Ще раз оновіть посилання на коментар kzu.


Це виглядає дуже цікаво, я головним чином переглядаю відеофайли (AVI, DIVX тощо). Дякую за вказівник
Девід Хейс

Посилання на гострі таліби, здається, мертве :-( - що дивно, як вікі на ... developer.novell.com/wiki/index.php/TagLib_Sharp:_Examples ... вказує на цю URL-адресу
SteveC

Дякую, SteveC, на той момент, коли я розмістив це, обидва посилання були дійсними, і я не був впевнений, що це офіційне місце для поїздки, схоже, що Novell - це правильний сайт для відвідування цієї ліб-програми зараз.
mockobject

Дякую за голову до kzu, я оновив посилання в моїй оригінальній відповіді, щоб вказати також на розташування github.
mockobject

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 ви обов'язково повинні використовувати бібліотеку Windows.Storage, яка містить SystemPhotoProperties, SystemMusicProperties тощо. Https://docs.microsoft.com/en-us/windows/uwp/files/quickstart-getting-file-properties

І нарешті, я опублікував набагато краще рішення, яке використовує там WindowsAPICodePack

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.