Einzelnen Beitrag anzeigen

Delphi-Lover

Registriert seit: 19. Okt 2004
Ort: Amsterdam
30 Beiträge
 
Delphi 2005 Professional
 
#16

Re: Erweiterte Dateiinformationen schreiben

  Alt 25. Apr 2005, 16:00
Hello,

For the community.

I was just fighting to read the filesummaryinfo and nothing seems to work, so I puzzled with some sources from this site and the main source from Serge Perevoznyk (that you can find on 10.000 sites via Google) Here is the source that will work on WindowsXP and Delphi >= 5.

Code:
unit UFileSummaryInfo;

interface

uses Windows, ActiveX, ComObj;

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.

//I've changed the numbers of the original constants to get the right PID...
//e.g. I decreased all const with 2...
// Summary Information
 PID_TITLE       = 0; //2;
 PID_SUBJECT     = 1;
 PID_AUTHOR      = 2;
 PID_KEYWORDS    = 3;
 PID_COMMENTS    = 4;
 PID_TEMPLATE    = 5;
 PID_LASTAUTHOR  = 6;
 PID_REVNUMBER   = 7;
 PID_EDITTIME    = 8;
 PID_LASTPRINTED = 9;
 PID_CREATE_DTM  = 10;
 PID_LASTSAVE_DTM = 11;
 PID_PAGECOUNT   = 12;
 PID_WORDCOUNT   = 13;
 PID_CHARCOUNT   = 14;
 PID_THUMBNAIL   = 15;
 PID_APPNAME     = 16;
 PID_SECURITY    = 17;

 // 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 : string) : boolean;
function GetFileSummaryInfo(const FileName: WideString;
 GUID_SummaryType: TGUID; PID_InfoType: cardinal): WideString;

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 :             //Address of an interface pointer
 IStorage ) : HResult; stdcall; external 'ole32.dll';

implementation

uses SysUtils;

function PropertyPIDToCaption(const ePID: Cardinal): string;
begin
 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;

function IsNTFS(AFileName : string) : boolean;
var fso, drv : OleVariant;
begin
  IsNTFS := False;
  fso := CreateOleObject('Scripting.FileSystemObject');
  drv := fso.GetDrive(fso.GetDriveName(AFileName));
  if drv.FileSystem = 'NTFS' then IsNTFS := True;
end;

function GetFileSummaryInfo(const FileName: WideString;
  GUID_SummaryType: TGUID; PID_InfoType: cardinal): WideString;
var
  Stg: IStorage;
  PropSetStg: IPropertySetStorage;
  PropStg: IPropertyStorage;
  PropVariant: array of TPropVariant;
  PropEnum: IEnumSTATPROPSTG;
  PropStat: STATPROPSTG;
  PIDCount: Integer;
  HRslt: HResult;
  PropSpec: array of TPropSpec;
begin
  Result:='';

  //I use the STGFMT_ANY const instead of the original STGFMT_FILE that didn't work at all...
  if(StgOpenStorageEx(pwidechar(FileName),STGM_READ or STGM_SHARE_DENY_WRITE,
    STGFMT_ANY,0,nil,nil,@IID_IPropertySetStorage,Stg) = S_OK) then
  begin
    PropSetStg := Stg as IPropertySetStorage;

    If (PropSetStg.Open(GUID_SummaryType,
                        STGM_READ or STGM_SHARE_EXCLUSIVE,
                        PropStg)) = S_OK Then
    Begin
      If PropStg.Enum(PropEnum) = S_OK then
      Begin
        PIDCount := 0;

        HRslt := PropEnum.Next(1, PropStat, nil);
        while HRslt = S_OK do
        begin
          inc(PIDCount);
          SetLength(PropSpec,PIDCount);
          PropSpec[PIDCount-1].ulKind := PRSPEC_PROPID;
          PropSpec[PIDCount-1].propid := PropStat.propid;
          HRslt := PropEnum.Next(1, PropStat, nil);
        end;

        SetLength(PropVariant,PIDCount);
        HRslt := PropStg.ReadMultiple(PIDCount, @PropSpec[0], @PropVariant[0]);

        // Use this to get the Incomming PID_InfoType
        if HRslt <> S_FALSE then
        Begin
          if PropVariant[PID_InfoType].vt = VT_LPSTR then
            if Assigned(PropVariant[PID_InfoType].pszVal) then
              Result := PropVariant[PID_InfoType].pszVal;
        End;

        //Use This to loop through all PID's
        //(and ignore the incomming PID_InfoType)
        {
        for k := 0 to PIDCount -1 do
        begin
          S := '';
          if PropVariant[k].vt = VT_LPSTR then
            if Assigned(PropVariant[k].pszVal) then
              S := PropVariant[k].pszVal;

          S := Format(IntToStr(k)+' '+PropertyPIDToCaption(PropSpec[k].Propid)+ ' %s',[s]);
          if S <> '' then Result := Result + S + #13;
        end;
        }
      End;
    End;
  end;
end;

end.
Use the function in this way:

Code:
Var FileName,Info : WideString;
Begin
  If IsNTFS(FileName) Then
  Begin
    Info:=GetFileSummaryInfo(FileName,FmtID_SummaryInformation,PID_KEYWORDS);
    MessageDlg(Info,mtCustom,[mbOK], 0);
  End;
End
Experiment with the PID_ numbers and these values

FmtID_SummaryInformation
FMTID_DocSummaryInformation
FMTID_UserDefinedProperties

Greets,

Delphi-Lover
Rob
  Mit Zitat antworten Zitat