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

В случае с редким или самописным софтом такая проблема случается сплошь и рядом. Практически каждая отдельно взятая контора может похвастаться, что какой-то местный кудесник-программист наколотил две-три тысячи строк кода, создавая очередную программу отчетности или ERP-систему. И все идет хорошо, пока этот компьютерный гуру не потеряется. Стандартного инсталлятора нет, простое копирование папки с программой не помогает, а программу срочно нужно установить еще на одну машину. Кажется, пора начинать рвать на себе волосы? Но это не вариант для компьютерной нечисти! 🙂 Что переносить?

Итак, самый главный вопрос: что переносить кроме папки с программой? Условно все необходимое можно разбить на три пункта:

  1. Файлы, к которым обращается программа.
  2. Ветки реестра, к которым обращается программа.
  3. Среда выполнения.

Если с пониманием первых двух пунктов проблем нет, то насчет третьего стоит сделать уточнение. Под средой выполнения здесь понимаются базы данных, драйвера устройств (псевдоустройств), именованные каналы (Named Pipes), мэйлслоты, COM/ActiveX компоненты и так далее. То есть, все, с чем работает программа (и что предоставлено сторонним софтом, а не операционной системой) через стандартные интерфейсы Windows — будь то сеть, IPC или тому подобное.

Среда является самым проблемным компонентом при переносе, и именно из-за среды приходится заморачиваться, чтобы ОС на обеих машинах совпадали.

 

Какие файлы и ветки реестра переносить?

Господа, давайте дружно поднимем бокалы с кофе, выпьем и почтим память безвременно ушедших утилит-мониторов NT Filemon и NT Regmon, которые отслеживали обращения любого процесса к файлам и ключам реестра соответственно. Злой гений Марка Руссиновича безжалостно аннигилировал их… а потом воссоздал из пепла в одном мощном и полезном инструменте. Встречайте, Process Monitor. Именно эта тулза будет основным оружием переноса и поможет нам разобраться, какие файлы использует программа и к каким ключам в реестре обращается. Для этого нам понадобятся две функции: Show Registry Activity и Show File System Activity.

Итак, открывай ProcMon, запускай переносимую софтину и дождись, пока она полностью загрузится. Затем ступай в ProcMon, отключи логирование, найди нужную программу (по имени исполняемого файла), жми правой кнопкой по записи в столбце Process Name и выбирай Include ‘SuperProg.exe’, где SuperProg.exe — это исходное приложение для переноса. Ты увидишь, что Process Monitor отсеял все события, связанные с другими процессами. Можно было бы анализировать все в уме, отслеживая события, которые появляются в Process Monitor, но мы поступим иначе. Для удобства сохраним лог всех обращений в файл. Для этого нажимай «File -> Save…». В окне сохранения опцию «Events to save» выставляй в «Events displayed using current filter»(чекбокс «Also include profiling events» должен быть включен), а «Format» выбирай «Comma-Separated Values (CSV)». Сохрани куда-нибудь Logfile.csv и можешь заглянуть внутрь. Испугался? 🙂

Разобраться в этой помойке без помощи парсера сложно. Чтобы упростить задачу, я, когда сам занимался подобным переносом, набросал два Perl-скрипта (ищи их на диске). Положи эти скрипты в папку, где был сохранен Logfile.csv (или сразу сохраняй лог в папку к скриптам). Теперь запускай parse.pl. Этот скрипт отпарсит log-файл и создаст еще два лога: file.log будет содержать уникальные обращения к файлам и папкам, reg.log —уникальные обращения к веткам реестра.

 

Отделяем мух от котлет

Не торопись запускать второй скрипт. Сначала рекомендую отсеять явно левые записи из reg.log. Такие ветки реестра, как HKLM/Software или HKCR/Interface являются чисто системными, поэтому на новую машину их импортировать не имеет смысла (в худшем случае можно испортить систему). Удаляем. Сильно тут не лютуй, а то выкинешь что-то, что имеет отношение к программе, которую переносим. После этого можно с чистым сердцем запускать export.pl. Скрипт пошуршит и создаст в папке кучу REG-файлов (их можно импортировать на целевой системе) + папку subdir. Далее необходимо проанализировать содержание Reg-файлов, напрячь голову и отсортировать файлы на три группы:

  • Нужен программе;
  • Не нужен программе;
  • На дополнительное изучение.

Сортируя файлы, не забывай редактировать абсолютные (полные) пути до компонентов (DLL-библиотек, файлов настроек и прочего), если найдешь. Так мы получим REG-файлы, которые необходимо импортировать на целевой машине. Теперь по поводу файлов. В папке subdir скрипт воссоздал дерево обращений к файлам таким образом:

subdir
C (буква диска)
Program Files

…и так далее, до файлов включительно.

 

Непосредственный перенос

На новой машине скопируй папку с программой в C:Program Files (к примеру). Импортируй ключи реестра, которые ты определил в группу «Нужен программе». Из папки subdir восстанови структуру файлов и каталогов, отсутствующих в системе, на которую выполняется перенос. Надеюсь, ты понимаешь, что системные файлы и библиотеки заменять не надо. Поэтому при переносе файлов нужно быть очень осторожным. Обязательно обращай внимание, где располагается перемещаемый файл — проведи аналогию с переменными окружения (изучи вывод команды «set» в консоли). Просмотри содержимое каждого файла, который, как тебе кажется, не является системным. Поправь значения опций, в которых задается полный путь до каких-либо компонентов, если найдешь файл(ы) настроек.

