На главную
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила раздела "Наши Исходники"
Раздел предназначен для публикации различных исходников и программных решений (в виде исходных текстов), которые Вы считаете достойными внимания и/или интересными. Язык исходника значения не имеет. Это может быть C/C++, Pascal, Perl, PHP, C#, Foth, Prolog или любой другой существующий язык программирования. Единственный момент – в названии темы этот язык должен быть указан. Например, «[C++] Представление чисел в римской записи». Сам исходный текст должен содержаться в первом посте темы. Если исходник занимает не больше одного-двух экранов, то допустимо его публикация непосредственно в посте. Иначе исходный текст должен быть прикреплен к посту в виде архива. Кроме того, первый пост должен содержать:

- Информацию о платформе/компиляторе, для которых предназначен исходный текст (если эта информация существенна)
- Ссылку на оригинал и автора (если публикуется чужой исходный текст)
- Максимально подробное описание – какую задачу решает опубликованный исходный текст, и чем он интересен.

Плагиат крайне не приветствуется. Также не приветствуется публикация исходных текстов вирусов, крэков и т. п. информации. Это элементарно противозаконно.

Для быстрого поиска нужного исходника можно воспользоваться навигатором:
Быстрый поиск по разделу
Модераторы: Flex Ferrum
  
> [C++] Распаковка zip файла средствами Windows XP, WinAPI
    Вот пример распаковки файла readme.txt из архива file.zip , если в системе зарегистрирован zipfldr.dll

    ExpandedWrap disabled
               OleInitialize(NULL);
       
          char cInPath[]="c:\\file.zip\\readme.txt";
              char cOutPath[]="c:\\13";
          int nLen;
          BSTR bstrZip,bstrFol;
          HRESULT hres;
          long lCount;
       
           IShellDispatch *pSD = NULL;
           //Интерфейсы IID_Folder
           Folder* pZipFolder = NULL;
                Folder* pOutFolder = NULL;
           //Интерфейс IID_FolderItems
           FolderItems* pFolderItems = NULL;
       
           hres=CoCreateInstance(CLSID_Shell, NULL, CLSCTX_SERVER,IID_IShellDispatch, (LPVOID *) &pSD);
          
           if (SUCCEEDED(hres))
           {
               VARIANT vZipDir,vOutDir,vOptions;
              
               VariantInit(&vZipDir);
               vZipDir.vt = VT_BSTR;
               nLen = (lstrlen(cInPath) + 1) * sizeof(WCHAR);
               bstrZip = SysAllocStringByteLen(NULL,nLen);
              
               MultiByteToWideChar(CP_ACP,0,cInPath,-1,bstrZip,nLen);
               vZipDir.bstrVal = bstrZip;
          
               VariantInit(&vOutDir);
               vOutDir.vt = VT_BSTR;
               nLen = (lstrlen(cOutPath) + 1) * sizeof(WCHAR);
               bstrFol = SysAllocStringByteLen(NULL, nLen);
       
               MultiByteToWideChar(CP_ACP,0,cOutPath,-1,bstrFol,nLen);
               vOutDir.bstrVal = bstrFol;
              
               if (SUCCEEDED(pSD->NameSpace(vOutDir,&pOutFolder)))
               {  
                    //Мы можем получить количество файлов в ZIP папке
                    if (SUCCEEDED(pOutFolder->Items(&pFolderItems)))
                {
                 pFolderItems->get_Count(&lCount);
                }
                   //Опции
                   //4 Do not display a progress dialog box.  
                   //8 Give the file being operated on a new name in a move, copy, or rename operation if a file with the target name already exists.  
                   //16 Respond with "Yes to All" for any dialog box that is displayed.  
                   //64 Preserve undo information, if possible.
                   //128 Perform the operation on files only if a wildcard file name (*.*) is specified.  
                   //256 Display a progress dialog box but do not show the file names.  
                   //512 Do not confirm the creation of a new directory if the operation requires one to be created.  
                   //1024 Do not display a user interface if an error occurs.  
                   //2048 Version 4.71. Do not copy the security attributes of the file.
                   //4096 Only operate in the local directory. Don't operate recursively into subdirectories.
                   //9182 Version 5.0. Do not copy connected files as a group. Only copy the specified files.
       
                   VariantInit(&vOptions);
                   vOptions.vt=VT_I4;
                   vOptions.lVal=0;
              
                   hres=pOutFolder->CopyHere(vZipDir,vOptions);
       
                   pOutFolder->Release();
                  
                   VariantClear(&vOptions);
               }
              
               pSD->Release();
       
               //SysFreeString(bstrZip);
               VariantClear(&vZipDir);
          
               //SysFreeString(bstrFol);
               VariantClear(&vOutDir);
       
       
           }
    Сообщение отредактировано: Jenya -
    Фтп клиент для локальных сетей :
    Ftp_Manager
      А можно ли таким образом распаковывать отдельные файлы из вложенных в zip-архив папок?

      Upd: да, умеет :)
      надо только изменить направление слешей в пути после имени архива
      (ex: "c:\\test\\d.zip\\word/document.xml")

      Спасибо, интересная функция :)
      Сообщение отредактировано: brother_fox -
        Цитата Jenya @
        Вот пример распаковки файла readme.txt из архива file.zip , если в системе зарегистрированzipfldrdll


        Хороший, пример, но кроме него нигде не могу найти описания по работе с zipfldr.dll
        К примеру как получить список файлов в архиве, или распоковать весь архив
          Интерфейсы zipfldr.dll не документированы.

          Перечислить файлы достаточно просто, если учесть, что Windows воспринимает zip архив как папку.
          Я в своей программе Ftp_Man во встроенном проводнике даже принудительно отключил просмотр zip папок.
          Получить IShellFolder zip папки, вызвать EnumObjects - примеры в инете есть.
          Ну или парсить структуру zip архива, где-то в этом разделе вродебы был пример.

          Кстати перед распаковкой можно проверить регистрацию библиотеки zipfldr.dll проверив существование ключа реестра

          Цитата

          HKEY_CLASSES_ROOT\CLSID\{E88DCCE0-B7B3-11d1-A9F0-00AA0060FA31}


          На пример так :

          ExpandedWrap disabled
            BOOL IsZipSupportEnabled(void)
            {
               HKEY hkey;
               LONG lRes;
              
               lRes = RegOpenKey(HKEY_CLASSES_ROOT,"CLSID\\{E88DCCE0-B7B3-11d1-A9F0-00AA0060FA31}", &hkey);
               if( lRes == ERROR_SUCCESS && hKey )
                 return TRUE;
             
               return FALSE;    
            }
          Сообщение отредактировано: Jenya -
          Фтп клиент для локальных сетей :
          Ftp_Manager
            А можно так распаковать файл 1.txt в архиве 1.Zip? CopyFile("C:\\1.zip\\1.txt" , "C:\\2.txt" , false); - или как-то по-другому?
              Цитата Iliaistar @
              А можно так распаковать файл 1.txt в архиве 1.Zip? CopyFile("C:\\1.zip\\1.txt" , "C:\\2.txt" , false); - или как-то по-другому?

              с помощью LZCopy?
                LZCopy непонятно как работает, просто копирует...
                  Цитата Iliaistar @
                  LZCopy непонятно как работает, просто копирует...


                  Я на практике тоже не понял как оно действует, копировать копирует, по инструкции если исходный файл был сжат то он при копировании будет разархивирован, вроде так, но что-то не получается) А может потому что нельзя натравливать LZCopy на ZIP архивы вот ссылка
                  Т.е. оно так и работает если исходный файл не сжат по LZ то он сжимается при копировании, если был сжат то разархивируется, но это вся относится к LZ, по крайней мере ZIP архивы созданные в WinRAR не распаковываются.

                  Добавлено
                  Цитата Jenya @
                  Получить IShellFolder zip папки, вызвать EnumObjects


                  Все хорошо, но у меня не получается получить IShellFolder от зип файла(

                  ExpandedWrap disabled
                    ...
                    mbstowcs( wpath, "C:\\test.zip", MAX_PATH ); // ANSI to UNICODE
                    wpath[ MAX_PATH - 1 ] = 0;
                    hr = pDesk->ParseDisplayName( NULL, 0, wpath, NULL, &pidl, &fa );
                    hr = pDesk->BindToObject( pidl, NULL, IID_IShellFolder, (void**)&pFolder ); // тут возвращает код ошибки
                    ...



                  а парсить зип файл не хотелось бы)
                  Сообщение отредактировано: VSV -
                    ExpandedWrap disabled
                      //Получаем PIDL и IShellFolder из пути
                      BOOL GetItemIdListFromPath(LPCSTR lpszPath, LPITEMIDLIST *lpItemIdList,IShellFolder **pCurFolder)
                      {
                          LPSHELLFOLDER pShellFolder = NULL;
                          HRESULT         hr = E_FAIL;
                          ULONG         chUsed;
                          WCHAR         wcPath[MAX_PATH];
                       
                               if (!lpszPath)
                              return FALSE;
                       
                          //Получаем IShellFolder интерфейс для рабочего стола
                          if (SHGetDesktopFolder(&pShellFolder) != NOERROR)
                              return FALSE;
                              
                          //Конвертируем строку в UNICODE
                          MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,lpszPath,-1,wcPath,ARRAYSIZE(wcPath));
                       
                          //Конвертируем  путь в ITEMIDLIST
                               if (SUCCEEDED(pShellFolder->ParseDisplayName(NULL,NULL,wcPath,&chUsed,lpItemIdList,NULL)))
                          {
                              //Получаем указатель на IShellFolder для папки
                              hr = pShellFolder->BindToObject(*lpItemIdList,NULL,IID_IShellFolder,(LPVOID*)pCurFolder);
                          }
                       
                          pShellFolder->Release();
                          
                          if SUCCEEDED(hr)
                              return TRUE;
                          else
                              return FALSE;
                      }
                    Фтп клиент для локальных сетей :
                    Ftp_Manager
                      Цитата Jenya @
                      //Получаем PIDL и IShellFolder из пути
                      BOOL GetItemIdListFromPath(LPCSTR lpszPath, LPITEMIDLIST *lpItemIdList,IShellFolder **pCurFolder)


                      Попробывал, по сути у меня также и было и также вроде не работает с ZIP папками, в строке выскакивает ошибка
                      Цитата Jenya @
                      ExpandedWrap disabled
                        hr = pShellFolder->BindToObject(*lpItemIdList,NULL,IID_IShellFolder,(LPVOID*)pCurFolder);


                      первый параметр можно же так задавать - "C:\\test.zip"?

                      получилось так - (Borland® C++Builder® for Microsoft® Windows™ Version 10.0.2288.42451 Update 2)
                      ExpandedWrap disabled
                        //---------------------------------------------------------------------------
                         
                        #define NO_WIN32_LEAN_AND_MEAN
                        #include <vcl.h>
                        #pragma hdrstop
                         
                        #pragma argsused
                        #pragma   link   "shell32.lib"
                        #pragma   link   "shlwapi.lib"
                         
                         
                        #include <shlobj.h>
                        #include <shlwapi.h>
                        #include <iostream.h>
                         
                        //---------------------------------------------------------------------------
                         
                        #pragma argsused
                        int main(int argc, char* argv[])
                        {
                        CoInitialize(NULL);
                         
                        IShellFolder *psfZip;
                         
                        IShellFolder *psfParent;  
                          
                        LPITEMIDLIST  pidl = ::ILCreateFromPath( "C:\\New.zip" );  
                          
                        if ( pidl )  
                         
                        {  
                          
                        LPCITEMIDLIST pidlChild = NULL;  
                          
                        HRESULT hr = SHBindToParent( pidl, IID_IShellFolder,  
                         
                        (void**)&psfParent, &pidlChild );  
                          
                        if ( SUCCEEDED( hr ) )  
                          
                        {  
                         
                        hr = psfParent->BindToObject( pidlChild, NULL, IID_IShellFolder,(void**)&psfZip );
                         
                        LPENUMIDLIST ppenum = NULL;
                        LPITEMIDLIST pidlItems = NULL;
                        ULONG celtFetched;
                        STRRET strDispName;
                        TCHAR pszDisplayName[MAX_PATH];
                         
                        hr = psfZip->EnumObjects(NULL,SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &ppenum);
                         
                            while( hr = ppenum->Next(1,&pidlItems, &celtFetched) == S_OK && (celtFetched) == 1)
                            {
                                psfZip->GetDisplayNameOf(pidlItems, SHGDN_INFOLDER, &strDispName);
                                StrRetToBuf(&strDispName, pidlItems, pszDisplayName, MAX_PATH);
                                cout << pszDisplayName << '\n';
                            }
                         
                        psfParent->Release();
                         
                        }
                         
                        }
                            return 0;
                        }
                      Сообщение отредактировано: VSV -
                        Цитата Jenya @
                        Вот пример распаковки файла readme.txt из архива file.zip , если в системе зарегистрирован zipfldr.dll


                        А запаковать удавалось? Вроде Вы писали что можно, мне не удалось, сделал пустой ZIP файл, но увы хоть и без ошибок но копирования не происходит
                        ExpandedWrap disabled
                          hres=pOutFolder->CopyHere(vZipDir,vOptions);


                        параметры задаю так
                        ExpandedWrap disabled
                          char cInPath[]="c:\\readme.txt";
                          char cOutPath[]="c:\\New.zip\\";


                        в обычную же папку копирование файла удается
                        ExpandedWrap disabled
                          char cInPath[]="c:\\readme.txt";
                          char cOutPath[]="c:\\New\\";
                          Там нужно не в совсем пустой а уже с заголовком. Только 4 или 2 символа заголовка брать нужно, я не помню точно, вроде бы 4 : попробуй и отпишись. "PK" + '\x03' + '\x04'
                          Сообщение отредактировано: Jenya -
                          Фтп клиент для локальных сетей :
                          Ftp_Manager
                            Помогла задержка)
                            Т.е. я создал пустую ZIP папку ничего не правя и добавил задержку после
                            ExpandedWrap disabled
                              hres=pOutFolder->CopyHere(vZipDir,vOptions);


                            файл был скопирован в архив)

                            Еще бы какнить научиться создавать пустую ZIP папку через винду, хотя и "рускачками несложно") и задержку грамотней оформить, т.е. дожидаться когда закончиться поток копирования, последнее как то более туманно)
                              Попробуй всё таки не пустую. Задержка не есть хорошо.
                              Сообщение отредактировано: Jenya -
                              Фтп клиент для локальных сетей :
                              Ftp_Manager
                                Цитата Jenya @
                                Там нужно не в совсем пустой а уже с заголовком. Только 4 или 2 символа заголовка брать нужно, я не помню точно, вроде бы 4 : попробуй и отпишись. "PK" + '\x03' + '\x04'


                                Цитата Jenya @
                                Попробуй всё таки не пустую. Задержка не есть хорошо.


                                Я если чесно так и не понял, что подразумевается под пустым?

                                Цитата Jenya @
                                "PK" + '\x03' + '\x04'


                                у меня так - user posted image
                                вот ссылка на картинку ссылка на картинку

                                Добавлено
                                Вот кстати обсуждение про аналогичный случай - тут
                                Сообщение отредактировано: VSV -
                                  Под пустым подразумевается файл из одного заголовка из 4-х байтов.
                                  Сообщение отредактировано: Jenya -
                                  Фтп клиент для локальных сетей :
                                  Ftp_Manager
                                    Цитата Jenya @
                                    Под пустым подразумевается файл из одного заголовка из 4-х байтов.

                                    Цитата Jenya @
                                    "PK" + '\x03' + '\x04'


                                    Пробовал так, но не помогло
                                    ExpandedWrap disabled
                                      fstream zip_file("C:\\New2.zip", ios::out);
                                      char buff_line[10]="";
                                      sprintf(buff_line, "PK%c%c\n", '\x03', '\x04');
                                      zip_file.write(buff_line,lstrlen(buff_line));
                                      if(zip_file.is_open() == 0) return 0;
                                      zip_file.close();


                                    при копировании в архив пишет что архив поврежден, или имеет не правильный формат

                                    вверху я приводил ссылку на заголовок и символы в пустом ZIP архиве создаваемом Windows, либо WinRAR заголовок должен отличаться от этого?
                                      тут вот тоже пишут о задержки, хоть и для шарпа

                                      Ziping a file using the Windows Shell API creates another thread where the zipping is executed.This means that it is possible that this console app would end before the zipping thread starts to execute which would cause the zip to never occur and you will end up with just an empty zip file. So wait a second and give the zipping thread time to get started
                                      Сообщение отредактировано: VSV -
                                        можно ли через WaitForExit подождать?
                                          Для WaitFor нужен хэндл обьекта.
                                          Фтп клиент для локальных сетей :
                                          Ftp_Manager
                                            А как тогда можно дождаться завершения?
                                              Оказывается при копировании файла тут
                                              ExpandedWrap disabled
                                                pOutFolder->Release();

                                              происходит задержка, в принципе можно довольствоваться этим)
                                                Посмотри вот здесь :

                                                http://www.autohotkey.com/forum/topic19789.html+dll

                                                Тут вроде тайм-аута нету.
                                                Фтп клиент для локальных сетей :
                                                Ftp_Manager
                                                  Обнаружилась такая проблемка при многократном перезапуске извлечения для одного архива, либо при распаковывании архива в котором больше 100 файлов вылетает окошко - Файл существует
                                                  Причина - в папке C:\Documents and Settings\{USER_NAME}\Local Settings\Temp генерируются для каждого файла папки с именами Временная папка {НОМЕР} для {ИМЯ_АРХИВА}.zip
                                                  Когда НОМЕР становится больше 99 то начинает выскакивать это окошко и разархивирования не происходит

                                                  видимо надо чистить эти папки ручками) Но судя по тому что для копирования запускается несколько потоков для нескольких файлов - если судить по выскакивающим окошкам копирования, то это становиться не слишком тривиально, т.к. есть вероятность затереть еще не скопированный файл, хотя не знаю))) может и не так


                                                  Еще вопрос - при извлечении выскакивает окошко копирования файлов с кнопкой отмены, которую может нажать юзер, как то не показывать это окошко можно?
                                                  Сообщение отредактировано: VSV -
                                                    Цитата

                                                    Folder.CopyHere(vItem [, vOptions])
                                                    Parameters

                                                    vItem Required. The item or items to copy. This can be a string that represents a file name, a FolderItem object, or a FolderItems object.
                                                    vOptions Optional. Options for the copy operation. This value can be zero or a combination of the following values. These values are based upon flags defined for use with the fFlags member of the C++ SHFILEOPSTRUCT structure. These flags are not defined as such for Microsoft Visual Basic, Visual Basic Scripting Edition (VBScript), or Microsoft JScript, so you must define them yourself or use their numeric equivalents.4 Do not display a progress dialog box.
                                                    8 Give the file being operated on a new name in a move, copy, or rename operation if a file with the target name already exists.
                                                    16 Respond with "Yes to All" for any dialog box that is displayed.
                                                    64 Preserve undo information, if possible.
                                                    128 Perform the operation on files only if a wildcard file name (*.*) is specified.
                                                    256 Display a progress dialog box but do not show the file names.
                                                    512 Do not confirm the creation of a new directory if the operation requires one to be created.
                                                    1024 Do not display a user interface if an error occurs.
                                                    2048 Version 4.71. Do not copy the security attributes of the file.
                                                    4096 Only operate in the local directory. Don't operate recursively into subdirectories.
                                                    9182 Version 5.0. Do not copy connected files as a group. Only copy the specified files.


                                                    Наводит на мысль, что в основе CopyHere лежит SHFileOperation, однако работать с помощью SHFileOperation с виртуальными zip папками нельзя.


                                                    Кстати вот так создается пустой zip файл в примере : http://www.robvanderwoude.com/vbstech_files_zip.html
                                                    Там кстати Sleep 200 делается.

                                                    Цитата

                                                    ' Create an empty ZIP file
                                                    Set objFSO = CreateObject( "Scripting.FileSystemObject" )
                                                    Set objTxt = objFSO.OpenTextFile( myZipFile, ForWriting, True )
                                                    objTxt.Write "PK" & Chr(5) & Chr(6) & String( 18, Chr(0) )
                                                    objTxt.Close
                                                    Set objTxt = Nothing
                                                    Set objFSO = Nothing
                                                    Сообщение отредактировано: Jenya -
                                                    Фтп клиент для локальных сетей :
                                                    Ftp_Manager
                                                      Цитата Jenya @
                                                      Кстати вот так создается пустой zip файл в примере : http://www.robvanderwoude.com/vbstech_files_zip.html

                                                      У меня так вот получилось
                                                      ExpandedWrap disabled
                                                          FILE * f1;
                                                          f1 = fopen("C:\\New.zip", "wb");
                                                          char buff_line[22]="";
                                                          sprintf(buff_line, "PK\x5\x6");
                                                          int n = 1;
                                                          fwrite(buff_line, sizeof(buff_line), n, f1);
                                                          fclose(f1);
                                                        Цитата

                                                        Обнаружилась такая проблемка при многократном перезапуске извлечения для одного архива, либо при распаковывании архива в котором больше 100 файлов вылетает окошко - Файл существует
                                                        Причина - в папке C:\Documents and Settings\{USER_NAME}\Local Settings\Temp генерируются для каждого файла папки с именами Временная папка {НОМЕР} для {ИМЯ_АРХИВА}.zip
                                                        Когда НОМЕР становится больше 99 то начинает выскакивать это окошко и разархивирования не происходит


                                                        Решилась проблема? Отпишите, пожалуйста. У меня как раз случай "многократного перезапуска" :o
                                                          Удалять временные файлы.
                                                          Фтп клиент для локальных сетей :
                                                          Ftp_Manager
                                                            Извините за некропост, но решение проблемы не нашел.
                                                            Как распаковать ВСЕ файлы из архива?
                                                            0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                                            0 пользователей:


                                                            Рейтинг@Mail.ru
                                                            [ Script Execution time: 0,2308 ]   [ 17 queries used ]   [ Generated: 6.12.19, 18:52 GMT ]