Как можно сделать обновление?
Можно простым копированием готовых файлов, с последующим контролем параметров (контрольной суммы, версии, даты и пр.). Но, это «грузит» сеть, лучший вариант – передавать информацию в сжатом виде, и распаковывать её «на месте». Кроме того, эта ситуация заставит пользователей (или Вас) делать операцию копирования (подмены) и настройки (перенастройки) ПО вручную. А здесь возможны ошибки. Способ хорош только в самых простых случаях.
Идеально будет иметь свой собственный сервис обновлений, который будет определять: что и как копировать, контролировать и исправлять. Это серьёзно и надёжно (если правильно написано). Только, многие ли осилят это произведение? А нужны ли сложности, когда можно обойтись простым?
Проще написать свой (или использовать готовый) модуль, который будет запускаться при обновлении, и получать его в виде исполняемых файлов (инсталляционных или апдейт-программ). Или не писать его, а получать эти исполняемые обновления, например, по почте. Вполне гибко. Недостаток: всегда копируется (скачивается) дополнительный объём информации, связанный с сопутствующими алгоритмами сжатия-разжатия данных. А если хочется передавать только сжатые файлы и скрипты настройки (или изменения) программы?
Что ж, упаковщики-распаковщики можно выделить и заранее зарегистрировать у пользователей или просто положить нужные .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
На рубль работы, на два
На рубль работы, на два похвальбы.