
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.218.158.43] |
![]() |
|
Страницы: (2) 1 [2] все ( Перейти к последнему сообщению ) |
Сообщ.
#16
,
|
|
|
Господа программисты, помогите!
Имею биологическое образование. Третью неделю лажу по интернету, одно понял - без вашей помощи мне не обойтись. Мне нужно получать свойства (автор, ключевые слова) из не compound файлов (в частности TIFF, JPEG). Как я понял, на этом форуме говорится именно об этом. Но разговор окончился на том, что Krid изменил код на подходящий, и... все. Выручайте! Опубликуйте исходник. |
![]() |
Сообщ.
#17
,
|
|
Цитата к.б.н. @ Мне нужно получать свойства (автор, ключевые слова) из не compound файлов (в частности TIFF, JPEG). Вот тебе пример. Снимает то, что тебе нужно и немного еще (из дополнительных свойств нет времени писать демку полного разбора) ![]() ![]() uses GDIPOBJ, GDIPAPI, GDIPUTIL, ActiveX; {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); function GetAdvTagData(const ID: Integer): String; const TAG_Title = 40091; TAG_Comments = 40092; TAG_Author = 40093; TAG_KeyWords = 40094; TAG_Subject = 40095; begin case ID of TAG_Title: Result := 'Title'; TAG_Comments: Result := 'Comments'; TAG_Author: Result := 'Author'; TAG_KeyWords: Result := 'KeyWords'; TAG_Subject: Result := 'Subject'; else Result := ''; end; end; var GDIImage: TGPImage; I, ACount, PropSize: Integer; PropertyesList: array of TPropId; PropertyItem: PPropertyItem; PropName: String; PropValue: WideString; ByteValue: DWORD; begin if OpenDialog1.Execute then begin Memo1.Clear; GDIImage := TGPImage.Create(OpenDialog1.FileName); try ACount := GDIImage.GetPropertyCount; SetLength(PropertyesList, ACount); GDIImage.GetPropertyIdList(ACount, @PropertyesList[0]); for I := 0 to ACount - 1 do begin PropSize := GDIImage.GetPropertyItemSize(PropertyesList[I]); GetMem(PropertyItem, PropSize); try GDIImage.GetPropertyItem(PropertyesList[I], PropSize, PropertyItem); PropName := GetAdvTagData(PropertyesList[I]); if PropName <> '' then begin SetLength(PropValue, PropertyItem^.length); Move(PropertyItem^.value^, PropValue[1], PropertyItem^.length); end else begin PropName := GetMetaDataIDString(PropertyItem^.id); ByteValue := 0; if PropertyItem^.type_ in [PropertyTagTypeByte, PropertyTagTypeShort, PropertyTagTypeLong] then begin if PropertyItem^.length <= 4 then begin Move(PropertyItem^.value^, ByteValue, PropertyItem^.length); PropValue := IntToStr(ByteValue); end else begin SetLength(PropValue, PropertyItem^.length); Move(PropertyItem^.value^, PropValue[1], PropertyItem^.length); end; end; end; Memo1.Lines.Add(PropName + ' - ' + PropValue); finally FreeMem(PropertyItem); end; end; finally GDIImage.Free; end; end; end; |
![]() |
Сообщ.
#18
,
|
|
Цитата к.б.н. @ Мне нужно получать свойства (автор, ключевые слова) из не compound файлов (в частности TIFF, JPEG). Как я понял, на этом форуме говорится именно об этом. Не правильно понял. Читай внимательно предыдущие посты и введение к коду из фака (как извлечь "Сводку" свойств файла). Там говорится о стандартных св-вах, хранящихся либо внутри compound файлов либо в файловых потоках, ассоциированных с файлом. А получение специфических св-в файлов определённого типа - это совсем из другой оперы. Тут используются свои наборы API (см. например, код Rouse_ - там юзаются ф-ции из gdiplus.dll)/свои интерфейсы/прямое чтение "тэгов" из файла/etc. Вобщем, твой вопрос (о св-вах TIFF, JPEG) скорее для форума Delphi: Multimedia |
Сообщ.
#19
,
|
|
|
Благодарю!
Отличный код. Все работает. Правда, чтобы получить только необходимое (название, коммент., автор...), я его несколько укоротил. Для таких же тупых как я, прокомментирую: Здесь используется новый интерфейс GDI+. Работает на Windows XP и .NET Server, на более ранних ПО не работает (без определенной доработки). Чтобы с этим кодом заработал Delphi, в него надо установить соответствующие заголовочные файлы (подробности http://www.delphikingdom.com/asp/viewitem.asp?catalogid=772 ) |
Сообщ.
#20
,
|
|
|
MSI файлы - это наборы таблиц и комманд для интерпретатора msiexec. Разумеется вы можете опросить таблицы внутри msi на предмет количесва названия файлов всего что вы пожелаете, есть даже SQL подобный язык. Для интересующихся - скачайте Microsoft MSI Orca. (http://www.technipages.com/downloadview-details-44-Orca_MSI_Editor.html).
Примерно код для прочтения какого либо свойтсва из MSI: ![]() ![]() const msilib = 'msi.dll'; type MSIHANDLE = DWORD; TMsiHandle = MSIHANDLE; function MsiCloseHandle(hAny: MSIHANDLE):UINT;stdcall;external msilib name 'MsiCloseHandle'; function MsiOpenProduct(szProduct:LPCSTR;var hProduct:MSIHANDLE):UINT;stdcall;external msilib name 'MsiOpenProductA'; function MsiGetProductProperty(hProduct:MSIHANDLE;szProperty:LPCSTR;lpValueBuf:LPSTR;pcchValueBuf:LPDWORD):UINT;stdcall; external msilib name 'MsiGetProductPropertyA'; function MsiSetInternalUI(dwUILevel:INSTALLUILEVEL;phWnd:LPHWND):INSTALLUILEVEL;stdcall; external msilib name 'MsiSetInternalUI'; function GetMSIProperty(aProductCode:string):string; var msi:TMSIHandle; t:string; function _getmsiproperty(_name:string):string; var txt:PChar; sz:DWORD; begin sz:=MAX_PATH; txt:=AllocMem(sz+1); if MsiGetProductProperty(msi,PChar(_name),txt,@sz)=ERROR_MORE_DATA then begin ReAllocMem(txt,sz+1); MsiGetProductProperty(msi,PChar(_name),txt,@sz); end; SetString(Result,txt,sz); FreeMem(txt,sz+1); end; begin MsiSetInternalUI(2,nil); // скрываем GUI if MsiOpenProduct(PChar(aProductCode),msi)=ERROR_SUCCESS then begin t:=_getmsiproperty('ARPPRODUCTICON'); // главная иконка приложения if t='' then t:=_getmsiproperty('ProductIcon'); if t='' then t:=_getmsiproperty('CompleteSetupIcon'); if t='' then t:=_getmsiproperty('CustomSetupIcon'); if t='' then t:=_getmsiproperty('InfoIcon'); if t='' then t:=_getmsiproperty('InstallerIcon'); if t='' then t:=_getmsiproperty('RemoveIcon'); if t='' then t:=_getmsiproperty('RepairIcon'); Result:=t; MsiCloseHandle(msi); end; end; |
Сообщ.
#21
,
|
|
|
работаю на builder c++,
но к сожалению, у меня при вызове hr = pPropSetStg->Open(PropSetfmtid, STGM_READ, &pPropStg ); получаю hr равную -2147286785, т.е. возникает ошибка, для doc файлов такая ошибка не возникает вот весь участок кода: ![]() ![]() FMTID PropSetfmtid={0xf29f85e0,0x4ff9,0x1068,{0xab, 0x91, 0x08, 0x00, 0x2b, 0x27, 0xb3, 0xd9 }}; HRESULT hr = S_OK; IPropertyStorage *pPropStg = NULL; IPropertySetStorage *pPropSetStg = NULL; IStorage *stgRoot = NULL; PROPSPEC propspec; PROPVARIANT propRead; if (StgOpenStorageEx(StringToOleStr(FileName), STGM_READ | STGM_SHARE_DENY_WRITE, STGFMT_ANY, 0, NULL, NULL, IID_IPropertySetStorage, reinterpret_cast<void**>(&pPropSetStg)) != S_OK) return; //if (pPropSetStg->Open(PropSetfmtid, STGM_DIRECT | STGM_SHARE_EXCLUSIVE | STGM_READ, &pPropStg ) != S_OK) // return; hr = pPropSetStg->Open(PropSetfmtid, STGM_DIRECT | STGM_SHARE_EXCLUSIVE | STGM_READ, &pPropStg ); propspec.ulKind = PRSPEC_PROPID; propspec.propid = 0x00000002; pPropStg->ReadMultiple(1, &propspec, &propRead); AnsiString Title = propRead.pszVal; подскажите пожалуйста как можно считать свойства из pdf и djvu файла? почему возникает ошибка? |
Сообщ.
#22
,
|
|
|
Доброго времени суток.
Подскажите пожалуйста. Использую за основу код из сообщения #5 от Krid. Но я хочу получить пользовательское свойство из .DOC файла. Вот такой код получился. ![]() ![]() procedure TForm1.Button1Click(Sender: TObject); var stgRoot: IStorage; stgPS: IPropertySetStorage; stgP: IPropertyStorage; ps: ^TPropSpec; pv: ^TPropVariant; ReturnCode: Integer; 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; if (StgOpenStorageEx(StringToOleStr(OpenDialog1.FileName), STGM_READ or STGM_SHARE_DENY_WRITE, STGFMT_ANY, 0, nil, nil, @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.ulKind := PRSPEC_PROPID; // ps.propid := PIDSI_TITLE; // свойство по имени ps.ulKind := PRSPEC_LPWSTR; ps.lpwstr := 'QWERTY'; // читаем св-во ReturnCode := stgP.ReadMultiple(1, ps, pv); if ReturnCode = S_OK then ShowMessage(pv.pszVal) else ShowMessage('Error!!!'); finally if assigned(ps) then FreeMem(ps); if assigned(pv) then FreeMem(pv); stgP := nil; stgPS := nil; stgRoot := nil; end; end; В тестируемом DOC файле создал свойство QWERTY при чтении свойство по имени всегда S_FALSE. Чтение стандартных свойств по номеру работает. Подскажите, пожалуйста что я не правильно делаю. |
![]() |
Сообщ.
#23
,
|
|
Пользовательские св-ва надо считывать из набора UserDefinedProperties, а ты открываешь SummaryInformation.
В stgPS.Open вместо FMTID_SummaryInformation юзай FMTID_UserDefinedProperties ({D5CDD505-2E9C-101B-9397-08002B2CF9AE}) |
Сообщ.
#24
,
|
|
|
Спасибо большое. Получилось.
|