...

суббота, 22 марта 2014 г.

15 проблем, возникающих при интеграции протектора в Windows-приложение

Данная статья может быть интересна тем, кто занимается написанием какого-либо прикладного ПО и собирается выпустить дистрибутив своего ПО в большой мир.

Данная статья скорее всего будет малополезна матерым системным програмистам под Windows, а также тем, кто уже съел не одну собаку при создании дистрибутивов ПО.


Данная статья скорее всего будет не слишком интересна системным администраторам, но у них, возможно, найдётся, что добавить.


Также данная статья только ставит вопросы, не давая ответов, так что не ищите их в ней.


Если у кого-то все же осталось желание узнать немного больше о предмете разговора, добро пожаловать под кат.



В один прекрасные день я проснулся, и понял, что так жить больше нельзя. Мое приложение качают, устанавливают, и… И все! Не покупают! Я не слишком долго размышлял над причиной — я давно предполагал, что когда-нибудь так и будет, потому что у меня фактически не было защиты — как многие начинающие шароварщики, я решил, что все сделаю сам, и сделал систему защиты на основе ассиметричного шифрования; но под конец, когда первые «защищенные» моей защитой версии стали покупать, мне стало лень доделывать проверку подписи в программе — это надо было еще разбираться с какой-либо криптографической библиотекой для C++, и я оставил, как есть. Покупают же!

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


Протектор — наше всё




Надо покупать протектор от стороннего производителя, который профессионально занимается этим вопросом. С этим фактом было трудно поспорить, и я стал листать интернет в поискать наиболее дешевого и в тоже время функционального варианта. К слову сказать, мне не попадалось хороших обзоров рынка протекторов (и я постарался исправить это в предыдущем посте), и во многом приходилось полагаться на мнение «очевидцев», использующих тот или иной протектор. Также, о некоторых протекторах тогда я так и не узнал, пока не засел за вышеуказанную статью. В результате основными критериеми выбора были: «живость» протектора, наличие живой и бодрой службы поддержки, которая оперативно отвечает на самые дурацкие вопросы, и цена полного комплекта со всем «фаршем».

Пару слов о «фарше»




Под «фаршем» я подразумеваю дополнительные функции, которые облегчают использование протектора и продажу ПО, защищенного им: консольные утилиты для пакетной обработки приложений (в т.ч. чтобы можно было настроить и post-build step); сервер активации, который желательно ставится на любой хостинг; генератор лицензий, который также можно захостить на любом хостинге и отдавать регистритору ссылку на него. Также к «фаршу» можно отнести и поддержку x64-приложений — я был свято уверен, что наравне с x86-версиями я буду предоставлять и x64-версии.

Выбор сделан




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

Еще 30 тыщ ведер и золотой ключик у нас в кармане




Есть еще один небольшой нюанс при выборе протектора — есть ли у него и насколько в него интегрированы сервисы лицензирования — напоминания о демо/триале, диалоги активации, берёт ли протектор на себя заботу о хранении ключей на компьютере пользователя, и тому подобные мелочи. Как оказалось, у выбранного мной протектора таких возможностей мало (есть настраиваевые сообщения об обнаружении отладчика и виртуальной машины, и все). Этот вопрос может являться в некоторых случаях ключевым; и если бы я обратил на него внимание до выбора протектора, то возможно (но не факт) мой выбор был бы другим.

Также стоит обратить внимание на то, есть ли у протектора и насколько вас устраивают встроенные диалоги и процедуры и можно ли их обойти и заменить своими процедурами активации и отображаемыми диалогами.


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


Так или иначе, я стал счастливым обладателем протектора, и начал прикручивать его к своей программе.


Дальнейшая повесть, собственно, и рассказывает о некоторых проблемах, с которыми и я столкнулся в процессе этого прикручивания. Как оказалось, есть нюансы, особенно если вы хотите поддерживать все ОС от Windows 2000 до Windows 8.1.


Данная часть рассказывает о проблемах честного программиста, который хочет максимально корректно обращаться с системой при активации и проверке подлинности своего ПО.

Проблема 1 — хранение регистрационной информации на компьютере пользователя




Как оказалось, правильно хранить регистрационные данные пользователя на компьютерах под управлением современных систем Windows не так и просто. Данные можно сохранять без проблем лишь в том случае, если активация производится только для текущего пользователя. Если пытаться активировать программу для всех пользователей (что более чем логично для per computer лицензии), то возникают некоторые проблемы.

Проблема 2 — файлы или реестр




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

Проблема 3 — виртуализация для бесправных




Во времена W2K/WinXP очень многие пользователи грешили тем, что всегда работали на компьютере с правами администратора. В системах Windows, начиная с Windows Vista, Microsoft многое сделала для того, чтобы уменьшить проблемы от такого использования системы.

