如何以编程方式设置文件标签

发布于 2024-09-05 15:52:59 字数 155 浏览 5 评论 0原文

当使用 Windows 资源管理器查看文件时,我可以选择设置“标签”、“类别”或其他属性。对于 JPEG,可以选择一组不同的属性(包括“标签”)。我希望能够以编程方式设置这些。

如何使用 Delphi 以编程方式设置文件标记和其他文件属性(我有 Delphi 2010 Pro)?

When using Windows Explorer to view files, I'm given the option to set a "tag", "category", or other attributes. For a JPEG a different set of attributes (including "tag") are options. I'd like to be able to set these programmatically.

How do I programmatically set a file tag and other file attributes using Delphi (I have Delphi 2010 Pro)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

音盲 2024-09-12 15:52:59

JPEG 文件中的标签存储为 IPTC 关键字。如果您需要的话,有一些库可用于阅读和编写这些内容。

资源管理器为不同的文件类型显示不同的列,因为它知道这些文件类型支持这些额外的列。您可以定义 shell 插件来支持您自己的文件类型的自定义列信息。 MSDN 提供了概述。

Tags in JPEG files are stored as IPTC keywords. There are a few libraries available for reading and writing those, if that's what you're asking for.

Explorer shows different columns for different file types because it knows that those file types support those extra columns. You can define shell plug-ins to support custom column information for your own file types. MSDN provides an overview.

鼻尖触碰 2024-09-12 15:52:59

我认为您想要检索可以在资源管理器中按鼠标右键访问的文件的所有属性。

您可以使用这个单元:

unit u_fsummary;

interface

uses Windows, ComObj, ActiveX, Variants, Sysutils;

procedure SetFileSummaryInfo(const FileName : WideString; Author, Title, Subject, Keywords, Comments : WideString);
function GetFileSummaryInfo(const FileName: WideString): String;
function IsNTFS(AFileName : string) : boolean;

implementation

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


function GetFileSummaryInfo(const FileName: WideString): String;

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 := '

这不是我的代码,但我已经成功使用了它。效果很好。
要检索属性,您可以执行以下操作:

mmProps2.Lines.Text := GetFileSummaryInfo(edtFile.Text);

问候


Neftalí

