Delphi:如何设置(写入)扩展文件属性?

4
我想设置属性,就像Windows资源管理器文件属性->摘要选项卡中所示的那样(作者、标题、主题等)。 (在Windows 7中是详细信息选项卡) 我已经知道如何使用StgCreateStorageEx进行获取。
目标文件扩展名为xls、xlsx、csv、txt和jpg。 操作系统:Windows 2003/2008/XP/Windows 7。 请注意,此代码将成为Web服务应用程序,并且服务器未安装Excel。
注意:似乎没有关于如何设置它们的信息/示例代码。 Details tab

如果答案回答了问题,我很乐意给它一个赞。 - mas_oz2k1
3个回答

6

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;

更多信息请参阅http://www.delphi-central.com/tutorials/File_Summary_Info.aspx。此外,http://www.swissdelphicenter.ch/torry/showcode.php?id=1614可以展示如何操作[IPropertyStorage]


你尝试过Unicode Delphi中的一些示例吗?我曾经在Delphi 2009中尝试了完全相同的代码来自于这篇文章,但在PropSetStg.Open处却出现了“%1未找到”的错误,就像这里描述的那样 - TLama
@TLama - 我之前在 Windows XP 上尝试过 Delphi 7,效果还不错。这也是我发布此问题代码的原因。我不知道会出现这些问题。如果无法正常工作,OP 可以发表评论,我将删除答案。 - RBA
@RBA,事实是我没有尝试过在非Unicode Delphi上运行,因为我认为这可能与操作系统有关(我使用的是Windows 7)。 - TLama
@RBA,示例代码仅展示如何获取属性(来自链接),我的问题是关于如何为特定的目标文件和操作系统设置属性。 - mas_oz2k1
@RBA,我的错,我忘了在问题中提到Delphi Central的链接 - 你是用这个代码作为服务器应用程序还是客户端桌面?注意:第二个链接使用OLE对象,但目标文件是Word文档。 - mas_oz2k1

1

部分答案:Delphi代码的设置属性可以在这里找到。 或者如果你有最新的JCL库-使用jclNtfs.pas中的TJclFilePropertySet 警告:请注意,在Windows 7 Pro / Enterprise或2008(64位)中,此代码适用于xls文件,但似乎不适用于txt / cvs和jpg文件。 看来M $已经改变了这些操作系统中属性的工作方式:“您无法添加或更改某些类型文件的文件属性。例如,您无法向TXT或RTF文件添加任何属性”。不幸的是,对我来说,回到XP模式不是一个选项。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接