Я пытаюсь узнать, как читать / писать в расширенные свойства файла в C #, например. Комментарий, скорость передачи данных, дата доступа, категория и т. Д., Которые вы можете увидеть в проводнике Windows. Есть идеи, как это сделать? РЕДАКТИРОВАТЬ: в основном я буду читать / писать в видео файлы (AVI / DIVX / ...)
Чтение / запись расширенных свойств файла (C #)
- На этот вопрос явно нет ответа, поскольку принятый ответ показывает только, как получить расширенные свойства, а не как их установить. 05.12.2013
- Для настройки расширенных свойств см. stackoverflow.com/ вопросы / 5337683 / 14.08.2014
Ответы:
Для тех, кто не без ума от 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)}");
}
}
}
Решение 2016
Добавьте в проект следующие пакеты NuGet:
Microsoft.WindowsAPICodePack-Shell
от MicrosoftMicrosoft.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: реализация обработчиков свойств
Для читателя ID3 есть статья CodeProject. И ветка на kixtart.org с дополнительной информацией для других свойств. Обычно вам нужно вызвать GetDetailsOf()
метод на объект оболочки folder для shell32.dll
.
Этот пример в 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 диалогового окна Ссылки.
Спасибо, ребята, за эту ветку! Это помогло мне, когда я хотел выяснить версию файла exe. Однако мне нужно было самому разобраться в том, что называется расширенными свойствами.
Если вы откроете свойства файла exe (или dll) в проводнике Windows, вы увидите вкладку «Версия» и представление дополнительных свойств этого файла. Я хотел получить доступ к одной из этих ценностей.
Решением этой проблемы является индексатор свойств FolderItem.ExtendedProperty, и если вы удалите все пробелы в имени свойства, вы получите значение. Например. Версия файла - это FileVersion, и вот она.
Надеюсь, это поможет кому-то еще, просто подумал, что добавлю эту информацию в эту ветку. Ваше здоровье!
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);
}
Folder rFolder = shell.NameSpace(_rootPath);
. К вашему сведению, я использую ОС Windows 8. 30.10.2014 Ответ Джеркера немного проще. Вот пример кода, который работает из 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.
}
- После просмотра ряда решений в этом потоке и в других местах был составлен следующий код. Это только для чтения собственности.
- Мне не удалось заставить работать функцию Shell32.FolderItem2.ExtendedProperty, она должна принимать строковое значение и возвращать правильное значение и тип для этого свойства ... это всегда было пустым для меня, а справочные ресурсы разработчика были очень тонкими.
- Microsoft, похоже, отказалась от WindowsApiCodePack, что принесло нам код ниже.
Использовать:
string propertyValue = GetExtendedFileProperty("c:\\temp\\FileNameYouWant.ext","PropertyYouWant");
- Вернет вам значение расширенного свойства, которое вы хотите, в виде строки для данного файла и имени свойства.
- Выполняет цикл только до тех пор, пока не будет найдено указанное свойство - не до тех пор, пока не будут обнаружены все свойства, как некоторый пример кода.
Будет работать в версиях 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; }
shell
к любому из IShellDispatch
интерфейсов (1-6) и напрямую вызвать член. Shell32.IShellDispatch ishell = (Shell32.IShellDispatch)shell; Shell32.Folder shellFolder = ishell.NameSpace(baseFolder);
18.11.2018 Я не уверен, для каких типов файлов вы пытаетесь записать свойства, но taglib-sharp - отличная библиотека тегов с открытым исходным кодом, которая прекрасно дополняет всю эту функциональность. Он имеет много встроенной поддержки для большинства популярных типов файлов мультимедиа, но также позволяет выполнять более сложные теги практически для любого файла.
РЕДАКТИРОВАТЬ: Я обновил ссылку на taglib sharp. Старая ссылка больше не работала.
РЕДАКТИРОВАТЬ: Ссылка была обновлена еще раз для каждого комментария kzu.
Вот решение для чтения - не записи - расширенных свойств на основе того, что я нашел на этой странице и на справка по объектам 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 там
NullReferenceException
на линии сstring header = objFolder.GetDetailsOf(null, i);
02.01.2013objFolder = shell.NameSpace(@"C:\temp\testprop");
. К вашему сведению, я использую ОС Windows 8. 30.10.2014if (String.IsNullOrEmpty(header)) break;
Поскольку некоторые заголовки являются пустыми, вам необходимо удалить их и просмотреть все возможные индексы. (Конечно, поскольку не может быть такого множества свойств, вы можете разумно ограничить цикл до 1000 вместоshort.MaxValue
.) 17.11.2018