WedX - журнал о программировании и компьютерных науках

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

Я пытаюсь узнать, как читать / писать в расширенные свойства файла в C #, например. Комментарий, скорость передачи данных, дата доступа, категория и т. Д., Которые вы можете увидеть в проводнике Windows. Есть идеи, как это сделать? РЕДАКТИРОВАТЬ: в основном я буду читать / писать в видео файлы (AVI / DIVX / ...)

20.10.2008

  • На этот вопрос явно нет ответа, поскольку принятый ответ показывает только, как получить расширенные свойства, а не как их установить. 05.12.2013
  • Для настройки расширенных свойств см. stackoverflow.com/ вопросы / 5337683 / 14.08.2014

Ответы:


1

Для тех, кто не без ума от VB, вот он на C #:

Обратите внимание: вам необходимо добавить ссылку на Microsoft Shell Controls and Automation на вкладке COM диалогового окна References.

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)}");
        }
    }
}
19.01.2010
  • как установить одно из этих значений? например, для Автор или издатель файла .txt. Я нахожусь в выигрыше 7 и использовал это, и он показывает пустые имена автора и издателя и 282 других свойства 07.04.2010
  • @Vainbhav - Вы не можете их установить. 14.04.2010
  • Вы должны добавить ссылку на Microsoft Shell Controls and Automation на вкладке COM диалогового окна Refences. 19.04.2011
  • Имейте в виду, что это решение не работает в Windows XP. При доступе к Shell32 из XP вы получаете исключение COM. 15.10.2012
  • Я использовал это в XP, какое исключение COM вы видите? 15.10.2012
  • О том, как их УСТАНОВИТЬ, лучше рассказать в этом вопросе: stackoverflow.com/questions/5337683/ 01.11.2012
  • @ csharptest.net Я получаю NullReferenceException на линии с string header = objFolder.GetDetailsOf(null, i); 02.01.2013
  • Это лучше, чем код VB, поскольку количество заголовков обычно больше. Я получил больше результатов с этой логикой, чем с жестко запрограммированными 35 21.01.2013
  • Я скопировал и использовал тот же код, что и выше. Но я получаю исключение COM в runime здесь objFolder = shell.NameSpace(@"C:\temp\testprop");. К вашему сведению, я использую ОС Windows 8. 30.10.2014
  • Это хорошо, но как насчет записи свойств файла, как это указано в заголовке вопроса? 16.07.2016
  • @ M.Mahdipour это невозможно для некоторых, поскольку они определяются форматом файла. 16.07.2016
  • Есть ли способ сделать это без COM? Как насчет создания нового пустого файла со свойствами? 17.01.2017
  • В Windows 10 он возвращает только 52 поля, не включая частоту кадров, высоту кадра, ширину и т. Д.? 26.06.2017
  • Как упомянул предыдущий пользователь, это не возвращает свойства видео. Есть ли альтернатива? 05.01.2018
  • Причина, по которой это не возвращает все свойства, заключается в том, что цикл выходит из цикла, если возвращаемый заголовок пуст. if (String.IsNullOrEmpty(header)) break; Поскольку некоторые заголовки являются пустыми, вам необходимо удалить их и просмотреть все возможные индексы. (Конечно, поскольку не может быть такого множества свойств, вы можете разумно ограничить цикл до 1000 вместо short.MaxValue.) 17.11.2018
  • Какой пакет или библиотеку мне нужно установить, чтобы получить доступ к Shell? 20.06.2019
  • как это будет работать с недавно выпущенным .NET5.0? Можно ли использовать PInvoke или так? C # / WinRT - не лучший вариант: github.com/microsoft/CsWinRT/issues/591 < / а> 20.11.2020

  • 2

    Решение 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

    Дополнительная тема: Документы Microsoft: реализация обработчиков свойств

    23.06.2016
  • Я не вижу пакетов с этими именами от Microsoft 04.12.2018
  • @JacobBrewer На самом деле это тот, который был загружен acdvorak: nuget.org/packages/ Microsoft.WindowsAPICodePack-Shell. В Visual Studio NuGet-Package-Manager он отображается как Microsoft. Другие пакеты с похожими именами являются его ответвлениями и также могут работать должным образом или даже лучше. Я не знаю... 04.12.2018

  • 3

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

    20.10.2008
  • Спасибо, я смогу извлечь из этого 21.10.2008

  • 4

    Этот пример в 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 and Automation на вкладке COM диалогового окна Ссылки.

    28.11.2008
  • Стоит отметить, что в Windows 7 (по крайней мере) вы можете увеличить размер arrHeaders до чуть более 280 и получить обратно много дополнительных метаданных. Я обнаружил это, когда искал способ получить метаданные из файла WTV (телешоу, записанное в Windows 7 Media Center). 28.10.2010
  • Первый цикл для i = от 0 до 34 должен быть от i = 0 до Integer.MaxValue. Затем проверьте возвращаемое значение objFolder.GetDetailsOf (objFolder.Items, i). Если он возвращает ноль или пробел, то у вас есть все заголовки. 22.02.2011
  • @TimMurphy, к сожалению, это неправильно (по крайней мере, в Windows 10 или 7). Некоторые заголовки пусты, поэтому вам нужно перебрать все индексы. (Конечно, поскольку их не миллионы, вы можете ограничить цикл до 1000.) 17.11.2018

  • 5

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

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

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

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

    23.08.2010
  • Это также гарантирует, что ваш код (по крайней мере, в большинстве случаев) по-прежнему будет работать на машинах, не владеющих английским языком. 09.02.2012
  • Одно небольшое улучшение: FolderItem не содержит ExtendedProperty (). Однако FolderItem2 делает. 31.08.2014
  • Этот ответ немного проще других. Я привел пример кода, который работает здесь: stackoverflow.com/a/46648086/661933 09.10.2017

  • 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);
     }
    
    27.02.2013
  • Я скопировал и использовал тот же код, что и выше. Но я получаю исключение COM в runime здесь Folder rFolder = shell.NameSpace(_rootPath);. К вашему сведению, я использую ОС Windows 8. 30.10.2014
  • Что это за ошибка? Убедитесь, что вы используете правильную версию Shell32.dll. Проверьте это, возможно, это полезно 30.10.2014
  • +1 за ссылку выше. Ссылка, которую вы предложили, работает нормально. Мне нужна еще одна твоя помощь. т.е. как передать один файл для получения метаданных? поскольку он принимает передачу только папки. 30.10.2014

  • 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.
    }
    
    09.10.2017

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

    Использовать:

    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;
      }
      
    23.04.2018
  • Обратите внимание, что вместо использования InvokeMember () вы можете привести shell к любому из IShellDispatch интерфейсов (1-6) и напрямую вызвать член. Shell32.IShellDispatch ishell = (Shell32.IShellDispatch)shell; Shell32.Folder shellFolder = ishell.NameSpace(baseFolder); 18.11.2018

  • 9

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

    РЕДАКТИРОВАТЬ: Я обновил ссылку на taglib sharp. Старая ссылка больше не работала.

    РЕДАКТИРОВАТЬ: Ссылка была обновлена ​​еще раз для каждого комментария kzu.

    20.10.2008
  • Это выглядит очень интересно, в основном я буду смотреть видеофайлы (AVI, DIVX и т. Д.). Спасибо за указатель 21.10.2008
  • Ссылка taglib-sharp кажется мертвой :-( - что странно, как вики по адресу ... developer.novell.com/wiki/index.php/TagLib_Sharp:_Examples ... указывает на этот URL 28.07.2009
  • Спасибо, SteveC, в то время, когда я разместил эту ссылку, обе ссылки были действительны, и я не был уверен, что было официальным местом, куда можно было перейти, похоже, novell - это тот сайт, на который сейчас стоит перейти для этой библиотеки. 28.07.2009
  • Спасибо за внимание, kzu, я обновил ссылку в моем исходном ответе, чтобы она также указывала на местоположение github. 03.01.2012

  • 10

    Вот решение для чтения - не записи - расширенных свойств на основе того, что я нашел на этой странице и на справка по объектам 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 там

    10.08.2019
    Новые материалы

    Как создать диаграмму градиентной кисти с помощью D3.js
    Резюме: Из этого туториала Вы узнаете, как добавить градиентную кисть к диаграмме с областями в D3.js. Мы добавим градиент к значениям SVG и применим градиент в качестве заливки к диаграмме с..

    Я хотел выучить язык программирования MVC4, но не мог выучить его раньше, потому что это выглядит сложно…
    Просто начните и учитесь самостоятельно Я хотел выучить язык программирования MVC4, но не мог выучить его раньше, потому что он кажется мне сложным, и я бросил его. Это в основном инструмент..

    Лицензии с открытым исходным кодом: руководство для разработчиков и создателей
    В динамичном мире разработки программного обеспечения открытый исходный код стал мощной парадигмой, способствующей сотрудничеству, инновациям и прогрессу, движимому сообществом. В основе..

    Объяснение документов 02: BERT
    BERT представил двухступенчатую структуру обучения: предварительное обучение и тонкая настройка. Во время предварительного обучения модель обучается на неразмеченных данных с помощью..

    Как проанализировать работу вашего классификатора?
    Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

    Работа с цепями Маркова, часть 4 (Машинное обучение)
    Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

    Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
    Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..


    Для любых предложений по сайту: [email protected]