Если о защите системных библиотек Windows хоть как-то позаботится SFC (System File Checker), то в случае реестра такой помощи ждать не приходится. Поэтому при импортировании веток реестра с рабочей машины нужно быть вдвойне осторожным. Причем, как и в случае с файлами настроек, придется корректировать пути в строковых параметрах. Зарегистрируй COM-компоненты — их легко определить по наличию нескольких экспортируемых функций (DllRegisterServer, например).

Тем, кто забыл: регистрация производится командой regsvr32 component.dll, где component.dll является COM-сервером (кстати, COM-сервер может находиться и внутри exe-файла). Ценителям Total Commander будет приятно, что для их любимца есть listerплагин, который на раз определяет COM/ActiveX. Если программа использует какие-то специфические технологии, необходима дополнительная настройка. Скажем, в случае с использованием BDE(Borland Database Engine) необходимо внести соответствующие изменения у DataSource’ов, которые использует программа.

После этого остается только проинсталлировать и настроить среду, которая нужна нашему приложению (если нужна). Стандартные компоненты наподобие сервера БД ты установишь сам. Перенос среды должен быть легче всего, поскольку для серверов БД есть нормальные инсталляторы. Установить драйвер можно специальной утилитой, а зарегистрировать COM-сервер еще проще.

 

Перенос драйверов

А что делать, если программа работает с драйвером, единственный установщик которого потерян вместе с install.exe? Да и как вообще определить, что программа работает с драйвером? Какой-либо специальной тулзы я не нашел, поэтому воспользуемся OllyDbg. Чтобы работать через DeviceIoControl (через эту системную функцию драйверу устройств отправляются разные команды), сначала необходимо открыть созданное устройство через символическую ссылку вызовами CreateFileA/CreateFileW. От этого и будем плясать.

Загрузи программу в отладчик. Прямо на точке входа в окне дизассемблера жми <Ctrl+G>, вводи CreateFileA и нажимай <OK>. Мы попали в начало функции открытия файла. На этом месте нажимай <Shift+F4> или в меню по правой кнопке «Breakpoint — Conditional log». В открывшемся окне в поле «Expression» вписывай DWORD PTR DS:[ESP+4] — по этому адресу лежит указатель на открываемый файл. В комобоксе «Decode value of expression as» выбирай «Pointer to ASCII string» (для юникод-версии соответственно — «Pointer to UNICODE string»). Радио-кнопку <Log value of expression> выставляй в «Always». Остальные опции оставь по умолчанию. Нажимай <OK> и запускай программу.

Очень вероятно, что придется имитировать ее реальное использование, поскольку мы не знаем, в какой момент может произойти обращение к драйверу. Открывай в OllyDbg лог (комбинация клавиш <Ctrl+L>) и ищи подсвеченные строки, начинающиеся с COND. В кавычках будет указан файл, и если он начинается с . — считай, что это наш драйвер. С помощью утилиты WinObj (кстати, написанной опять же Руссиновичем) выясни настоящее имя устройства. Оно должно выглядеть как DeviceDevName. Посредством той же WinObj убедись, что на другом компьютере этого устройства нет.

Настал черед поиска самого файла драйвера. Большинство драйверов располагаются в %SystemRoot%System32Drivers. Перейди в эту папку и ищи UNICODE-строку имени устройства (DeviceDevName). Если файла с такой строкой нет, то открывай «Сервис Менеджер».

Там ищи все драйвера, которые располагаются по нестандартному пути — искомая строка должна быть в одном из них. Этот же «Сервис Менеджер» поможет тебе перенести драйвер на другой компьютер (сделай скриншоты настроек, пропиши зависимости и так далее).

Утилита хорошая, но, увы, не совсем корректно инсталлирует драйвера. Поэтому, после того, как установишь свой драйвер, выполни следующие действия: найди в редакторе реестра ветку HKEY_LOCAL_MACHINESystemCurrentControlSetServicesвыбранноеимядрайвера и удали ключи «Group» и «ObjectName» в этом разделе. Если ключи не удалить, то менеджер при запуске драйвера будет выдавать ошибку, сообщая, что указан некорректный путь, хотя путь тут как бы и не причем.

 

Подводные камни

Когда ты считаешь, что все перенес — запускай программу. С вероятностью 70-75% она запустится. Что-то пошло не так? Вполне ожидаемо. Мы тут не яичницу жарим. В общем случае придется применить технологию багхантинга. Брать в зубы дизассемблер, отладчик и ловить исключения (или ExitProcess, если программа вываливается безмолвно). Сложно дать какие-то рекомендации, но все же попробуем. Просмотри внимательно еще раз REG-файлы. Возможно, ты не заметил что-то, что позволяло программе жить и процветать на прежней машине. Попробуй определить несистемные библиотеки из subdir и скопировать их с заменой. Если сообщение, с которым вываливается программа, более информативно, чем «Access violation», попробуй поискать в интернете текст ошибки (это может быть связано со средой исполнения). Но, в любом случае, твоим главным оружием здесь будет незаменимая связка: дизассемблер + отладчик + мозг и прямые руки.

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

Bdetest.exe работает с BDE через алиас «testBDE», за каким-то чертом обращается к драйверу и просто не может функционировать без определенной информации в реестре и файловой системе. На диске ты сможешь найти все необходимое: результат работы скриптов, скрин BDE-алиаса, драйвер, базу и саму программу.

 

Заключение

Перенос программ без инсталлятора — нетривиальная задача. Необходимо обладать знаниями во многих сферах IT — администрировании, программировании, дизассемблировании, отладке, базах данных. Но всегда помни: непереносимых программ не бывает! Ведь, как гласит манифест хакера, если компьютер совершает ошибку, то это ты напортачил.

Оставить мнение

Check Also

Десятка быстрых. Выбираем консольный софт для повседневных нужд

И вновь на страницах нашего журнала рубрика «Кто самый большой гик на планете». В этот раз…