【问题标题】:How can I add NTFS metadata to any file?如何将 NTFS 元数据添加到任何文件?
【发布时间】:2020-09-02 08:40:59
【问题描述】:

是否有可能将诸如“版本 = 1.2.3.4”之类的信息添加到 - 比如说 - TXT 文件?这可以通过 NTFS 元数据实现吗?如果是这样,我可以通过程序设置这些信息吗?

提前感谢您的任何提示!伯恩德

【问题讨论】:

    标签: file attributes metadata meta ntfs


    【解决方案1】:

    您可以使用备用数据流 (ADS) 或扩展文件属性 (more e.g. here)。

    如果您确定您的文件保留在 NTFS 上,替代数据流是存储任意数量替代数据的完美方式 - 但当此类文件离开 NTFS 时,您将丢失 ADS。

    另一个选项是使用扩展文件属性,它支持跨平台、跨 FS,但它有限制(例如,您可以存储多少数据)。如果您要保存,例如版本信息,这可能是最好的方法。

    【讨论】:

      【解决方案2】:

      谢谢罗伯特!我使用了您建议的 NTFS 扩展文件属性。它们被称为“文件摘要信息”。不幸的是,信息没有显示在 Windows 文件资源管理器的“详细信息”选项卡中的文本文件中。我为注册表找到了一些技巧,但它们还没有奏效。我的代码是德尔福:

      CONST FmtID_SummaryInformation:TGUID=   '{F29F85E0-4FF9-1068-AB91-08002B27B3D9}';
      //    FMTID_DocSummaryInformation:TGUID='{D5CDD502-2E9C-101B-9397-08002B2CF9AE}';
      //    FMTID_UserDefinedProperties:TGUID='{D5CDD505-2E9C-101B-9397-08002B2CF9AE}';
            IID_IPropertySetStorage:TGUID=    '{0000013A-0000-0000-C000-000000000046}';
      
            STGFMT_FILE=3; //Indicates that the file must not be a compound file.
                            //This element is only valid when using the StgCreateStorageEx
                            //or StgOpenStorageEx functions to access the NTFS file system
                            //implementation of the IPropertySetStorage interface.
                            //Therefore, these functions return an error if the riid
                            //parameter does not specify the IPropertySetStorage interface,
                            //or if the specified file is not located on an NTFS file system volume.
      
            STGFMT_ANY=4; //Indicates that the system will determine the file type and
                          //use the appropriate structured storage or property set
                          //implementation.
                          //This value cannot be used with the StgCreateStorageEx function.
      
      
            // Summary Information
             PID_TITLE        = 2;
             PID_SUBJECT      = 3;
             PID_AUTHOR       = 4;
             PID_KEYWORDS     = 5;
             PID_COMMENTS     = 6;
             PID_TEMPLATE     = 7;
             PID_LASTAUTHOR   = 8;
             PID_REVNUMBER    = 9;
             PID_EDITTIME     = 10;
             PID_LASTPRINTED  = 11;
             PID_CREATE_DTM   = 12;
             PID_LASTSAVE_DTM = 13;
             PID_PAGECOUNT    = 14;
             PID_WORDCOUNT    = 15;
             PID_CHARCOUNT    = 16;
             PID_THUMBNAIL    = 17;
             PID_APPNAME      = 18;
             PID_SECURITY     = 19;
      (*
             // Document Summary Information
             PID_CATEGORY     = 2;
             PID_PRESFORMAT   = 3;
             PID_BYTECOUNT    = 4;
             PID_LINECOUNT    = 5;
             PID_PARCOUNT     = 6;
             PID_SLIDECOUNT   = 7;
             PID_NOTECOUNT    = 8;
             PID_HIDDENCOUNT  = 9;
             PID_MMCLIPCOUNT  = 10;
             PID_SCALE        = 11;
             PID_HEADINGPAIR  = 12;
             PID_DOCPARTS     = 13;
             PID_MANAGER      = 14;
             PID_COMPANY      = 15;
             PID_LINKSDIRTY   = 16;
             PID_CHARCOUNT2   = 17;
      *)
      FUNCTION IsNTFS(AFileName:AnsiString):Boolean;
      VAR fso,drv:OleVariant;
      BEGIN
        fso:=CreateOleObject('Scripting.FileSystemObject'{=});
        drv:=fso.GetDrive(fso.GetDriveName(AFileName));
        Result:=drv.FileSystem='NTFS'{=};
      END;
      
      FUNCTION StgOpenStorageEx(
       CONST pwcsName:POleStr;   //Pointer to the path of the
                                 //file containing storage object
             grfMode:LongInt;    //Specifies the access mode for the object
             stgfmt:DWORD;       //Specifies the storage file format
             grfAttrs:DWORD;     //Reserved; must be zero
             pStgOptions:Pointer;//Address of STGOPTIONS pointer
             reserved2:Pointer;  //Reserved; must be zero
             riid:PGUID;         //Specifies the GUID of the interface pointer
             OUT stgOpen:IStorage//Address of an interface pointer
      ) : HResult; stdcall; external 'ole32.dll'{=};
      
      FUNCTION GetFileSummaryInfo(FileName:AnsiString):AnsiString;
      {Read the File Summary Info of a file (NTFS)}
        FUNCTION PropertyPIDToCaption(CONST ePID:Cardinal):AnsiString;
        BEGIN {PropertyPIDToCaption}
          CASE ePID OF
            PID_TITLE:       Result:='Title';
            PID_SUBJECT:     Result:='Subject';
            PID_AUTHOR:      Result:='Author';
            PID_KEYWORDS:    Result:='Keywords';
            PID_COMMENTS:    Result:='Comments';
            PID_TEMPLATE:    Result:='Template';
            PID_LASTAUTHOR:  Result:='Last Saved By';
            PID_REVNUMBER:   Result:='Revision Number';
            PID_EDITTIME:    Result:='Total Editing Time';
            PID_LASTPRINTED: Result:='Last Printed';
            PID_CREATE_DTM:  Result:='Create Time/Date';
            PID_LASTSAVE_DTM:Result:='Last Saved Time/Date';
            PID_PAGECOUNT:   Result:='Number of Pages';
            PID_WORDCOUNT:   Result:='Number of Words';
            PID_CHARCOUNT:   Result:='Number of Characters';
            PID_THUMBNAIL:   Result:='Thumbnail';
            PID_APPNAME:     Result:='Creating Application';
            PID_SECURITY:    Result:='Security';
            ELSE             Result:='$'+IntToHex(ePID,8);
          END
        END; {PropertyPIDToCaption}
      VAR i,k:Integer;
          PropSetStg:IPropertySetStorage;
          PropSpec:ARRAY OF TPropSpec;
          PropStg:IPropertyStorage;
          PropVariant:ARRAY OF TPropVariant;
          Rslt:HResult;
          S:AnsiString;
          Stg:IStorage;
          PropEnum:IEnumSTATPROPSTG;
          HR:HResult;
          PropStat:STATPROPSTG;
          AHRes:HRESULT;
          PFNw,P:PWideChar;
      BEGIN {GetFileSummaryInfo}
        GetMem(P,257); PFNw:=StringToWideChar(FileName,P,256);
        Result := '';
        TRY
          OleCheck(StgOpenStorageEx(PFNw,STGM_READ OR STGM_SHARE_DENY_WRITE,STGFMT_FILE,0,NIL,NIL,@IID_IPropertySetStorage,Stg));
          PropSetStg:=Stg AS IPropertySetStorage;
          AHRes:=PropSetStg.Open(FmtID_SummaryInformation,STGM_READ OR STGM_SHARE_EXCLUSIVE,PropStg);
          IF AHRes<>S_OK THEN Exit;
          OleCheck(AHRes);
          OleCheck(PropStg.Enum(PropEnum));
          hr:=PropEnum.Next(1,PropStat,NIL);
          i:=0;
          WHILE hr=S_OK DO BEGIN
            inc(i);
            SetLength(PropSpec,I);
            PropSpec[i-1].ulKind:=PRSPEC_PROPID;
            PropSpec[i-1].propid:=PropStat.propid;
            hr := PropEnum.Next(1,PropStat, nil);
          END;
          SetLength(PropVariant,i);
          Rslt:=PropStg.ReadMultiple(i,@PropSpec[0],@PropVariant[0]);
          IF Rslt=S_FALSE THEN Exit;
          FOR k:=0 TO i-1 DO BEGIN
            S:='';
            IF (PropVariant[k].vt=VT_LPWSTR) AND Assigned(PropVariant[k].pwszVal) THEN
              S:=WideCharToString(PropVariant[k].pwszVal);
            IF (PropVariant[k].vt=VT_LPSTR) AND Assigned(PropVariant[k].pszVal) THEN
              S:=PropVariant[k].pszVal;
            S:=PropertyPIDToCaption(PropSpec[k].Propid)+'='+S;
            IF S<>'' THEN Result:=Result+S+#13#10;
          END;
        FINALLY
        END;
      END; {GetFileSummaryInfo}
      
      PROCEDURE SetFileSummaryInfo(FileName,Author,Title,Subject,Keywords,Comments:AnsiString);
      {Write some fields of the File Summary Info of a file (NTFS)}
      VAR PropSetStg:IPropertySetStorage;
          PropSpec:ARRAY OF TPropSpec;
          PropStg:IPropertyStorage;
          PropVariant:ARRAY OF TPropVariant;
          Stg:IStorage;
          PFNw,P:PWideChar;
          Anz:LongInt;
      BEGIN {SetFileSummaryInfo}
        IF NOT IsNTFS(FileName) THEN Exit;
        Anz:=5;
        GetMem(P,257); PFNw:=StringToWideChar(FileName,P,256);
        OleCheck(StgOpenStorageEx(PFNw,STGM_SHARE_EXCLUSIVE OR STGM_READWRITE,STGFMT_ANY,0,NIL,NIL,@IID_IPropertySetStorage,Stg));
        PropSetStg:=Stg AS IPropertySetStorage;
        OleCheck(PropSetStg.Create(FmtID_SummaryInformation,FmtID_SummaryInformation,PROPSETFLAG_DEFAULT,STGM_CREATE OR STGM_READWRITE OR STGM_SHARE_EXCLUSIVE,PropStg));
        Setlength(PropSpec,Anz);
        PropSpec[0].ulKind:=PRSPEC_PROPID;
        PropSpec[0].propid:=PID_AUTHOR;
        PropSpec[1].ulKind:=PRSPEC_PROPID;
        PropSpec[1].propid:=PID_TITLE;
        PropSpec[2].ulKind:=PRSPEC_PROPID;
        PropSpec[2].propid:=PID_SUBJECT;
        PropSpec[3].ulKind:=PRSPEC_PROPID;
        PropSpec[3].propid:=PID_KEYWORDS;
        PropSpec[4].ulKind:=PRSPEC_PROPID;
        PropSpec[4].propid:=PID_COMMENTS;
        SetLength(PropVariant,Anz);
        PropVariant[0].vt:=VT_LPSTR;
        PropVariant[0].pszVal:=PChar(Author);
        PropVariant[1].vt:=VT_LPSTR;
        PropVariant[1].pszVal:=PChar(Title);
        PropVariant[2].vt:=VT_LPSTR;
        PropVariant[2].pszVal:=PChar(Subject);
        PropVariant[3].vt:=VT_LPSTR;
        PropVariant[3].pszVal:=PChar(Keywords);
        PropVariant[4].vt:=VT_LPSTR;
        PropVariant[4].pszVal:=PChar(Comments);
        OleCheck(PropStg.WriteMultiple(Anz,@PropSpec[0],@PropVariant[0],2));
        PropStg.Commit(STGC_DEFAULT);
        FreeMem(P);
      END; {SetFileSummaryInfo}
      

      【讨论】:

      • 不适用于网络驱动器和 Windows 文件资源管理器不显示条目 :-(
      猜你喜欢
      • 2012-04-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-27
      相关资源
      最近更新 更多