我正在尝试找出如何在C#中读写扩展文件属性,例如在Windows资源管理器中可以看到的注释、比特率、访问日期和类别等信息。你有什么想法吗? 编辑:我主要会读写视频文件(AVI/DIVX/...)
我正在尝试找出如何在C#中读写扩展文件属性,例如在Windows资源管理器中可以看到的注释、比特率、访问日期和类别等信息。你有什么想法吗? 编辑:我主要会读写视频文件(AVI/DIVX/...)
对于那些不喜欢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)}");
}
}
}
将以下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();
重要提示:
文件必须是由特定的指定软件创建的有效文件。每种文件类型都有特定的扩展文件属性,并非所有属性都可写。
如果您在桌面上右键单击文件并且无法编辑属性,则您也无法在代码中进行编辑。
示例:
作者
或 标题
属性。因此,请确保使用一些 try
catch
。
更多主题: Microsoft Docs:实现属性处理程序
有一篇CodeProject文章介绍了ID3读取器。还有一个kixtart.org的主题,提供其他属性的更多信息。基本上,您需要在shell32.dll
上的文件夹 shell对象上调用GetDetailsOf()
方法。
这是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的引用。
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操作系统。 - DonMax用途:
string propertyValue = GetExtendedFileProperty("c:\\temp\\FileNameYouWant.ext","PropertyYouWant");
Will work on Windows versions like Windows server 2008 where you will get the error "Unable to cast COM object of type 'System.__ComObject' to interface type 'Shell32.Shell'" if just trying to create the Shell32 Object normally.
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),然后直接调用成员,而无需使用_InvokeMember()_
。 Shell32.IShellDispatch ishell = (Shell32.IShellDispatch)shell; Shell32.Folder shellFolder = ishell.NameSpace(baseFolder);
- skstJerker的答案更简单。这是一个可以工作的示例代码,来自微软:
var folder = new Shell().NameSpace(folderPath);
foreach (FolderItem2 item in folder.Items())
{
var company = item.ExtendedProperty("Company");
var author = item.ExtendedProperty("Author");
// Etc.
}
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.
}
var i = 0;
while (true)
{
...
if (String.IsNullOrEmpty(header)) break;
...
i++;
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;
}
我不确定您要为哪些类型的文件编写属性,但taglib-sharp是一个出色的开源标记库,可以很好地封装所有这些功能。它具有对大多数流行媒体文件类型的内置支持,但也允许您使用几乎任何文件进行更高级的标记。
编辑:我已更新taglib sharp的链接。旧链接已不再有效。
编辑:根据kzu的评论,再次更新了链接。