Чтение/запись "Расширенные" свойства файла (С#)

Я пытаюсь выяснить, как читать/записывать расширенные свойства файла в С# например Комментарий, скорость передачи битов, доступ к дате, категорию и т.д., Которые вы можете увидеть в проводнике Windows. Есть идеи, как это сделать? EDIT: в основном я буду читать/записывать видеофайлы (AVI/DIVX/...)

Ответ 1

Для тех, кто не сумасшедший относительно VB, здесь он находится в С#:

Обратите внимание, что вы должны добавить ссылку на Microsoft Shell Controls и Automation со вкладки 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)}");
        }
    }
}

Ответ 2

Здесь статья CodeProject для чтения ID3. И поток на kixtart.org, который имеет больше информации для других свойств. В принципе, вам нужно вызвать метод GetDetailsOf() в объекте оболочки папки для shell32.dll.

Ответ 3

Этот образец в 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 Controls и Automation со вкладки COM диалогового окна "Ссылки".

Ответ 4

Решение 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: реализация обработчиков свойств

Ответ 5

Спасибо, ребята, за эту тему! Это помогло мне, когда я хотел выяснить версию exe файла. Тем не менее, мне нужно было выяснить последний бит о том, что называется Extended Properties.

Если вы открываете свойства файла exe (или dll) в проводнике Windows, вы получаете вкладку "Версия" и представление "Расширенные свойства этого файла". Я хотел получить доступ к одному из этих значений.

Решением этого является индекс индексатора свойств FolderItem.ExtendedProperty, и если вы отбросите все пробелы в имени свойства, вы получите значение. Например. Версия файла идет FileVersion, и там у вас есть.

Надеюсь, это поможет кому-то еще, просто подумал, что я бы добавил эту информацию в эту тему. Ура!

Ответ 6

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

Ответ 7

Ответ Джеркера немного проще. Здесь пример кода, который работает из 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.
}

Ответ 8

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

Использование:

string propertyValue = GetExtendedFileProperty("c:\\temp\\FileNameYouWant.ext","PropertyYouWant");
  1. Вернет вам значение расширенного свойства, которое вы хотите в качестве строки для данного файла и имени свойства.
  2. Только циклы, пока не найдут указанное свойство - пока все свойства не будут обнаружены, как некоторый пример кода
  3. Будет работать в версиях Windows, таких как Windows Server 2008, где вы получите сообщение об ошибке "Невозможно передать COM-объект типа" System.__ 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;
    }
    

Ответ 9

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

EDIT: Я обновил ссылку на taglib sharp. Старая ссылка больше не работала.

EDIT: Обновлена ​​ссылка еще раз за комментарий кзу.