+ 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; end; procedure SetFileSummaryInfo(const FileName : WideString; Author, Title, Subject, Keywords, Comments : WideString); var PropSetStg: IPropertySetStorage; PropSpec: array of TPropSpec; PropStg: IPropertyStorage; PropVariant: array of TPropVariant; Stg: IStorage; begin OleCheck(StgOpenStorageEx(PWideChar(FileName), 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,6); 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; PropSpec[5].ulKind := PRSPEC_PROPID; PropSpec[5].propid := 99; SetLength(PropVariant,6); PropVariant[0].vt:=VT_LPWSTR; PropVariant[0].pwszVal:=PWideChar(Author); PropVariant[1].vt:=VT_LPWSTR; PropVariant[1].pwszVal:=PWideChar(Title); PropVariant[2].vt:= VT_LPWSTR; PropVariant[2].pwszVal:=PWideChar(Subject); PropVariant[3].vt:= VT_LPWSTR; PropVariant[3].pwszVal:=PWideChar(Keywords); PropVariant[4].vt:= VT_LPWSTR; PropVariant[4].pwszVal:=PWideChar(Comments); PropVariant[5].vt:= VT_LPWSTR; PropVariant[5].pwszVal:=PWideChar(Comments); OleCheck(PropStg.WriteMultiple(6, @PropSpec[0], @PropVariant[0], 2 )); PropStg.Commit(STGC_DEFAULT); end; end.

这不是我的代码,但我已经成功使用了它。效果很好。
要检索属性,您可以执行以下操作:

问候


Neftalí

I think that you want retrieve all properties of the file that can be accesed pressing right button on mouse in explorer.

You can use this unit:

unit u_fsummary;

interface

uses Windows, ComObj, ActiveX, Variants, Sysutils;

procedure SetFileSummaryInfo(const FileName : WideString; Author, Title, Subject, Keywords, Comments : WideString);
function GetFileSummaryInfo(const FileName: WideString): String;
function IsNTFS(AFileName : string) : boolean;

implementation

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


function GetFileSummaryInfo(const FileName: WideString): String;

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 := '

This is not my code, but i have used it successfully. It work fine.
To retrieve properties you can do this:

mmProps2.Lines.Text := GetFileSummaryInfo(edtFile.Text);

Regards


Neftalí

+ 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; end; procedure SetFileSummaryInfo(const FileName : WideString; Author, Title, Subject, Keywords, Comments : WideString); var PropSetStg: IPropertySetStorage; PropSpec: array of TPropSpec; PropStg: IPropertyStorage; PropVariant: array of TPropVariant; Stg: IStorage; begin OleCheck(StgOpenStorageEx(PWideChar(FileName), 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,6); 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; PropSpec[5].ulKind := PRSPEC_PROPID; PropSpec[5].propid := 99; SetLength(PropVariant,6); PropVariant[0].vt:=VT_LPWSTR; PropVariant[0].pwszVal:=PWideChar(Author); PropVariant[1].vt:=VT_LPWSTR; PropVariant[1].pwszVal:=PWideChar(Title); PropVariant[2].vt:= VT_LPWSTR; PropVariant[2].pwszVal:=PWideChar(Subject); PropVariant[3].vt:= VT_LPWSTR; PropVariant[3].pwszVal:=PWideChar(Keywords); PropVariant[4].vt:= VT_LPWSTR; PropVariant[4].pwszVal:=PWideChar(Comments); PropVariant[5].vt:= VT_LPWSTR; PropVariant[5].pwszVal:=PWideChar(Comments); OleCheck(PropStg.WriteMultiple(6, @PropSpec[0], @PropVariant[0], 2 )); PropStg.Commit(STGC_DEFAULT); end; end.

This is not my code, but i have used it successfully. It work fine.
To retrieve properties you can do this:

Regards


Neftalí

请爱~陌生人 2024-09-12 15:52:59

我知道没有标准方法来存储附加元数据信息。每个应用程序都可以注册自己的属性选项卡,并可以以任何方式存储此元数据信息。

我相信您谈论的是 Windows 照片库的图像标记功能。

该信息存储在两个文件中: pictures.pd4 和 NavTree.state
Gail Bjork 确定想要删除此信息的人

它存储在:C:\Users\YourUser\AppData\Local\Microsoft\Windows Photo Gallery。

有些人已经弄清楚了文件格式。但我还没有找到微软内部或外部任何人发布的规范。

您还询问了其他文件属性,这些属性可以通过

FileSetAttr(FileName,Attribute)

可设置的属性进行设置:

  • faReadOnly
  • faHidden
  • faSysFile
  • faVolumeID
  • faDirectory
  • faArchive
  • faSymLink

//以下将 test.txt 设置为只读和隐藏文件。
FileSetAttr('C:\Test.txt',faReadOnly 或 faHidden);

该函数确实有一个布尔结果,您可以检查该结果以了解操作是否成功完成。

I know of no standard way to store additional meta data information. Each application can register there own property tab and could store this meta data information in any way.

I believe your talking about the image tagging feature of Windows Photo Gallery.

The information is stored in two files: pictures.pd4 and NavTree.state
as determined by Gail Bjork person who wanted to remove this information.

This stored in: C:\Users\YourUser\AppData\Local\Microsoft\Windows Photo Gallery.

Some people have figured out the file format. But I have not found a published spec from anyone internal to Microsoft or external.

You also asked about other file attributes these can be set through the

FileSetAttr(FileName,Attribute)

Attributes that can be set:

  • faReadOnly
  • faHidden
  • faSysFile
  • faVolumeID
  • faDirectory
  • faArchive
  • faSymLink

//The following sets test.txt to a readonly and hidden file.
FileSetAttr('C:\Test.txt',faReadOnly or faHidden);

The function does have a boolean result that you can check to see if the operation completed successfully.

云仙小弟 2024-09-12 15:52:59

我现在正在开发一个标记应用程序,似乎最好的答案是 Windows Imaging Component API,它具有读取和写入各种图像格式(Exif、IPTC 等)元数据的实现。应该区分文件系统中文件的元数据和文件本身内的元数据——这是指后者。

Getty Images 也有一篇关于使用 WIC API 进行编程。

I'm developing a tagging application right now, and it seems that the best answer is the Windows Imaging Component API, which has implementations for reading and writing metadata for various image formats (Exif, IPTC, etc.). A distinction should be made between metadata for the file in the filesystem and metadata within the file itself--this is referencing the latter.

Getty Images also has a good article on programming with the WIC API.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文