4

I would like to set properties as shown in Windows Explorer File Properties->Summary Tab (Authors, Title, Subject, etc). (In Windows 7 is the Details tab) I already know how to GET them using StgCreateStorageEx,

The target file extensions are xls, xlsx, csv, txt and jpg files. OS: Windows 2003/2008/XP/Windows 7. Notice that this code will go a web service application and the server does not have Excel installed.

Note:It seems to be that there is no information/sample code about how to SET them. Details tab

mas_oz2k1
  • 2,851
  • 3
  • 34
  • 41

3 Answers3

6

To write summary information use IPropertyStorage:WriteMultiple method. See MSDN sample WriteRead. Not delphi but is easy to convert.

Xearinox
  • 3,224
  • 2
  • 24
  • 38
4
function GetFileSummaryInfo(const FileName: WideString): String;

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}';

const
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;

var
 I: Integer;
 PropSetStg: IPropertySetStorage;
 PropSpec: array of TPropSpec;
 PropStg: IPropertyStorage;
 PropVariant: array of TPropVariant;
 Rslt: HResult;
 S: String;
 Stg: IStorage;
 PropEnum: IEnumSTATPROPSTG;
 HR : HResult;
 PropStat: STATPROPSTG;
 k : integer;

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;

begin
 Result := '';
try
 OleCheck(StgOpenStorageEx(PWideChar(FileName),
 STGM_READ or STGM_SHARE_DENY_WRITE,
 STGFMT_FILE,
 0, nil,  nil, @IID_IPropertySetStorage, stg));

 PropSetStg := Stg as IPropertySetStorage;

 OleCheck(PropSetStg.Open(FmtID_SummaryInformation,
    STGM_READ or STGM_SHARE_EXCLUSIVE, PropStg));

 OleCheck(PropStg.Enum(PropEnum));
 I := 0;

 hr := PropEnum.Next(1, PropStat, nil);
  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_LPSTR then
      if Assigned(PropVariant[k].pszVal) then
       S := PropVariant[k].pszVal;

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

for more http://www.delphi-central.com/tutorials/File_Summary_Info.aspx. Also this : http://www.swissdelphicenter.ch/torry/showcode.php?id=1614 show you how to manipulate [IPropertyStorage]

RBA
  • 12,337
  • 16
  • 79
  • 126
  • Have you tried some of the examples in Unicode Delphi ? I've tried the very same code [`from this post`](http://stackoverflow.com/a/3051746/960757) in Delphi 2009 getting the `%1 not found` error at `PropSetStg.Open` like [`described here`](http://stackoverflow.com/q/12108295/960757). – TLama Aug 28 '12 at 07:28
  • @TLama - I have tried only in Delphi 7, on Windows XP some time ago, and it worked ok. This was the reason to post the code for this question. I did not knew about this problems. If is not working, OP can post a comment and I will delete the answer – RBA Aug 28 '12 at 08:01
  • @RBA, truth is that I haven't tried this with a non Unicode Delphi thinking about that *issue* as OS related (having Windows 7). – TLama Aug 28 '12 at 08:05
  • @RBA, the sample code is only how to get the properties(from the link), my question was regarding how to set the properties for the particular target files and OS – mas_oz2k1 Aug 28 '12 at 23:22
  • @RBA, My bad I forgot to mention the delphi central link in the question-did you use this code for server application or client desktop? Note: The second link uses ole objects but the target file is a word document. – mas_oz2k1 Aug 28 '12 at 23:39
1

Partial answer: The set property Delphi code can be found here. or if you have the latest JCL library - use TJclFilePropertySet at jclNtfs.pas Warning: Notice that this code works for xls files but it does not seem to work for txt/cvs and jpg files in Windows 7 Pro/Enterprise or 2008 (64 bits). It seems that M$ has changed the way properties work in these OS: "You can't add or change the file properties of some types of files. For example, you can't add any properties to TXT or RTF file". Sadly for me, going back to XP mode is not an option.

mas_oz2k1
  • 2,851
  • 3
  • 34
  • 41