Статья: Обновление приложений в MS Visual FoxPro Часть 1
В этой статье :
  • Для чего написана эта статья.
  • Введение.
  • Как в идеале надо обновлять приложения.
  • Как это работает.
  • .
  • Для чего написана эта статья.

    Почему я решил написать статью - да просто прочитал рекламный листок одной большой компании, как она внедрила один крупный проект в гостиничном бизненсе и это автообновление позволило сократить много инженеров поддержки, которые занимались только Upgrade на новые версии старой системы... Хорошие деньги за такую простую функцию программы!... Но в FoxPro такая возможность уже существует много лет и мы ее не используем из-за собсвенной лени. Причем самообновление даже через интернет позволит профессионально напоминать нашим клиентам - что мы, хоть и не такие большие как Microsoft, но заботимся о наших клиентах, думаем о них и развиваем систему. Кроме того подобный подход упрощает разработку - получил задание по e-mail, выполнил работу, опубликовал на своем или клиента Web Server, а на утро его сотня - тысяча клиентов скачали новое обновление. Круто! Уровень сервиса как и в системе за 1 миллион долларов.

    Думаю, что я не открою секрет, что подобная проблема стояла перед многими из нас, кто связан с практической разработкой программного обеспечения. И не важно - работаешь ты в крупной "программерской конторе" пишущей для крупных заказчиков или разрабатываешь приложение для "под заказ" для небольших клиентов с минимальными ресурсами. Каждый решал эту проблему по-своему. Путей решения много. Автор этой статьи пытался решить данную проблему несколькими методами. Но после нескольких методов изыскания и поиска нашел очень интересное решение, преложенное Rick Strahl и выложенное на сайте компании West Wind Technologies в свободном доступе.  Изучив преложенный материал я понял, что это именно то, что мне нужно и лучше уже просто написать невозможно. Так что моя данная статья будет неким кратким вольным переводом с английского с некоторым облегчением кода и разработкой реального примера.  Для тех же, кто знаком с английским языком сразу отсылаю к оригиналу. Мной было получено разрешение на все вышеописанные действия от Рика, за что я ему выражаю признательность и благодарность за создание прекрасных продуктов на основе и для FoxPro - особенно Web Connection который "затыкает" по скорости и удобству создания Web приложений многие известные аналоги.

    Введение.

    Обновление установленных и работающих приложений не является для большинства нас как разработчиков приоритетной задачей. Обновление программ, особенно находящихся в разных местах является не простым заданием. Если Вы сталкивались в своей практике с разработкой и установкой программ для клиентов с тысячью и более пользователей и найдя крошечный, но критически важный баг, Вы аероятнее всего знакомы с исчезающим чувством пустоты в Вашем желудке в тщетных попытках найти всех этих пользователей и известить, что в программе ощибка но Вы уже ее исправили и можете предоставить им улучшенную версию.

    Обновление программ связано с решением многих вопросов. Прежде всего Вам необходимо разработать способ передачи обновления пользователю. Кроме того надо придумать как проверять наличие новых версий и как собственно устанавливать обновления на клиентские машины. Очень редко обновление требует от нас замену только одного выполняемого EXE модуля основной программы, но очень часто это затрагивает дополнительные файлы и что наиболее существенно - требуется вносить изменения в структуру данных баз на стороне клиента.

    В данной статье мы сфокусируем Ваше внимание как на практике провести процесс проверки наличия новой версии и собственно обновления приложения через Интернет (Интранет, далее для простоты написания я буду упускать змечание на то, что вся информация будет каксаться и внутренних компьютерных сетей) а так же связанных с данной тематикой некоторых сопутствующих проблем. В дальнейшем будет представлен класс, разработанный Rick Strahl который берет на себя всю черновую работу по проверке обновлений on-line, затем прием новой версии с Web Site используя протокол HTTP и обновление любого количества файлов, входящих в приложение.

    Как в идеале надо обновлять приложения.

    Перед тем как углубиться в детальное изучение работы класса wwCodeUpdate, давайте кратко рассмотрим процессы, участвующие в обновлении данных через Интернет. Для наших пользователей внутри наших приложений мы должны выполнить следующие задачи процесса обновления:

    • Проверить наличие новой версии у источника обновления путем сравнения online версии с текущей локальной версией на клиенте
    • Принять файл обновления на локальную машину через Интернет
    • Обновить запущенный EXE модуль а так-же остальные файлы из принятой новой версии
    • Перезапустить оригинальное приложение
    • Запустить любые после обновления приложения операции, например, изменение структуры таблиц данных и т.д.

    На первый взгляд описанный процесс выглядит простым, но за этой простотой скрывается довольно большой объем работ и внешнее приложение, призванные осуществить задуманное нами. Типичный сценарий работы программы обычно выглядит примерно так: Приложение стартует и как часть процесса загрузки приложения происходит проверка номера последней достуаной версии данной программы через Web путем чтения XML файла, который содержит номер последней версии и так-же дополнительной информации об обновляемом файле (URL, размер файла обновления, сообщение Вашему пользователю). Эта информация в части номера последней версии сравнивается с текущим номером локальной версии, используемой клиентом. Если версия, доступная OnLine более свежая, чем используемая клиентом - выдается сообщение с предложением принять обновление. После подверждения клиентом программа скачивает обновление из Web, используя URL, извлеченного  из принятого XML файла в начале данной операции и сохраненный в специальном локальном директории клиента.

    В этой точке процесса запущенное приложение должно завершить свою работу и запустить другое приложение, которое обновит исполняемый модуль и снова запустит его. Это требуется по той причине, что запущенный EXE файл заблокирован в процессе выполнения и не может быть перезаписан. Таким образом, текущее приложение закрывается и стартует программа обновления приложения. Данная программа обновления берет на себя замену оригинального выполняемого EXE файла путем разархивирования обновленных файлов в специальный директорий и последующая замена программного EXE файла а так-же всех дополнительных файлов, которые необходимы для работы Вашего приложения. Эта-же программа запускает снова оригинальное приложение, которое в момент нового старта будет уже иметь последний номер версии и пройдет без обновления очередное сравнение номера версии, записанного в XML файле на Web сервере обновлений.

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

    Как это работает.

    Класс wwCodeUpdate берет на себя большую часть процесса обновления со всего несколькими свойствами и простыми методами. Путем назначения свойств данного класса мы определяем где обновление должно выполняться и к каким файлам обращться на Web и где их так-же устанавливать. В дополнение наш класс использует XML файл на сервере как источник версии и указатель какой файл надо загружать с сервера, что делает возможным иметь для обновления несколько версий одновременно (например многоступенчатое обновление для очень старых версий Вашей программы).

    Перед тем, как мы окунемся в детальное изучение работы класса, давайте рассморим схематичный код в Lising 1, использующий класс wwCodeUpdate внутри клиентского приложения для проверки наличия новой версии и установки последней.

    Listing 1

    * SampleAppForm :: CheckForNewVersion() LOCAL loUpdate, loAPI, lcURL, lnVersion *** Запрашиваем URL который бедем в дальнейшем использовать для проверки версии *** Например: http://www.sergey.couk/ww_update/orders_update.xml loAPI= CREATEOBJECT("wwAPI") lcUrl = loAPI.GetProfileString(FULLPATH("wwReader.ini"),"Main","VersionUpdateUrl") loUpdate= CREATEOBJECT("wwCodeUpdate") ***Url где проверять наличие свежей версии (XML файл) loUpdate.cVersionUrl = lcUrl loUpdate.cVersionType = "N" && Numeric Type *** имя файла приложения для горячей замены loUpdate.cExeFile ="orders.exe" *** Возврат текущей доступной версии из XML файла *** Установка свойств loUpdate object из XML lnVersion = loUpdate.GetVersionInfo() *** Если мы не можем получить номер версии с Web Server  IF lnVersion = 0 *** Не можем получить информацию о версии программы - выйти *** Мы так-же можем показать ошибку: loUpdate.cErrorMsg RETURN ENDIF *** Сравнить номер версии с *** номером версии приложения - здесь свойство формы *** Обычно используется .H установка, поле таблицы или объект конфигурации IF lnVersion > THISFORM.nVersion *** Покажем сообщение и предложим скачать обновление IF MessageBox(loUpdate.cUserMessage + CHR(13) + CHR(13) +; "Вы не желаете скачать и уствновить обновление программы? (" ; LTRIM(TRANSFORM(loUpdate.nFileSize,"999,999,999")) + ; "kb)",32+4,"Фирма Рога и Копыта")= 6 IF !loUpdate.DownloadUpdate() MessageBox(loUpdate.cErrorMsg,48,"Download Error") ELSE *** Закрываем программу VFP CLEAR EVENTS RELEASE THISFORM ***  Запускаем CodeUpdate Exe и завершаем программу loUpdate.RunUpdateExe(; [WSCRIPT CodeUpdate.vbs "orders.exe" "] + ; SYS(5) + CURDIR() +; [codeupdate\wwReader_Update.exe /auto ] + ; SYS(5) + CURDIR() + [" ] + ; ["Фирма Рога и Копыта"]) ENDIF ENDIF ENDIF RETURN

    Приведенный выше код начинается с создания wwCodeUpdate класса и получения URL для проверки необходимости обновления из INI файла. Это значение может поступить откуда угодно - DBF таблицы конфигурации, регистра, XML файла и т.д. - но мы предпочтем управлять этим значением наиболее простым способом, так что будет возможно  изменить место нахождения файла для различных версий или в период тестирования на локальном сервере. Этот URL указывает на XML файл, размещенный на Web сервере и содержит информацию о последней доступоной версии программы, как это показано в Listing 2. 
    Listing 2
    <?xml version = "1.0"?>
    <codeupdate>
        <version>1.001</VERSION>
        <usermessage>Новая версия 1.001 готова для обновления</usermessage>
        <fileurl>http://www.sergey.couk/ww_update/orders_update.exe</fileurl>
        <size>372</size> 
    </codeupdate>
        
    Метод GetVersionInfo() загружает этот XML файл и присваивает значения полученные из него некоторым свойствам класса. Вам необходимо установить следующие свойства класса до вызова этого метода: