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

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

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

Для быстрого поиска нужного исходника можно воспользоваться навигатором:
Быстрый поиск по разделу
Модераторы: Flex Ferrum
Страницы: (2) [1] 2  все  ( Перейти к последнему сообщению )  
> [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 -
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script Execution time: 0,1704 ]   [ 17 queries used ]   [ Generated: 27.06.19, 04:15 GMT ]