Вы здесь

Создать свой сервис обновления: распаковка сжатых данных

Cabinet
Как можно сделать обновление?
 
Можно простым копированием готовых файлов, с последующим контролем параметров (контрольной суммы, версии, даты и пр.). Но, это «грузит» сеть, лучший вариант – передавать информацию в сжатом виде, и распаковывать её «на месте». Кроме того, эта ситуация заставит пользователей (или Вас) делать операцию копирования (подмены) и настройки (перенастройки) ПО вручную. А здесь возможны ошибки. Способ хорош только в самых простых случаях.
 
Идеально будет иметь свой собственный сервис обновлений, который будет определять: что и как копировать, контролировать и исправлять. Это серьёзно и надёжно (если правильно написано). Только, многие ли осилят это произведение? А нужны ли сложности, когда можно обойтись простым?
 
 
Проще написать свой (или использовать готовый) модуль, который будет запускаться при обновлении, и получать его в виде исполняемых файлов (инсталляционных или апдейт-программ). Или не писать его, а получать эти исполняемые обновления, например, по почте. Вполне гибко. Недостаток: всегда копируется (скачивается) дополнительный объём информации, связанный с сопутствующими алгоритмами сжатия-разжатия данных. А если хочется передавать только сжатые файлы и скрипты настройки (или изменения) программы?
 
Что ж, упаковщики-распаковщики можно выделить и заранее зарегистрировать у пользователей или просто положить нужные .dll, .exe-файлы в соответствующие каталоги. Этот даст возможность отсылать (получать) не исполняемые файлы, а только архивы. Хороший вариант. Недостаток: изначальная инсталляционная (установочная) программа должна содержать нужные архиваторы и никто не отменяет ситуации, что пользователь что-то нарушит – удалит. Хотя, от этого никто не застрахован…
 
Можно ли как-то ещё минимизировать? Можно. Воспользоваться встроенными средствами самого Windows. Он же имеет собственные средства обновления и работы с архивами? Имеет. Значит, к ним можно «присосаться».
 
В наличии у нас 3 (три) .dll-ки с API-функциями, позволяющие работать с cabinet-файлами: Cabinet.dll, ZipFldr.dll и SetupAPI.dll. Мои комментарии к ним:
 
  • Cabinet.dll – описана в MSDN, но работать с ней у меня не получилось (толи руки «кривые», толи Майкрософт «накосячил»).
  • ZipFldr.dll – появилась в WinXP, позволяет работать и с .zip-архивами(!), недокументированна, поэтому лучше работать с ней, используя COM-класс. Недостаток: с ней связан сервис, который пользователи могут отключать.
  • SetupAPI.dll – всегда есть, хорошо документирована, имеет ANSI и Unicode-функции.
 
Утомлять не буду. Вот мой пример реализации распаковки .cab-файла для пишущих на CA-Visual Objects:
 
// Распаковываем файл "test.cab" в папку "\\192.168.0.100\tmp2\"
CabinetExtract( String2Psz( "C:\test.cab" ), String2Psz( "\\192.168.0.100\tmp2\" ) )
 
 
FUNCTION CabinetExtract( pszCabFile AS PSZ, pszTargetPath AS PSZ ) AS LOGIC PASCAL
      // Description: Функция распаковки cabinet-файла (*.cab)
      // Parameters :
            // pszCabFile      - имя cabinet-файла
            // pszTargetPath - путь для распаковки (в конце обязательна наклонная черта)
      // Returns    : LOGIC
 
      LOCAL lSuccess AS LOGIC
 
      pszgTargetPath := pszTargetPath
      lSuccess := SetupIterateCabinet( pszCabFile, 0, @CabinetCallback(), NULL_PTR )
      pszgTargetPath := NULL_PSZ
      RETURN lSuccess
 
STATIC GLOBAL pszgTargetPath AS PSZ
 
_DLL FUNC SetupIterateCabinet( CabinetFile AS PSZ    ,;
                                                 Reserved   AS DWORD,;
                                                 MsgHandler AS PTR     ,;
                                                 Context     AS PTR ) AS LOGIC PASCAL:Setupapi.SetupIterateCabinetA
 
 
 
STATIC FUNCTION CabinetCallback( Context              AS PTR                 ,;
                                                       Notification AS DWORD        ,;
                                                       Param1             AS DWORD PTR      ,;
                                                       Param2             AS DWORD PTR) AS DWORD CALLBACK
      LOCAL wRetVal AS DWORD
      LOCAL strInfo AS FILE_IN_CABINET_INFO
      LOCAL wLen AS DWORD
 
wRetVal := NO_ERROR
      DO CASE
      CASE Notification = SPFILENOTIFY_FILEINCABINET // A file is encountered in the cabinet.
 
            strInfo := Param1
            MemSet( @strInfo.FullTargetName[ 1 ], 0, MAX_PATH )
 
            // Складываем путь и имя файла => полный путь распаковки
            wLen := PszLen( pszgTargetPath )
            IF wLen > 0
                  MemCopy( @strInfo.FullTargetName[ 1 ], pszgTargetPath, wLen )
            ENDIF
            MemCopy( @strInfo.FullTargetName[ wLen + 1 ], strInfo.NameInCabinet, PszLen( strInfo.NameInCabinet ) )
 
            wRetVal := FILEOP_DOIT // Extract the current file.
 
      CASE Notification = SPFILENOTIFY_FILEEXTRACTED // The file has been extracted from the cabinet.
 
            wRetVal := NO_ERROR
 
      CASE Notification = SPFILENOTIFY_NEEDNEWCABINET // The current file is continued in the next cabinet.
 
            wRetVal := NO_ERROR
 
      OTHERWISE
      END CASE
 
      RETURN wRetVal
 
DEFINE SPFILENOTIFY_FILEINCABINET := 0x00000011
DEFINE SPFILENOTIFY_NEEDNEWCABINET := 0x00000012
DEFINE SPFILENOTIFY_FILEEXTRACTED := 0x00000013
DEFINE FILEOP_DOIT := 1
 
STRUCTURE FILE_IN_CABINET_INFO
 
      MEMBER NameInCabinet AS PSZ
      MEMBER FileSize         AS DWORD
      MEMBER Win32Error       AS DWORD
      MEMBER DosDate          AS WORD
      MEMBER DosTime          AS WORD
      MEMBER DosAttribs       AS WORD
 
      MEMBER DIM FullTargetName[ MAX_PATH ] AS BYTE
 
 
 
 
Пока ставлю точку. Думаю, несколько позже продолжить тему вопросов о создании своего сервиса обновления программного обеспечения. А пока, всем пока, всем счастливо!
 
 
27.10.2013 г.      Карандаш. 
 

Комментарии

Your mustang-soft.com - considerable resource

На рубль работы, на два похвальбы.

Theme by Danetsoft and Danang Probo Sayekti inspired by Maksimer