Как извлечь "Сводку" свойств файла?

Previous  Top  Next

    
 

 

Ниже показан пример получения набора свойств файла (которые отображаются на вкладке "Сводка" диалогового окна "Свойства:").
В файловой системе NTFS читаются свойства любого файла (если они вообще есть, конечно). В других ФС читаются св-ва только compound-файлов (они же structured storage, т.е. файлы хранения структурированной информации, такие как файлы MS Office, пакеты MSI, etc.), т.к. в этом случае вся информация о св-вах находится в самих файлах (опять же, она может там и отсутствовать). Ну и, естественно, не читаются нестандартные свойства, т.к. они нигде не хранятся, а динамически добавляются на вкладку соответствующим файлу COM-сервером - обработчиком вкладок св-в (PropertySheetHandlers).
В этом примере считывается несколько св-в из набора SummaryInformation.

Code:

unit Unit1;

 

interface

 

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

Dialogs, StdCtrls, ComCtrls;

 

type

TForm1 = class(TForm)

   Button1: TButton;

   ListView1: TListView;

   OpenDialog1: TOpenDialog;

   procedure Button1Click(Sender: TObject);

   procedure FormCreate(Sender: TObject);

private

   { Private declarations }

public

   { Public declarations }

end;

 

var

Form1: TForm1;

 

implementation

 

{$R *.dfm}

 

uses ActiveX, ComObj;

 

function StgOpenStorageEx(const pwcsName : POleStr; grfMode : LongInt; stgfmt : DWORD;

                          grfAttrs : DWORD;  pStgOptions : Pointer; reserved2 : Pointer;

                           riid : PGUID; out stgOpen : IStorage ) : HResult; stdcall; external 'ole32.dll';

 

 

const

// GUID'ы для набора св-в SummaryInformation

FMTID_SummaryInformation  : TGUID = '{F29F85E0-4FF9-1068-AB91-08002B27B3D9}';

IID_IPropertySetStorage   : TGUID = '{0000013A-0000-0000-C000-000000000046}';

 

STGFMT_FILE = 3;

STGFMT_ANY = 4;

 

type

PPropSpecArray=^TPropSpecArray;  // массив спецификаций св-в

TPropSpecArray=array[0..999] of TPropSpec;

 

PPropVariantArray=^TPropVariantArray; // массив - приемник, куда будут помещены значения нужных св-в

TPropVariantArray=array[0..999] of TPropVariant;

 

 

// вспомогательные ф-ции  *******

 

function IsNTFS(AFileName : string) : boolean;

var

fso, drv : OleVariant;

begin

fso := CreateOleObject('Scripting.FileSystemObject');

drv := fso.GetDrive(fso.GetDriveName(AFileName));

Result:=drv.FileSystem = 'NTFS'

end;

 

function FileTimeToLocalSystemTime(ft:FILETIME):TSystemTime;

var

t:FILETIME;

begin

FileTimeToLocalFileTime(ft,t);

FileTimeToSystemTime(t,result);

end;

 

function SysTimeToStr(ST : TSystemTime):string;

begin

SetLength(result,15);

GetTimeFormat(LOCALE_USER_DEFAULT,0,@st,nil,@result[1],15);

SetLength(result, StrLen(@result[1]));

end;

 

function SysDateToStr(ST : TSystemTime) : string;

begin

SetLength(Result, 255);

GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, @ST, nil, @result[1], 255);

SetLength(Result, LStrLen(@result[1]));

end;

 

function SysDateTimeToStr(ST:TSystemTime):string;

begin

result:=SysDateToStr(ST)+' '+SysTimeToStr(ST)

end;

 

// *******

 

procedure TForm1.Button1Click(Sender: TObject);

var

stgRoot:IStorage;

stgPS:IPropertySetStorage;

stgP:IPropertyStorage;

ps:PPropSpecArray;

pv:PPropVariantArray;

lit:TListItem;  // значения св-в записываем в ListView

begin

 

if (not OpenDialog1.Execute) then exit;  // выбираем файл

 

// Проверяем: если это не compound file и система - не NTFS, тогда выходим.

// (для compound файлов FS не важна)

if (StgIsStorageFile(StringToOleStr(OpenDialog1.FileName))<>S_OK) then

if (not IsNTFS(OpenDialog1.FileName)) then

begin

  MessageBox(Handle,'NTFS needed for non-compound files','Error',MB_ICONERROR);

  exit;

end;

 

 

ListView1.Clear;

 

if (StgOpenStorageEx(StringToOleStr(OpenDialog1.FileName), STGM_READ or STGM_SHARE_DENY_WRITE,

                       STGFMT_ANY, 0, nilnil,

                      @IID_IPropertySetStorage, stgRoot)<>S_OK) then // открываем файл

