На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
Дорогие девчонки! Поздравляем вас с праздником 8 Марта!
msm.ru
! user posted image
Пожалуйста, выделяйте текст программы тегом [сode=pas] ... [/сode]. Для этого используйте кнопку [code=pas] в форме ответа или комбобокс, если нужно вставить код на языке, отличном от Дельфи/Паскаля.

Соблюдайте общие правила форума

Следующие вопросы задаются очень часто, подробно разобраны в FAQ и, поэтому, будут безжалостно удаляться:
1. Преобразовать переменную типа String в тип PChar (PAnsiChar)
2. Как "свернуть" программу в трей.
3. Как "скрыться" от Ctrl + Alt + Del (заблокировать их и т.п.)
4. Как запустить программу/файл? (и дождаться ее завершения)
5. Как перехватить API-функции, поставить hook? (перехват сообщений от мыши, клавиатуры - внедрение в удаленное адресное прстранство)
... (продолжение следует) ...

Внимание:
Попытки открытия обсуждений реализации вредоносного ПО, включая различные интерпретации спам-ботов, наказывается предупреждением на 30 дней.
Повторная попытка - 60 дней. Последующие попытки - бан.
Мат в разделе - бан на три месяца...

Полезные ссылки:
user posted image MSDN Library user posted image FAQ раздела user posted image Поиск по разделу user posted image Как правильно задавать вопросы


Выразить свое отношение к модераторам раздела можно здесь: user posted image Rouse_, user posted image Krid

Модераторы: Rouse_, Krid
Страницы: (2) [1] 2  все  ( Перейти к последнему сообщению )  
> Как извлечь информацию из файла , как на вкладке "Сводка" в Windows Explorer
    Всем привет

    Разьясните пожалуйсто,как из файлов с расширением "*.msi" , с помощью API-функций
    из закладки "Сводка" извлечь информацию о Авторе и Теме

    Заранее благодарен.
      Хм красивый вопрос... Первый раз такой слышу, никто раньше не интересовался.
      По сабжу: MsiGetProductInfoFromScript

      Вообще смотри вот сюда: http://msdn.microsoft.com/library/en-us/msi/setup/installer_function_reference.asp
        Rouse_

        кажется всё очень просто, может фаил что то и хранит внутри себя
        но все эти данные также есть в реестрее

        Как говоритсяб а ЛАРЧИК-то просто открывался !!!!!
          Цитата ctranik @
          но все эти данные также есть в реестрее

          Хм, я вообщето обьяснял про неустановленный MSI пакет :)
            Вообще, *.msi - это обычные compound-файлы (или structured storage - файлы хранения структуированых данных) и они, помимо прочего, хранят в себе т.н. наборы cвойств, т.е. информацию о документе (которую видно на той же вкладке "Сводка"). Все эти св-ва можно прочитать напрямую из файла. Для этого в винде предназначены COM-интерфейсы IPropertySetStorage, IPropertyStorage, etc.
            Вот небольшой примерчик считывания некоторых св-в из любых compound файлов, а так же св-ва обычных файлов (которые отображаются на вкладке "Сводка" диалогового окна "Свойства:"):
            ExpandedWrap disabled
              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;
               
              // Этот код в стиле VB чисто для примера. Узнать, какая FS в системе можно и через WinAPI
              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;
               
              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, 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[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('');
               
               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
               // наборы св-в могут храниться не только в *.msi, но и в любых compound-файлах (например в документах MS Office)
               OpenDialog1.Filter:='MSI Databases (*.msi)|*.msi|MS Office Documents (*.doc;*.xls)|*.doc; *.xls|All Files (*.*)|*.*'
              end;
               
              end.


            В наборе SummaryInformation есть еще несколько св-в (не все из них строковые). Также compound-файлы могут содержать и другие наборы св-в, например DocumentSummaryInformation, UserDefinedProperties, а также какие-нибудь произвольно определенные пользователем. Вся инфа - в MSDN. Прототипы, константы, структуры - в ActiveX.pas
              Krid, замечательный пример !
              Меня смущает одно. Если эту прогу запустить дважды, то на второй раз она скажет "Error - файл уже используется". И это будет пока не перезагрузишься. :huh:
              Cдается мне что файлик то надо закрывать ... Так как здесь есть Open
              ExpandedWrap disabled
                OleCheck(StgOpenStorage(StringToOleStr(OpenDialog1.FileName),nil,
                                         STGM_READ or STGM_SHARE_EXCLUSIVE,nil,0,stgRoot));   // открываем его

              , то должен быть и Close .
              Кстати, не подскажешь как его вызвать то ?
                Еще у меня вопрос... Я не понял что же дает STGM_SHARE_EXCLUSIVE ?
                В MSDN написано

                Цитата
                STGM_SHARE_EXCLUSIVE
                Prevents others from subsequently opening the object in any mode. Note that this value is not a simple bitwise OR operation of the STGM_SHARE_DENY_READ and STGM_SHARE_DENY_WRITE values. In transacted mode, sharing of STGM_SHARE_DENY_WRITE or STGM_SHARE_EXCLUSIVE can significantly improve performance since they don't require snapshotting. See the following Remarks section for more information about transactioning.

                Обратите внимание на выделенно синим. Не это ли мешает открывать файл впоследствии?
                  Народ, ну, что серьезно никто не знает как решается проблема то ?
                    Krid, ну отзовись пожалуйста :( . При выборе pdf или вомг - файла прога пишет :

                    Цитата
                    *.Экзе рэйсед экспепшен класс EOleSysError whith message "%1 уже существует"


                    Чего это она ?
                      Цитата SexGenius @
                      Если эту прогу запустить дважды, то на второй раз она скажет "Error - файл уже используется". И это будет пока не перезагрузишься.

                      Ну правильно, это из-за STGM_SHARE_EXCLUSIVE. Этот флаг задает монопольный доступ к файлу (или секции/хранилищу/набору св-в в нем) для одной программы. Просто, в то время как ты читаешь из файла, другая прога может в него писать (например поменять св-во). А это не есть гуд.

                      Ну тут можно либо закрыть файл - т.е., после всех операций написать
                      ExpandedWrap disabled
                         stgRoot:=nil;
                      либо открыть, например так STGM_READ or STGM_SHARE_DENY_WRITE (вообще, поэксперементируй с флагами - их там до е@#-матери, см. MSDN). А вообще, по-идее, в моем примере такой ошибки быть не должно - файл закрывается по выходе из Button1Click (stgRoot - локальная).

                      Цитата SexGenius @
                      При выборе pdf или вомг - файла прога пишет :

                      Да это чего-то OleCheck мудрит. Я бы ее вообще убрал и написал что-то типа
                      ExpandedWrap disabled
                        if (StgOpenStorage(StringToOleStr(OpenDialog1.FileName),nil,
                                           STGM_READ or STGM_SHARE_EXCLUSIVE,nil,0,stgRoot)<>S_OK) then
                          begin
                           MessageBox(Handle,'Can not open doc file','Error',MB_ICONERROR);
                           exit;
                          end;

                      И кстати, везде убрал бы эту OleCheck (как-то она жисть осложняеть :)) и все бы делал ручками.

                      Вобщем, код подправил. Должно работать нормально. А так - эксперементируй и не ищи легких путей :)
                        Цитата Krid, 05.10.2005, 19:32:12, 876404
                        Да это чего-то OleCheck мудрит. Я бы ее вообще убрал и написал что-то типа

                        Тады при открытии djvu или pdf-файла прога пишет, как ты догадался, следующее:
                        Цитата
                        Can not open doc file
                          Дык, естественно! pdf - это не compound (doc/structured storage / хранилище структуированых данных). Они и не должны так открываться - у них совсем другой формат. Еще раз скажу, что таким макаром, как в примере могут открываться только compound файлы. А pdf и djvu к ним никакого отношения не имеют :no:
                            Цитата Krid, 05.10.2005, 20:44:11, 876474
                            Еще раз скажу, что таким макаром, как в примере могут открываться только compound файлы.

                            А есть-ли какой-нить универсальный макар, которым можно считывать информацию со вкладки Сводка для любых файлов NTFS . Может какие-нить константы повтыкать другие в функции ?
                              Ах вон ты чего хочешь :) Ну это тоже можно сделать.
                              Дело в том, что NTFS позволяет для каждого файла создавать т.н. файловые потоки (files stream). По сути это те же файлы, только их не видно и они имеют "особые" атрибуты в ФС. С ними можно работать так же, как и с обычными файлами: создавать, удалять, записывать в них инфу (можно юзать почти все файловые API ф-ции).
                              Когда ты открываешь вкладку "Свойства" и пишешь там чего-нить, винда создает для этого файла несколько потоков, в которые записывает то, что ты ввел.
                              С потоками можно работать, например из ком. строки в консоли:
                              ExpandedWrap disabled
                                Создание файла с потоком:
                                type nul > somefile.txt:Stream
                                 
                                Запись в поток:
                                echo "Something" >> somefile.txt:Stream
                                 
                                Чтение из потока:
                                more < somefile:Stream
                                 
                                Копирование содержимого существующего файла в поток:
                                type file1.txt >> somefile.txt:Stream
                                 
                                Копирование содержимого потока в файл:
                                more < somefile.txt:Stream >> file2.txt
                                 
                                Удаление потоков выполняется через DeleteFile.

                              а можно и в программе (пример создания потока):
                              ExpandedWrap disabled
                                procedure TForm1.Button1Click(Sender: TObject);
                                var
                                 dwRet:DWORD;
                                 hFile,hStream:THandle;
                                begin
                                // создаем файл
                                hFile:=CreateFile( 'C:\testfile.txt', GENERIC_WRITE, FILE_SHARE_WRITE, nil, OPEN_ALWAYS, 0, 0);
                                CloseHandle(hFile);
                                 
                                // создаем в нем поток и пишем в него чего-нибудь.
                                hStream:=CreateFile( 'C:\testfile.txt:mystream', GENERIC_WRITE, FILE_SHARE_WRITE, nil, OPEN_ALWAYS, 0, 0);
                                WriteFile( hStream, 'This is a stream', 17, dwRet, nil );
                                CloseHandle(hStream);
                                end;

                              Соотв. читается инфа из потока ф-цией ReadFile.
                              Т.е., по идее, нужно открыть один из потоков, созданных виндой при записи св-в, прочитать его и выудить оттуда нужную инфу.

                              Но в Win2K появилась ф-ция StgOpenStorageEx, которая сама всем этим занимается. Причем в ней можно задать флаги так, что она будет одинаково работать и с compound файлами (содержащими св-ва внутри себя) и с обычными файлами, св-ва которых находятся в отдельном потоке - винда сама определит, что за файл.

                              Короче пример в посте #5 я изменил - теперь он может читать св-ва как из compound, так и из обычных файлов (если, конечно у этих файлов есть набор св-в).
                                Krid, огромадное спасибо !!! [+] !!!!
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,1680 ]   [ 16 queries used ]   [ Generated: 11.03.25, 11:23 GMT ]