В современных системах Windows, если приложение с правами обычного пользователя записывает какие-то данные в ветку реестра под HKEY_LOCAL_MACHINE, то срабатывает виртуализация реестра и реально данные пишутся куда-то в ветку HKEY_CURRENT_USER. Все довольны — программа довольна, что ей не запретили запись в реестр, и что она поменяла данные для всех пользователей системы. Пользователи системы также довольны тем, что программы одного пользователя системы делают меньше гадостей другим пользователям. В итоге все довольны, кроме разработчиков ПО, у которых прибавилось головной боли.


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


Проблема 4 — виртуализация для имеющих права




Имеющие права на запись в интимные части реестра и файловой системы, а к ним относятся пользователи систем с отключеным UAC, или пользователи, запустившие программу с повышением прав, проблем с записью куда надо не имеют. Эти проблемы имеют обычные бесправные пользователи. Проблема в том, чтобы бесправные пользователи, которые честно открывают ветку реестра HKLM только на чтение, должны прочтитать тоже самое, что, туда записали привилегированные пользователи. Виртуализация реестра, которая включена по умолчанию для бесправных и выключена для имеющих права, несколько этому мешает.

Проблема 5 — отключить виртуализацию




В принципе, виртуализацию отключить не сложно, нужно лишь немного погуглить. Немного сложнее не забыть, что программа должна работать и под Windows 2000/Windows XP, в которых новых Vista API нет и не будет.

Проблема 6 — отключили таки виртуализацию?




Если вы неплохой програмист, и умеете пользоваться гуглом, с виртуализацией реестра и файловой системы вы наверно разобрались. Но есть нюанс. Вы забыли, что ваше приложение выпускается в версиях x86 и x64, а у вас продаются сразу оба варианта под одной лицензией. Это другая ось виртуализации, ее надо обрабатывать отдельно. Опять же, не стоит забывать о поддержке W2K/WXP.

Проблема 7 — дайте прав




Пользователь скачал программу, установил, запускает. А она ему и говорит человеческим голосом: «незарегистрированная я». Нет проблем — если нужна активация только для текущего пользователя компьютера. Если же нужно активировать программу для всех пользователей данного компьютера, то надо перезапустить программу с повышенными правами, для возможности записи в общие для всех пользователей каталоги и/или ветки реестра. Пользователю будет удобно, если программа не просто уведомит о необходимости запуска с повышенными правами, но и сама перезапустится с соответствующим запросом от системы.

Перезапуск приложения с расширеными правами реализуется для всех систем одинаково, отличие есть лишь для старых систем W2K/WXP — запрашивается пароль администратора системы, в системах Windows Vista и выше появится обычное окно UAC.


Проблема 8 — много прав у президента




Парламентская республика — наш выбор. Нельзя давать президенту всей полноты власти, основополагающие вопросы должен решать парламент, операционная система, и остальные доверенные системные сервисные процессы. Если приложение для активации запросило права администратора, произвело (успешно или нет) активацию, то по завершении этого процесса оно должно вернуть все запрошенные полномочия системе — вне зависимости от того, зловредное ли это приложение или нет, оно должно перезапустится с правами оригинального пользователя. Если приложение зловредное — нужно сделать вид, что всё было сделано по-честному. Если приложение добропорядочное, то работая после активации с правами суперпользователя оно компрометирует систему через возможные дыры в своем коде. Перезапуск нужен в любом случае.

Хорошее приложение работать максимально удобно для пользователя. К сожалению, для систем W2K/WXP нет более или менее документированного способа для приложения перезапуститься с пониженным правами, и единственное, что остается — выдать предупреждение пользователю о необходимости запустить программу обычным способом и завершить свою работу.


Для систем Windows Vista+ у приложения есть возможность перезапуститься с правами Windows Explorer'а. Эта возможность, а также действия, необходимые для её реализации, известна google'у.


Проблема 9 — что-то пошло не так




Хотя я и старался все делать хорошо и правильно, и оттестировал свои методы и диалоги активации на W2K, WinXP, Windows 7 и Windows 8.1, проблем с активацией в первом же приложении, в которое я добавил свои новые функции, избежать не удалось. Поначалу я каждый раз что-то дописывал, перезаливал дистрибутив, и просил терпеливых пользователей попробовать еще раз. Потом мне это надоело, и я решил, что надо сделать мини-систему логгирования, и раскидать запись сообщений во всех контрольных точках процесса активации. Надо сказать, что это сильно помогло в отладке активации, да и получилась простая, но довольно удобная система протоколирования для несложных однопоточных приложений, которую можно использовать и для нужд приложения. Тут я вкратце опишу, что мне хотелось получить, в основном в плане GUI для активации, и чего не было у протектора.

Проблема 10 — кто показал GUI?




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

