gpt4 book ai didi

c# - 提取 Windows 文件属性(自定义属性)C#

转载 作者:IT王子 更新时间:2023-10-29 04:49:41 43 4
gpt4 key购买 nike

在 Word/Excel 中,您必须添加自定义属性。 (见图片) Custom Properties .正如你们所看到的,有一个字段:“Properties:”,您可以在那里添加任何您想要的信息。当您保存文件并转到文件夹中的文件位置时,您可以右键单击 -> 属性,您将拥有所有选项卡:常规/安全/详细信息/以前的版本。使用您添加选项卡自定义的功能。

现在我想通过编码得到这个信息:Custom Properties information .稍后将其提取到记事本。到目前为止,我使用的是 Shell32,但后来我只获得了“详细信息”选项卡中的信息。我做了一些研究,发现了 DSOfile.dll 的一些可能性。但我想知道是否有可能在不安装其他 DLL 的情况下执行此操作?到目前为止,这是我使用 Shell32 编写的代码。

        static void Main(string[] args)
{

//using (StreamWriter writer = new StreamWriter(@"filepathhere"))
//{
//Console.SetOut(writer);
ReadProperties();
//}
}
static void ReadProperties()
{
List<string> arrHeaders = new List<string>();
Shell shell = new Shell();
Folder objFolder = shell.NameSpace(@"filepathhere");
FolderItem objFolderItem = objFolder.ParseName("filehere.doc");

for (int i = 0; i < short.MaxValue; i++)
{
string header = objFolder.GetDetailsOf(objFolder, i);
if (String.IsNullOrEmpty(header))
break;
arrHeaders.Add(header);
}

for ( int i = 0; i < arrHeaders.Count; i++)
{
Console.WriteLine("{0}\t{1}: {2}", i, arrHeaders[i], objFolder.GetDetailsOf(objFolderItem, i));
}
Console.ReadKey();
}

提前致谢!

德苏

最佳答案

从历史上看,这些属性是由称为“结构化存储”的技术定义的。第一个结构化存储实现是古老的(但仍然非常活跃)Compound File Format

之后,微软增加了结构化存储能力directly into NTFS .这允许您在任何文件(甚至 .txt)文件上定义作者或标题等属性。尽管出于某种原因 Explorer UI 不再允许您执行此操作,但我认为它仍然可以通过编程方式工作。

然后,在 Vista 中,Microsoft 重新启动了所有这些并引入了所有这些的超集:Windows Property System .

不幸的是,框架中没有用于所有这些的 .NET API。但微软创建了一个名为 Windows API CodePack 的开源 .NET 库。因此,提取属性的最简单方法是添加对 WindowsAPICodePack Core NugetPackage 的引用,您可以像这样使用它:

static void Main(string[] args)
{
foreach (var prop in new ShellPropertyCollection(@"mypath\myfile"))
{
Console.WriteLine(prop.CanonicalName + "=" + prop.ValueAsObject);
}
}

如果您不想添加额外的 DLL,则可以从 WindowsAPICodePack 源 (Windows API Code Pack: Where is it?) 中提取 ShellPropertyCollection 代码。这是一项艰巨的工作,但也是可行的。

针对您的情况,另一种解决方案是使用旧的 Structure Storage native API。我提供了一个执行此操作的示例。以下是您可以如何使用它:

static void Main(string[] args)
{
foreach (var prop in new StructuredStorage(@"mypath\myfile").Properties)
{
Console.WriteLine(prop.Name + "=" + prop.Value);
}
}

public sealed class StructuredStorage
{
public static readonly Guid SummaryInformationFormatId = new Guid("{F29F85E0-4FF9-1068-AB91-08002B27B3D9}");
public static readonly Guid DocSummaryInformationFormatId = new Guid("{D5CDD502-2E9C-101B-9397-08002B2CF9AE}");
public static readonly Guid UserDefinedPropertiesId = new Guid("{D5CDD505-2E9C-101B-9397-08002B2CF9AE}");

private List<StructuredProperty> _properties = new List<StructuredProperty>();

public StructuredStorage(string filePath)
{
if (filePath == null)
throw new ArgumentNullException("filePath");

FilePath = filePath;
IPropertySetStorage propertySetStorage;
int hr = StgOpenStorageEx(FilePath, STGM.STGM_READ | STGM.STGM_SHARE_DENY_NONE | STGM.STGM_DIRECT_SWMR, STGFMT.STGFMT_ANY, 0, IntPtr.Zero, IntPtr.Zero, typeof(IPropertySetStorage).GUID, out propertySetStorage);
if (hr == STG_E_FILENOTFOUND || hr == STG_E_PATHNOTFOUND)
throw new FileNotFoundException(null, FilePath);

if (hr != 0)
throw new Win32Exception(hr);

try
{
LoadPropertySet(propertySetStorage, SummaryInformationFormatId);
LoadPropertySet(propertySetStorage, DocSummaryInformationFormatId);
}
finally
{
Marshal.ReleaseComObject(propertySetStorage);
}

// for some reason we can't read this one on the same COM ref?
LoadProperties(UserDefinedPropertiesId);
}

public string FilePath { get; private set; }
public IReadOnlyList<StructuredProperty> Properties
{
get
{
return _properties;
}
}

private void LoadPropertySet(IPropertySetStorage propertySetStorage, Guid fmtid)
{
IPropertyStorage propertyStorage;
int hr = propertySetStorage.Open(fmtid, STGM.STGM_READ | STGM.STGM_SHARE_EXCLUSIVE, out propertyStorage);
if (hr == STG_E_FILENOTFOUND || hr == STG_E_ACCESSDENIED)
return;

if (hr != 0)
throw new Win32Exception(hr);

IEnumSTATPROPSTG es;
propertyStorage.Enum(out es);
if (es == null)
return;

try
{
var stg = new STATPROPSTG();
int fetched;
do
{
hr = es.Next(1, ref stg, out fetched);
if (hr != 0 && hr != 1)
throw new Win32Exception(hr);

if (fetched == 1)
{
string name = GetPropertyName(fmtid, propertyStorage, stg);

var propsec = new PROPSPEC[1];
propsec[0] = new PROPSPEC();
propsec[0].ulKind = stg.lpwstrName != null ? PRSPEC.PRSPEC_LPWSTR : PRSPEC.PRSPEC_PROPID;
IntPtr lpwstr = IntPtr.Zero;
if (stg.lpwstrName != null)
{
lpwstr = Marshal.StringToCoTaskMemUni(stg.lpwstrName);
propsec[0].union.lpwstr = lpwstr;
}
else
{
propsec[0].union.propid = stg.propid;
}

var vars = new PROPVARIANT[1];
vars[0] = new PROPVARIANT();
try
{
hr = propertyStorage.ReadMultiple(1, propsec, vars);
if (hr != 0)
throw new Win32Exception(hr);

}
finally
{
if (lpwstr != IntPtr.Zero)
{
Marshal.FreeCoTaskMem(lpwstr);
}
}

object value;
try
{
switch (vars[0].vt)
{
case VARTYPE.VT_BOOL:
value = vars[0].union.boolVal != 0 ? true : false;
break;

case VARTYPE.VT_BSTR:
value = Marshal.PtrToStringUni(vars[0].union.bstrVal);
break;

case VARTYPE.VT_CY:
value = decimal.FromOACurrency(vars[0].union.cyVal);
break;

case VARTYPE.VT_DATE:
value = DateTime.FromOADate(vars[0].union.date);
break;

case VARTYPE.VT_DECIMAL:
IntPtr dec = IntPtr.Zero;
Marshal.StructureToPtr(vars[0], dec, false);
value = Marshal.PtrToStructure(dec, typeof(decimal));
break;

case VARTYPE.VT_DISPATCH:
value = Marshal.GetObjectForIUnknown(vars[0].union.pdispVal);
break;

case VARTYPE.VT_ERROR:
case VARTYPE.VT_HRESULT:
value = vars[0].union.scode;
break;

case VARTYPE.VT_FILETIME:
value = DateTime.FromFileTime(vars[0].union.filetime);
break;

case VARTYPE.VT_I1:
value = vars[0].union.cVal;
break;

case VARTYPE.VT_I2:
value = vars[0].union.iVal;
break;

case VARTYPE.VT_I4:
value = vars[0].union.lVal;
break;

case VARTYPE.VT_I8:
value = vars[0].union.hVal;
break;

case VARTYPE.VT_INT:
value = vars[0].union.intVal;
break;

case VARTYPE.VT_LPSTR:
value = Marshal.PtrToStringAnsi(vars[0].union.pszVal);
break;

case VARTYPE.VT_LPWSTR:
value = Marshal.PtrToStringUni(vars[0].union.pwszVal);
break;

case VARTYPE.VT_R4:
value = vars[0].union.fltVal;
break;

case VARTYPE.VT_R8:
value = vars[0].union.dblVal;
break;

case VARTYPE.VT_UI1:
value = vars[0].union.bVal;
break;

case VARTYPE.VT_UI2:
value = vars[0].union.uiVal;
break;

case VARTYPE.VT_UI4:
value = vars[0].union.ulVal;
break;

case VARTYPE.VT_UI8:
value = vars[0].union.uhVal;
break;

case VARTYPE.VT_UINT:
value = vars[0].union.uintVal;
break;

case VARTYPE.VT_UNKNOWN:
value = Marshal.GetObjectForIUnknown(vars[0].union.punkVal);
break;

default:
value = null;
break;
}
}
finally
{
PropVariantClear(ref vars[0]);
}

var property = new StructuredProperty(fmtid, name, stg.propid);
property.Value = value;
_properties.Add(property);
}
}
while (fetched == 1);
}
finally
{
Marshal.ReleaseComObject(es);
}
}

private static string GetPropertyName(Guid fmtid, IPropertyStorage propertyStorage, STATPROPSTG stg)
{
if (!string.IsNullOrEmpty(stg.lpwstrName))
return stg.lpwstrName;

var propids = new int[1];
propids[0] = stg.propid;
var names = new string[1];
names[0] = null;
int hr = propertyStorage.ReadPropertyNames(1, propids, names);
if (hr == 0)
return names[0];

return null;
}

public void LoadProperties(Guid formatId)
{
IPropertySetStorage propertySetStorage;
int hr = StgOpenStorageEx(FilePath, STGM.STGM_READ | STGM.STGM_SHARE_DENY_NONE | STGM.STGM_DIRECT_SWMR, STGFMT.STGFMT_ANY, 0, IntPtr.Zero, IntPtr.Zero, typeof(IPropertySetStorage).GUID, out propertySetStorage);
if (hr == STG_E_FILENOTFOUND || hr == STG_E_PATHNOTFOUND)
throw new FileNotFoundException(null, FilePath);

if (hr != 0)
throw new Win32Exception(hr);

try
{
LoadPropertySet(propertySetStorage, formatId);
}
finally
{
Marshal.ReleaseComObject(propertySetStorage);
}
}

private const int STG_E_FILENOTFOUND = unchecked((int)0x80030002);
private const int STG_E_PATHNOTFOUND = unchecked((int)0x80030003);
private const int STG_E_ACCESSDENIED = unchecked((int)0x80030005);

private enum PRSPEC
{
PRSPEC_LPWSTR = 0,
PRSPEC_PROPID = 1
}

private enum STGFMT
{
STGFMT_ANY = 4,
}

[Flags]
private enum STGM
{
STGM_READ = 0x00000000,
STGM_READWRITE = 0x00000002,
STGM_SHARE_DENY_NONE = 0x00000040,
STGM_SHARE_DENY_WRITE = 0x00000020,
STGM_SHARE_EXCLUSIVE = 0x00000010,
STGM_DIRECT_SWMR = 0x00400000
}

// we only define what we handle
private enum VARTYPE : short
{
VT_I2 = 2,
VT_I4 = 3,
VT_R4 = 4,
VT_R8 = 5,
VT_CY = 6,
VT_DATE = 7,
VT_BSTR = 8,
VT_DISPATCH = 9,
VT_ERROR = 10,
VT_BOOL = 11,
VT_UNKNOWN = 13,
VT_DECIMAL = 14,
VT_I1 = 16,
VT_UI1 = 17,
VT_UI2 = 18,
VT_UI4 = 19,
VT_I8 = 20,
VT_UI8 = 21,
VT_INT = 22,
VT_UINT = 23,
VT_HRESULT = 25,
VT_LPSTR = 30,
VT_LPWSTR = 31,
VT_FILETIME = 64,
}

[StructLayout(LayoutKind.Explicit)]
private struct PROPVARIANTunion
{
[FieldOffset(0)]
public sbyte cVal;
[FieldOffset(0)]
public byte bVal;
[FieldOffset(0)]
public short iVal;
[FieldOffset(0)]
public ushort uiVal;
[FieldOffset(0)]
public int lVal;
[FieldOffset(0)]
public uint ulVal;
[FieldOffset(0)]
public int intVal;
[FieldOffset(0)]
public uint uintVal;
[FieldOffset(0)]
public long hVal;
[FieldOffset(0)]
public ulong uhVal;
[FieldOffset(0)]
public float fltVal;
[FieldOffset(0)]
public double dblVal;
[FieldOffset(0)]
public short boolVal;
[FieldOffset(0)]
public int scode;
[FieldOffset(0)]
public long cyVal;
[FieldOffset(0)]
public double date;
[FieldOffset(0)]
public long filetime;
[FieldOffset(0)]
public IntPtr bstrVal;
[FieldOffset(0)]
public IntPtr pszVal;
[FieldOffset(0)]
public IntPtr pwszVal;
[FieldOffset(0)]
public IntPtr punkVal;
[FieldOffset(0)]
public IntPtr pdispVal;
}

[StructLayout(LayoutKind.Sequential)]
private struct PROPSPEC
{
public PRSPEC ulKind;
public PROPSPECunion union;
}

[StructLayout(LayoutKind.Explicit)]
private struct PROPSPECunion
{
[FieldOffset(0)]
public int propid;
[FieldOffset(0)]
public IntPtr lpwstr;
}

[StructLayout(LayoutKind.Sequential)]
private struct PROPVARIANT
{
public VARTYPE vt;
public ushort wReserved1;
public ushort wReserved2;
public ushort wReserved3;
public PROPVARIANTunion union;
}

[StructLayout(LayoutKind.Sequential)]
private struct STATPROPSTG
{
[MarshalAs(UnmanagedType.LPWStr)]
public string lpwstrName;
public int propid;
public VARTYPE vt;
}

[StructLayout(LayoutKind.Sequential)]
private struct STATPROPSETSTG
{
public Guid fmtid;
public Guid clsid;
public uint grfFlags;
public System.Runtime.InteropServices.ComTypes.FILETIME mtime;
public System.Runtime.InteropServices.ComTypes.FILETIME ctime;
public System.Runtime.InteropServices.ComTypes.FILETIME atime;
public uint dwOSVersion;
}

[DllImport("ole32.dll")]
private static extern int StgOpenStorageEx([MarshalAs(UnmanagedType.LPWStr)] string pwcsName, STGM grfMode, STGFMT stgfmt, int grfAttrs, IntPtr pStgOptions, IntPtr reserved2, [MarshalAs(UnmanagedType.LPStruct)] Guid riid, out IPropertySetStorage ppObjectOpen);

[DllImport("ole32.dll")]
private static extern int PropVariantClear(ref PROPVARIANT pvar);

[Guid("0000013B-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface IEnumSTATPROPSETSTG
{
[PreserveSig]
int Next(int celt, ref STATPROPSETSTG rgelt, out int pceltFetched);
// rest ommited
}

[Guid("00000139-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface IEnumSTATPROPSTG
{
[PreserveSig]
int Next(int celt, ref STATPROPSTG rgelt, out int pceltFetched);
// rest ommited
}

[Guid("00000138-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface IPropertyStorage
{
[PreserveSig]
int ReadMultiple(uint cpspec, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] PROPSPEC[] rgpspec, [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] PROPVARIANT[] rgpropvar);
[PreserveSig]
int WriteMultiple(uint cpspec, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] PROPSPEC[] rgpspec, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] PROPVARIANT[] rgpropvar, uint propidNameFirst);
[PreserveSig]
int DeleteMultiple(uint cpspec, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] PROPSPEC[] rgpspec);
[PreserveSig]
int ReadPropertyNames(uint cpropid, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] int[] rgpropid, [Out, MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 0)] string[] rglpwstrName);
[PreserveSig]
int NotDeclared1();
[PreserveSig]
int NotDeclared2();
[PreserveSig]
int Commit(uint grfCommitFlags);
[PreserveSig]
int NotDeclared3();
[PreserveSig]
int Enum(out IEnumSTATPROPSTG ppenum);
// rest ommited
}

[Guid("0000013A-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface IPropertySetStorage
{
[PreserveSig]
int Create([MarshalAs(UnmanagedType.LPStruct)] Guid rfmtid, [MarshalAs(UnmanagedType.LPStruct)] Guid pclsid, uint grfFlags, STGM grfMode, out IPropertyStorage ppprstg);
[PreserveSig]
int Open([MarshalAs(UnmanagedType.LPStruct)] Guid rfmtid, STGM grfMode, out IPropertyStorage ppprstg);
[PreserveSig]
int NotDeclared3();
[PreserveSig]
int Enum(out IEnumSTATPROPSETSTG ppenum);
}
}

public sealed class StructuredProperty
{
public StructuredProperty(Guid formatId, string name, int id)
{
FormatId = formatId;
Name = name;
Id = id;
}

public Guid FormatId { get; private set; }
public string Name { get; private set; }
public int Id { get; private set; }
public object Value { get; set; }

public override string ToString()
{
return Name;
}
}

关于c# - 提取 Windows 文件属性(自定义属性)C#,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35451540/

43 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com