begin

  MessageBox(Handle,'Can not open file','Error',MB_ICONERROR);

  exit;

end;

 

stgPS:=stgRoot as IPropertySetStorage;  // ссылаемся на нужный интерфейс

//открываем набор св-в

if (stgPS.Open(FMTID_SummaryInformation,STGM_READ or STGM_SHARE_EXCLUSIVE,stgP)<>S_OK) then

begin

MessageBox(Handle,'Can not open property set','Error',MB_ICONERROR);

exit;

end;

 

ps:=nil;

pv:=nil;

try

  GetMem(ps,SizeOf(TPropSpec));

  GetMem(pv,SizeOf(TPropVariant));

 

  ps[0].ulKind:=PRSPEC_PROPID;   // считываем св-ва по их идентификатору (см. ActiveX.pas)

 

//  Прочитаем несколько св-в файла.

//  В этом примере - для наглядности - читаем по одному св-ву из потока (можно за один раз прочитать и больше),

//  поэтому каждый раз значение будет лежать в pv[0].

 

  ps[0].propid:=PIDSI_TITLE;     // заголовок

  lit:=ListView1.Items.Add;

  lit.Caption:='Title';

  if (stgP.ReadMultiple(1, @ps[0], @pv[0])=S_OK) then // читаем св-во

  lit.SubItems.Add(pv[0].pszVal) // добавляем в ListView

  else lit.SubItems.Add('');

 

  ps[0].propid:=PIDSI_SUBJECT;   // тема

  lit:=ListView1.Items.Add;

  lit.Caption:='Subject';

  if (stgP.ReadMultiple(1, @ps[0], @pv[0])=S_OK) then

  lit.SubItems.Add(pv[0].pszVal)

  else lit.SubItems.Add('');

 

  ps[0].propid:=PIDSI_AUTHOR;   // автор

  lit:=ListView1.Items.Add;

  lit.Caption:='Author';

  if (stgP.ReadMultiple(1, @ps[0], @pv[0])=S_OK) then

  lit.SubItems.Add(pv[0].pszVal)

  else lit.SubItems.Add('');

 

  ps[0].propid:=PIDSI_COMMENTS; // комментарий

  lit:=ListView1.Items.Add;

  lit.Caption:='Comment';

  if (stgP.ReadMultiple(1, @ps[0], @pv[0])=S_OK) then

  lit.SubItems.Add(pv[0].pszVal)

  else lit.SubItems.Add('');

 

  ps[0].propid:=PIDSI_REVNUMBER; // номер редакции

  lit:=ListView1.Items.Add;

  lit.Caption:='Revision';

  if (stgP.ReadMultiple(1, @ps[0], @pv[0])=S_OK) then

  lit.SubItems.Add(pv[0].pszVal)

  else lit.SubItems.Add('');

 

  ps[0].propid:=PIDSI_APPNAME;   // приложение, создавшее пакет

  lit:=ListView1.Items.Add;

  lit.Caption:='Application';

  if (stgP.ReadMultiple(1, @ps[0], @pv[0])=S_OK) then

  lit.SubItems.Add(pv[0].pszVal)

  else lit.SubItems.Add('');

 

  ps[0].propid:=PIDSI_CREATE_DTM;   // Дата создания

  lit:=ListView1.Items.Add;

  lit.Caption:='Creation date';

  if (stgP.ReadMultiple(1, @ps[0], @pv[0])=S_OK) then

  lit.SubItems.Add(SysDateTimeToStr(FileTimeToLocalSystemTime(pv[0].filetime)))

  else lit.SubItems.Add('');

 

  ps[0].propid:=PIDSI_WORDCOUNT; // кол-во слов в документе

  lit:=ListView1.Items.Add;

  lit.Caption:='Word count';

  if (stgP.ReadMultiple(1, @ps[0], @pv[0])=S_OK) then

  lit.SubItems.Add(IntToStr(pv[0].lVal))

  else lit.SubItems.Add('');

 

finally

  if assigned(ps) then FreeMem(ps);

  if assigned(pv) then FreeMem(pv);

  stgP:=nil;

  stgPS:=nil;

  stgRoot:=nil;

end;

end;

 

procedure TForm1.FormCreate(Sender: TObject);

begin

// добавим в список 2 столбца (лучше это делать в дизайнере)

ListView1.ViewStyle:=vsReport;

ListView1.Columns.Add.Caption:='Name';

ListView1.Columns.Add.Caption:='Value';

 

// добавим в диалог открытия несколько типов compound-файлов

OpenDialog1.Filter:='All Files (*.*)|*.*|MS Office Documents (*.doc;*.xls;*.dot)'+

'|*.doc; *.xls; *.dot|MSI Databases (*.msi)|*.msi';

end;

 

end.

 

Взято из http://forum.sources.ru

Автор: Krid

©Drkb::03147