В случае использования протектора, с которым я работаю, соединением с сервером активации и получением ключа занимается API протектора, но никто не мешает реализовать всё это и самому. В моем случае короткие серийные номера вида «XXXX-XXXX-XXXX» производитель протектора называет кодами активации по своей терминологии, а длинный ключ, необходимый для инициализации подсистемы протектора, называется серийным номером, и содержит подписанные данные о покупателе, его электронном адресе, а также некоторую дополнительную информацию.


Производитель моего протектора предпочитает сам соединяться с сервером активации и получать ключ для заданного HWID-fingerprint'а и короткого серийника (кода активации), и он просто немного облегчил мне задачу — мне не нужно самому разбираться с WinInet.


В этом случае нужно показать пользователю GUI. Некоторые протекторы умеют это делать (но возможно не всегда так и не всегда то, что точно нужно). Мой протектор не имел никакого встроенного GUI активации, и все пришлось делать самому.


Я выявил набор опций пользовательского интерфейса активации, который хотелось по разному предлагать в разных программах/в разных версиях одной программы. Вот мой джентельменский набор:



  • Активировать серийный номер

  • Офлайн активация серийного номера

  • Активировать при помощи ключевого файла лицензии

  • Активировать пробную версию




Проблема 11 — весь гемор только при установке




Я не люблю такие программы, которые вроде устанавливаются без вопросов, а потом при каждом запуске еще что-то выпрашивают. Мне нравится, когда обо всем сразу спрашивают — например, при установке програмы: триал, или купил? Если триал — отметил для себя: возможны запросы от программы. Купил: жду, что будет работать без вопросов.

Для этого необходимо интегрировать активацию приложения непосредственно в программу-установщик.


Проблема 12 — интеграция с инсталлятором




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

Основная проблема заключалась в том, что хотелось обойтись без дополнительных окон, размещая всю информацию на страничках визарда setup-программы.


Варианты активации, которые хочется поддерживать в установщике, такие же как и для основной программы. К ним можно добавить лишь вариант «Активировать позже», который пропускает шаг активации при установке, но намекает, что активация будет потребована потом, и вариант «Уже активировано», который, в принципе, делает тоже самое.


Проблема 13 — пожалейте сисадмина, сделайте silent/batch режим установки




После того, как в инсталлятор были встроены странички активации, я задумался над тем, каково это будет сисадмину организации, которая купит у меня 50 копий ПО? Решил, что явно не сладко, если он все 50 копий будет ставить и активировать руками. Поэтому было решено сделать поддержку Silent-установки; для этого, как минимум, нужно научить инсталлятор принимать код активации из параметров командной строки программы установки. Также я добавил поддержку возможности активировать Trial-лицензию, используя опции командной строки. Еще пара хотелок, которые не слишком уж относятся, собственно, к протектору и активации приложения, но лежат где-то рядом, и я решил запихать их в один модуль с остальным.

Проблема 14 — диалог «О Программе»




Некоторые любят делать диалог о программе, и любовно выпилывают его неделями, некоторые ненавидят это, и выпускают первые версии без такого диалога. Я отношусь ко второй категории, но выпускать свои программы без красивого диалога About все же не хотелось.

В результате было принято сделать универсальный диалог, в котором можно (и почти все — опционально) показать картинку-лого слева или справа, показать название программы с подзаголовком и строкой информации, показать сведения о пользователе, на которого зарегистрирована программа, показать версию ОС, количество и тип ЦПУ, объем памяти, а также кактую-либо многострочную информацию (например, о копирайтах).


Также захотелось оставить возможность добавить «пасхалку» — я решил, что это можно прицепить на клик по изображению.


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


Само-собой, что все это должно быть оформлено в виде вызова одной единственной функции, пусть и с большим количеством параметров, чтобы таскать «About» из проекта в проект было просто.


Проблема 15 — shell-диалоги




Shell-диалоги — это диалоги выбора файла для сохранения, выбора файла для открытия, а также диалог выбора каталога. Для систем W2k/WinXP и для систем Windows Vista+ эти диалоги выглядят по разному, и что более печально, используют абсолютно разные API. Как минимум, мне необходимо было использовать такие диалоги в процессе активации, да и в своих программах хотелось, не теряя совместимости со старыми системами, отображать их в наиболее современном виде. Также хотелось каждый такой диалог вызывать максимально просто — иметь по одной функции для каждого типа диалога, не слишком теряя в функциональности по сравнению с системными функциями. На самом деле, решение почти каждой проблемы не слишком сложно, и находится гуглом без особых проблем. Немного больше времени занимает создание более или менее красивых и универсальные диалогов. В целом же, на все это, как ни крути, уходит время, и я решил выпустить свое решение отдельным продуктом, о котором раскажу в следующем посте (в хабе «Я пиарюсь»).

This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.


Комментариев нет:

Отправить комментарий