Этот документ описывает синтаксис написания инсталляционных скриптов для Microsoft Windows, используя технологию INF. На INF-файлах построена вся база драйверов и большинство системных инсталляционных пакетов Microsoft Windows. Автор статьи - Алексей Кердиваре. Он любезно разрешил разместить документ на нашем ресурсе, хотя и предупредил, что статья так никогда и не была дописана до конца (в тексте вы встретите недописанные секции). Вашему вниманию предлагается последний авторский вариант статьи от 23 июля 2004 г. Пусть вас не смущает дата трехлетней давности. Документ является, пожалуй, наиболее полным справочником по INF файлам на русском языке. Статью для вас отредактировал и даже дополнил, участник конференции Oszone Владимир "vek" Ходыгин.
Этот документ описывает синтаксис и основные принципы написания пакетных скриптов для установки приложений в среде MS Windows 4.x и выше. Технология простых инсталляционных скриптов получила название INF. Чтобы получить пользу от документа, читатель должен знать понятие и структуру системного реестра MS Windows, уметь работать с файлами, архиваторами, текстовыми редакторами (не Word ;-)), знать значение слов: двоичный файл (бинарный, бинарник), драйвер, библиотека, функция, точка входа, деинсталляция, пользователь (как системный аккаунт). То есть он должен обладать минимальными познаниями в системе и, конечно, желанием.
Несмотря на страсть всё и вся зашивать в бинарники, в установке пакетов и драйверов Microsoft решила пойти путём масс - она решила использовать скрипты. Сейчас все драйверы ко всем устройствам для MS Windows 4 и выше написаны на технологии INF. На диалектах INF базируется установка MS Internet Explorer всех версий, MS Media Player, заплаток к системе, Java VM, множество остальных мелких произведений от MS. В 2000м году Microsoft сделала большой шаг в вопросе установки приложений и "придумала" MSI. "Придумала" в кавычках потому, что в среде OpenSource давным-давно существовали пакеты RPM- и DEB-формата, на которые MSI-формат почему-то похож как брат-близнец. MSI является архивом cabinet-формата (что-то убогое и недотягивающее до ZIP по количеству функций, не говоря уже о RAR), к которому пришиты установочные скрипты в бинарном формате с GUI-диалогами. В системе должен быть установлен MSI Installer, являющийся сервисом с правами системы и тем самым позволяющий сетапить многие пакеты даже с правами юзера (зачем тогда системный администратор, непонятно...). Основными особенностями MSI-инсталлера, унаследованными от технологии Active Setup из INF, является возможность создавать точки отката реестра, которые применяются при деинсталляции пакета автоматически. Это было призвано в попытке избавиться от проблемы постоянного разрушения и замусоривания системного реестра - большой проблемы в MS Windows. Кроме того, существует возможность "восстановить" испорченное приложение из закэшированнного в анналах Windows дистрибутива. Отличительной особенностью MSI является страсть создавать в реестре десятки уникальных UID-ов под каждое приложение и нагружать их кучей параметров. Наверное, помогает. Однако не всегда все эти возможности были необходимыми, существовало много пакетов, где технология MSI была излишней, да и переделывать дистрибутивы не было смысла. Поэтому INF-технология пока продолжает существовать, а при громких заявлениях о MS Windows Longhorn, как о системе, которая наследует всё, остаётся уверенность, что INF будет востребованным и далее. INF-скрипты получились убогими - в них начисто отсутствуют основные смысловые конструкции, как то: inf...then...else, for, while, case и т.д. Впрочем, это не всегда необходимо, они занимают свою нишу, а смысловые конструкции содержит вместо них бинарный код. Скрипты INF ничем не отличаются от простых BAT-файлов по принципу - задана последовательность действий, интерпретатор выполняет, либо выводит ошибку. Скрипты умеют работать с реестром, файлами-папками, INI-, LNK-файлами, выводить простенькие диалоги, и последовательно запускать PE-файлы на выполнение. В принципе, для установки приложений этого хватает. Знание их структуры, работы и синтаксиса будет просто необходимо системным администраторам Windows, полезно инсталляторщикам и начинающим кулхацкерам...
Ограничения:
Здесь не будет затронут формат скриптов пакетов стандартных программ, входящих в состав MS Windows. В целом он идентичен принципам стандартных скриптов, описанных в этом документе.
Также не будет затронут формат скриптов сетевых драйверов и служб MS Windows NT. Несмотря на присутствие программных конструкций внутри этих скриптов, область применения их очень узка, а также требует для своей работы специально сформированных библиотечных файлов.
Здесь не будут рассматриваться специальные скрипты, применяемые в инсталляциях, основанных на Acme Setup (MSOffice 7-8 и др.), совпадающие большей частью лишь в расширении файла.
Не будет рассмотрена структура скриптов установки MS Windows NT 4.0, 5.x (файлы txtsetup.sif).
Не будут описаны CAT-файлы, как выпадающие из области освещения темы.
Не будут затронуты драйверные скрипты, если об этом не попросят читатели.
Ниже в тексте будут упоминаться слова, значение которых описывается здесь: Интерпретатор - Программа, распознающая синтаксис скрипта и последовательно выполняющая команды, указанные в скрипте. Скрипт - Текстовый файл, содержащий секции, параметры секций и значения параметров секций, описывающие действия, которые необходимо выполнить интерпретатору скрипта. Пакет процедур - Суммарный список заданий для выполнения при единичном проходе интерпретатором скрипта. Комментарий, закомментированная строка - Все символы справа от символа ; . Комментарий может быть расположен в рабочей, действующей строке при условии, что он будет правее любых действующих символов. Секция, секционный заголовок - Строчка, обрамлённая слева и справа знаками [ ] , например, вот так: [section.name] называется секционным заголовком. Секция содержит в себе все строки, расположенные ниже строки секционного заголовка вплоть до конца файла или же до следующего секционного заголовка, обозначающего следующую секцию. Строки, относящиеся к секции, называются полем секции. Параметр - Выражение (обычно одно слово), находящееся в поле секции, расположенное слева от первого символа = , например Parameter=... . Не все строки поля секции обязательно содержат параметры. Значение - Выражение, стоящее справа от параметра. Например, Parameter=value Объект - Директория или файл, без разницы. Любой текст - Любой текст серого цвета означает непроверенные данные. Со повышением версии документа такие фрагменты будут проверены и (возможно) заменены более корректными фактами.
В MS Windows присутствует по умолчанию два интерпретатора скриптов INF: SETUPAPI и ADVANCEDINF. Оба интерпретатора представляют два DLL-файла в системной директории и некоторое количество ключей в реестре. Интерпретатор SETUPAPI находится в библиотечном файле setupapi.dll, интерпретатор ADVANCEDINF - в библиотечном файле advpack.dll. В операционных системах MS Windows 95, 98 интерпретатор SETUPAPI находится в 16-разрядной библиотеке setupx.dll. Библиотека setupapi.dll есть в MS Windows 98 и включена в пакеты заплат для MS Windows 95, однако основным интерпретатором остаётся setupx.dll. То есть, следует учитывать, что setupapi.dll не всегда присутствует в системе. Исходя из того, что библиотеки интерпретаторов не являются исполняемыми файлами, требуется внешний инициатор запуска функции интерпретации скрипта. Им является системная утилита RunDLL32.exe. Формат запуска любой библиотеки посредством RunDLL32:
rundll32.exe libraryname,EntryPoint parameters
где: libraryname - имя файла библиотеки (в нашем случае библиотеки интерпретатора), допустимо указывать без расширения, если библиотека зарегистрирована в списке SharedDLLs в системном реестре; EntryPoint - регистрочувствительное имя точки входа в библиотеку (имя вызываемой функции), указывается сразу после запятой, без пробелов; parameters - параметры, передаваемые функции. Синтаксис командной строки для запуска интерпретаторов скриптов INF построен на этих же принципах. Формат запуска обусловлен высокой степенью дозволенности действий в системе файлу простого текстового формата. Microsoft не привыкла доверять скриптам. Поэтому простой запуск двойным щелчком в системе по умолчанию открывает файл скрипта блокнотом. Это достаточно легко изменить
где: InstallHinfSection - имя вызываемой функции (точка входа); DefaultInstall - первый параметр для вызываемой функции, означает имя выполняемой секции в INF-скрипте; 132 - второй параметр для вызываемой функции, флаг для обработки скрипта; C:\Script.inf - третий параметр для вызываемой функции, полный путь к файлу скрипта.Обратите внимание, требуется именно полный путь, так как простое указание имени файла подразумевает расположение файла скрипта в системной директории Windows. Это же примечание в равной мере относится и к интерпретатору AdvancedINF.
В случае с MS Windows 95 строка запуска будет такой:
где: rundll.exe - 16-разрядный бинарник для запуска 16-разрядной библиотеки setupx.dll C:\Short_~1\Script.inf - короткое, DOS полное имя к файлу скрипта, где каждое имя объекта не должно превышать 8-ми символов. Точка и три символа расширения не подпадают под это правило. Если имя папки или файла длиннее 8-ми символов, берутся первые 6, а остальные заменяются двумя символами: ~1. Другой объект длиннее 8-ми символов с одинаковыми первыми 6-ю символами в DOS-интерпретации будет оканчиваться на ~2 и так далее.
Надстроечный над SETUPAPI интерпретатор, позволяющий выполнять дополнительные функции. Стандартные функции передаёт на выполнение интерпретатору SETUPAPI. Функции, поддерживаемые интерпретатором AdvancedINF, помимо вышеописанных:
Предварительная запись изменяемых ключей реестра в бинарный файл (функция отката)
Однократное выполнение действий под каждым пользователем (доустановка) при инсталляции и деинсталляции во время входа в систему (Active Setup)
Запуск исполняемых файлов с параметрами в скрытом и нормальном режимах
Вывод простых диалоговых окон
Чтение директорий назначения операций с файлами из реестра
Исходя из вышеуказанного, будет разумным отдавать предпочтение интерпретатору AdvancedINF - так мы будем пользоваться преимуществами обоих интерпретаторов. Исключение составляет установка драйверов - здесь с этим может справляться только SETUPAPI. Типичный пример запуска интерпретатора AdvancedINF для выполнения скрипта:
где: LaunchINFSection - точка входа; C:\Script.inf - первый параметр для вызываемой функции, полный путь к файлу скрипта; DefaultInstall - второй параметр, имя выполняемой секции в INF-скрипте (обратите внимание, имя секции нечувствительно к регистру в отличие от точки входа); 4 - флаг реакции интерпретатора при обработке команд скрипта.
Для опознавания текстового файла как файла с INF-структурой интерпретатор ищет в непустых строках секционный заголовок [Version]. Заголовок традиционно располагается в начале файла и содержит в своей секции несколько строк, определяющих тип скрипта. Заголовки бывают следующих типов: Стандартные, Драйверные и Расширенные. Тип скрипта указывает, каким именно интерпретатором следует выполнять скрипт. В зависимости от интерпретатора можно выполнять различный набор действий.
Скрипт со стандартным заголовком предназначен для выполнения операций общего назначения. Набор функций, поддерживаемых скриптом со стандартным заголовком, определяется интерпретатором, которому был передан на выполнение этот скрипт. Вот секция стандартного заголовка скрипта:
Указанные здесь параметры SetupClass и ClassGUID редко используются вместе, обычно достаточно любого из них. С драйверными заголовками ситуация несколько иная. Ограничения для использования стандартного заголовка: крайне не рекомендуется использовать при написании скрипта установки драйверов. При построении листа драйверов, соответствующих типу устанавливаемого устройства, интерпретатор отбирает скрипты драйверов именно по заголовку и драйверные скрипты со стандартным заголовком никогда не будут включены в список. Другие ограничения на данный момент не известны.
Определением драйверного заголовка являются параметры Class и ClassGuid. Они указывают на один и тот же тип драйвера, Class указывает имя типа, ClassGuid - его GIUD. Список известных текущей операционной системе типов драйверов можно найти в системном реестре по пути: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class Классы драйверных типов:
{4D36E966-E325-11CE-BFC1-08002BE10318}
Computer
{4D36E968-E325-11CE-BFC1-08002BE10318}
Display
{4D36E96B-E325-11CE-BFC1-08002BE10318}
Keyboard
{4D36E96A-E325-11CE-BFC1-08002BE10318}
HDC
{745A17A0-74D3-11D0-B6FE-00A0C90F57DA}
HID
{6BDD1FC6-810F-11D0-BEC7-08002BE2092F}
Image
{4D36E96C-E325-11CE-BFC1-08002BE10318}
Media
{4D36E96D-E325-11CE-BFC1-08002BE10318}
Modem
{4D36E96E-E325-11CE-BFC1-08002BE10318}
Monitor
{4D36E96F-E325-11CE-BFC1-08002BE10318}
Mouse
{50906CB8-BA12-11D1-BF5D-0000F805F530}
MultiPortSerial
{4D36E972-E325-11CE-BFC1-08002BE10318}
Net
{4D36E979-E325-11CE-BFC1-08002BE10318}
Printer
{4D36E97B-E325-11CE-BFC1-08002BE10318}
SCSI Adapter
{50DD5230-BA8A-11D1-BF5D-0000F805F530}
Smart Cart Reader
Не рекомендуется указывать только Class, так как не все системы этим удовлетворятся. При определении скрипта как драйверного, в системе (начиная с версии MS Windows 2000 - NT 5.0) инициируется "вакцина" - реакция на изменение системной части реестра. При этом, в зависимости от текущих настроек, может быть выведен запрос на подтверждение установки драйвера. Начиная с MS Windows XP (NT 5.1) при настройках по умолчанию создается точка отката системной части реестра и изменённых в ходе установки системных файлов. Кроме того, при указании драйверного заголовка скрипт будет лишён возможностей, поддерживаемых в AdvancedINF.
Расширенный заголовок скрипта указывает, какая версия интерпретатора AdvancedINF необходима для выполнения скрипта. Новые версии библиотеки advpack.dll (AdvancedINF) обычно поставляются с дистрибутивами Microsoft Internet Explorer, так как технология установки последних базируется именно на AdvancedINF. Старые версии интерпретатора (ниже 2.0) можно обнаружить на Windows NT 4.0 с Сервис Пакетом 3 и ниже и на Windows 95 OSR 2 (без нового MSIE) и ниже. Если текущая версия интерпретатора ниже указанного в скрипте, обработка скрипта будет прервана и выведется ошибка, в нашем случае - "Error message":
Если файл с расширенным заголовком, предназначенный для обработки интерпретатором AdvancedINF, будет в командной строке передан на выполнение для SETUPAPI, выполнен он будет как файл со стандартным заголовком.
Как Вы заметили, в каждом типе заголовка неизменной строкой является параметр Signature. Его значение определяет, для какой операционной системы предназначен скрипт. Известны два значения: $CHICAGO$ и $WINDOWS NT$. Первый предназначен для всех операционных систем MS Windows; второй только для MS Windows NT 5.0 (2000), 5.1 (XP), 5.2 (2003). Исключение составляют драйверные скрипты - здесь необходимо по возможности точнее определить тип системы, иначе драйвер (в зависимости от типа) не будет опознан, как подходящий.
В каждом INF-файле присутствует выполняемая секция, определяемая уже в строке вызова INF-файла. Именно эта секция рассматривается как руководство к выполнению команд, независимо от наличия других выполняемых секций в этом скрипте. Подобный подход (в отличие от BAT-файлов) позволяет хранить множество пакетов процедур в одном и том же файле скрипта. Как правило, в одном скрипте установки хранятся пакеты процедур установки и деинсталляции приложения. Выполняемая секция содержит ключи, флаги для проверки возможности выполнения скрипта и, самое главное, параметры типов действий, чьи значения содержат имена дочерних секций, в которых прописаны объекты для выполнения действий над ними.
Наличие параметров в выполняемой секции во многом зависит от типа скрипта (стандартный, драйверный, расширенный). В одной заголовочной секции не может быть двух и более одноимённых параметров. Имена параметров, за исключением специальных флагов, определяют тип действий, например, запись в реестр, копирование файлов. Значения этих параметров составляют имена других, дочерних секций, содержащих адреса и имена объектов для выполнения операций. Имена дочерних секций должны даваться через запятую и знак пробела. Если имён дочерних секций несколько, они выполняются по очереди, в порядке написания. Некоторые параметры должны содержать только одну секцию. Пример выполняемой секции расширенного скрипта:
Правило: имена дочерних секций ( в этом примере они: cpf.test, cpf.tester,cpf.testing...) не должны начинаться со знака цифры (0-9) и не должны быть равны зарезервированным именам параметров, как то: CopyFiles DelFiles AddReg DelReg UpdateInis Reboot CheckAdminRights RequiredEngine CustomDestination BeginPrompt EndPrompt ComponentName ComponentVersion PreRollBack PerUserInstall RunPreSetupCommands RunPostSetupCommands. Кроме того, имена секций не должны содержать пробелов и знаков: ",'/\?*;:^()[]
Ниже приведена таблица описаний имён параметров выполняемой секции:
Копирование файлов, расположенных относительно файла скрипта в текущей директории, в поддиректориях или в cabinet-архивах в назначенные директории копирования. Более подробно в теме: "Копирование файлов"
Добавление или замена ключей, параметров и значений системного реестра на указанные в дочерних секциях. Более подробно в теме: "Операции с системным реестром"
Удаление из системного реестра ключей или параметров (не значений), указанных в дочерних секциях. Более подробно в теме: "Запись и удаление ключей реестра"
Удаление или запись параметров и значений в INI-файлах, а также создание пользовательских ярлыков. Более подробно в теме: "Работа с INI-файлами"
Интерпретатор AdvancedINF (версии 2.0 и выше):
RequiredEngine
RequiredEngine=SETUPAPI,"Error string"
Проверка на наличие указанного интерпретатора в системе перед обработкой выполняемой секции; SETUPAPI - имя, "Error string" - строка выводимой ошибки в случае отсутствия интерпретатора. Если интерпретатор не найден, обработка скрипта прекращается. Проверка производится перед обработкой всех остальных параметров.
Reboot
Reboot=1 Reboot=0
Флаг перезагрузки после выполнения пакета процедур. Этот флаг может быть отменён флагом вызова скрипта (через точку входа LaunchINFSectionEx) 0 - Перезагрузка не выполняется, даже если это необходимо. 1 - Пользователю всегда выдается запрос о перезагрузке.
Проверка перед выполнением на наличие администраторских привилегий текущего пользователя. Актуально только на NT-системах (MS Windows NT 4.0, 2000, XP, 2003) При 1 - производится. Если текущий пользователь в системе не имеет прав администратора, выводится ошибка и обработка скрипта прекращается. Проверка производится перед обработкой всех остальных параметров, за исключением RequiredEngine.
Отображение начального диалога с произвольным текстом и двумя кнопками (OK и Отмена). Если пользователь выберет "Отмена", обработка скрипта будет отменена. Более подробно, тема: "Диалоговые окна (AdvancedINF)"
Выполнение списка (списков) команд до начала обработки параметров CopyFiles, DelFiles, AddReg, DelReg, UpdateInis, PerUserInstall, EndPrompt и RunPostSetupCommands, но после обработки параметров CheckAdminRights, RequiredEngine. Более подробно тема: Последовательное выполнение списка команд (AdvancedINF)
Указывает дополнительную исполнимую секцию, которая "регистрирует" программу в списке Active Setup и дает возможность единожды под каждым пользователем при следующих входах в систему выполнить любой исполнимый файл с параметрами. Более подробно в теме: "Секция Per User (Active Setup)"
Удаление директорий, указанных в дочерних секциях.
Cleanup
Cleanup=1 Cleanup=0
Очистка директорий от содержимого перед удалением директорий (DelDirs).
NTAdmin
NTAdmin=1 NTAdmin=0
То же самое, что и CheckAdminRights.
PreRollBack
PreRollBack=Имя другой выполняемой секции
Реализация функции отката реестра, требуется указать выполняемую секцию, реестровые ключи операций которой будут сохранены в бинарный файл перед выполнением текущей секции. Типично - в секции инсталляции пакета указывать в качестве откатной точки секцию деинсталляции. При этом удаляются ключи и значения, установленные этим пакетом и возвращаются прежние, восстановленные из бинарного файла.
BackupPath
BackupPath=Директория
Применяется вместе с параметром PreRollBack, указывает директорию (можно несуществующую), которая будет использоваться для сохранения бинарных файлов точек отката реестра.
Дочерние секции подразумевают собой обычные секции, имена которых указаны в качестве значений в параметрах основной, выполняемой секции. Одна и та же дочерняя секция может вызываться из нескольких выполняемых секций. Дочернюю секцию невозможно выполнить отдельно, вызвав интерпретатор. Этим и различаются выполняемые и обычные секции. Некоторые параметры выполняемой секции имеют возможность воспринимать несколько дочерних секций сразу, выполняя их последовательно, одну за другой, другие могут содержать только одну дочернюю секцию и не выполняются вообще, если Вы попытаетесь указать несколько дочерних секций. К параметрам выполняемой секции, воспринимающим несколько дочерних секций, относятся: CopyFiles DelFiles AddReg DelReg UpdateInis CustomDestination DelDirs RunPreSetupCommands RunPostSetupCommands; к параметрам, воспринимающим единственную секцию следующие:PerUserInstall BeginPromptEndPrompt.
Для определения, под какой операционной системой запущена программа в целях корректировки своих действий "издревле" применяются самые разнообразные приёмы. В INF это сделано в виде суффиксов из нескольких букв к имени выполняемой секции. Суффиксом называется несколько символов латиницы и цифр, начинающихся со знака точки и расположенных внутри знаков [ ] , справа от имени секции. Если суффикс отсутствует - секция будет выполнена под всеми операционными системами. Если же в файле присутствует одноимённая секция, но с суффиксом конкретной операционной системы на конце, то она будет выполнена именно на операционной системе этого типа, а первая (без суффикса) - на всех остальных. То есть, сколько бы ни было одноимённых секций с разными суффиксами, выполнится только одна, соответствующая типу текущей операционной системы. Определение типа операционной системы возлагается на интерпретатор. Пример секций с разными суффиксами в одном скрипте:
На данный момент в стандартных INF скриптах известны всего два суффикса: win -MS Windows 95, 98, ME; и NT - MS Windows NT 4.0 и выше (2000, XP, 2003). То есть отсутствует конкретное определение версии операционной системы. Как немного облегчить положение, рассказано здесь.
В процессе выполнения скрипта может понадобиться возможность запустить exe-файлы с параметрами (или без). Для реализации этого в выполняемой секции требуется указать по крайней мере один из двух параметров: RunPreSetupCommands или RunPostSetupCommands. Как видно из названия параметров, первый выполнит свои дочерние функции перед установкой (обработкой скрипта), второй - после. Более подробно: RunPreSetupCommands обрабатывается после CheckAdminInstall (NTAdmin), RequiredEngine, но перед всеми остальными, а RunPostSetupCommands после всех, но перед EndPrompt. Параметры поддерживаются только интерпретатором AdvancedINF. Это единственные параметры, которые в своих значениях поддерживают флаги, а именно: при указании соответствующих флагов существует возможность запускать один список команд скрытым, другой - не ожидая завершения команд, третий - с задержкой после выполнения. Флаг, выглядящий, как одно число, пишется сразу после имени дочерней секции, отделяясь знаком двоеточия. Пример:
;Простое выполнение команд с показом окон и ожиданием завершения каждого процесса [cmd.begin] filename.exe /param1 /param2
;Выполнение команд с задержкой в 400 ms завершения каждого процесса [cmd.delay_post] filename.exe /param1 /param2
;Выполнение команд со скрытием окон (SW_HIDE) и ожиданием завершения каждого процесса [cmd.hidden] filename.exe /param1 /param2
;Выполнение команд с показом окон (SW_SHOW) и без ожидания завершения каждого процесса [cmd.nowait] filename.exe /param1 /param2
;Выполнение команд со скрытием окон (SW_HIDE) и без ожидания завершения каждого процесса [cmd.nowait_hidden] filename.exe /param1 /param2
;Простое выполнение команд с показом окон и ожиданием завершения каждого процесса [cmd.end] filename.exe /param1 /param2 filename2.exe /param1 /param2 filename3.exe /param1 /param2
Расшифровка ключей управления процессами в дочерних секциях: 1 - Попытаться скрыть окна создаваемого процесса 2 - Не ожидать завершения процессов, запускаемых в дочерних секциях 4 - После завершения каждого процесса будет выдержана пауза в 400 миллисекунд. Число флага кратно и может складываться из нескольких значений, то есть, содержать в себе несколько флагов. К примеру, число 6 содержит в себе 2 флага - 4 и 2; 5 - 4 и 1. В итоге могут получаться уникальные числа, содержащие любой набор флагов.
Можно сказать, основная задача инсталляционного INF-скрипта - это копирование файлов и изменение ключей реестра. Вот именно эти секции продуманы в реализации INF основательно. Копирование файлов включает в себя возможную распаковку из сжатых архивов формата cabinet (расширение файлов .cab), простое копирование, переименование в процессе копирования, создание директории назначения, привязку реального пути по системным переменным, удаление файлов, поддержку многодисковых и многоархивных дистрибутивов, проверку версии, локализации и наличия заменяемого файла. О том, как это всё реализовано, описано ниже.
Для успешного копирования файла необходимо знать три вещи: куда, что и откуда. Куда - это содержимое секции [DestinationDirs] и, может быть, ещё её помощника параметра CustomDestination. Что - это содержимое дочерних секций, содержащих имена файлов. Откуда - это содержимое секций [SourceDisksFiles] и [SourceDisksNames]. Объекты "куда" и "что" связаны между собой одинаковыми именами дочерних секций. То есть, исходя из того, что вся дочерняя секция может быть скопирована только в один каталог, логично то, что у дочерней секции всего один пункт назначения и, следовательно, ей принадлежит один параметр в секции [DestinationDirs]. Далее, объекты "что" и "откуда" связаны между собой именами файлов, значит, файл, присутствующий в операции перемещения (дочерней секции), обязан быть указанным в источнике [SourceDisksFiles]. Для облегчения понимания этих связей пример:
[DefaultInstall] CopyFiles=cpf.test
[cpf.test] filename.ext
[DestinationDirs] cpf.test=-1, C:\Temp
[SourceDisksFiles] filename.ext=1
[SourceDisksNames] 1="TEST CD","",0
В этом простом примере копируется файл filename.ext в каталог C:\Temp. Если необходимо скопировать несколько файлов в директорию C:\Temp, их нужно дописать в двух секциях: дочерней секции [cpf.test] и в секции "Откуда" - [SourceDisksFiles]. Если следующий файл необходимо будет копировать в другую директорию, для него придётся создавать новую дочернюю секцию, добавлять её к первой в параметре CopyFiles и указывать для неё новый каталог назначения [DestinationDirs]. В месте "Откуда" (дистрибутив) файлы могут находиться в разных подкаталогах и\или cab-архивах. За это отвечает секция [SourceDisksNames]. Она содержит пронумерованные дистрибутивные пути, причём каждый путь может указывать одновременно и на отдельный диск, и на отдельную директорию и на отдельный cab-архив. Формат записи дистрибутивных секций:
где: 1 - переменная дистрибутивного пути, "Drive_Name" - имя диска (label), "data1.cab" - cabinet-архив на диске "Drive_Name", содержащий файлы, предназначенные для копирования (допускается указывать имя файла cab-архива без расширения), subdir - Поддиректория на диске "Drive_Name", содержащая файл "data1.cab". Во второй строке указано лишь имя диска, имя файла cab-архива оставлено пустым, а поддиректория равна нулю. Более традиционным считается ставить для текущей директории знак точки - ".", однако, скорее всего, у Microsoft проблемы с синтаксисом и, кроме того, постоянные нарушения неписанных стандартов. Далее:
Если предположить, что все три указанных файла указаны в одной дочерней секции копирования, однако, как указано выше, находятся на разных сменных дисках - первые два на диске с меткой "Drive_Name", а третий - на диске "Drive_Name2", то в процессе копирования будет показан диалог с требованием сменить диск для продолжения операции копирования или указать другой путь к диску:
Переменные путей - это результат использования дисковой системы в MS Windows, где реальный путь к приложению может не совпадать с предполагаемым из-за разности имён разделов. К примеру, не всегда системная директория расположена как C:\Windows. Для того, чтобы файлы попали в нужную директорию назначения, в системе есть несколько системных переменных, определяющих конкретные пути в системе, например, в любой MS Windows 16-битная переменная %WinDir% (формата 8.3) содержит полный путь к каталогу с Windows. Помимо него, в NT-системах есть аналогичная переменная с именем %SystemRoot%, 32-х разрядная. Эти переменные почему-то нельзя использовать в INF-скриптах, однако взамен этого INF поддерживает целую кучу собственных переменных для системных директорий, на 90% ненужных, так как на всех существующих системах MS Windows эти пути ведут в одни и те же поддиректории главного каталога с MS Windows. Исключение составляет лишь системный подкаталог, в MS Windows 95, 98, ME он выглядит как %WinDir%\System, а в Windows NT 4.0, Windows 2000 и выше - %SystemRoot%\System32. Некоторые переменные не поддерживаются во всех системах (и в 9x и в NT). Это относится к DOS-утилитам, спулеру печати и директории загрузчика. Переменные в теле INF-скрипта обозначаются так же, как и в BAT-файлах - обрамляются знаками процента по бокам, например, %11%. Их невозможно изменить в секции [strings] для использования как директорий назначения и файлы всё равно будут скопированы в директорию, изначально соответствующую переменной. Однако можно использовать эту переменную для значений, подставляемых в другие типы секций (не секция [DestinationDirs]). Хотя при этом весь смысл подмены переменной теряется.
ID
Значение
Описание
DIRID_ABSOLUTE
-1
Реальный путь, указанный после запятой (cpf.test = -1, C:\Temp).
DIRID_ABSOLUTE_16BIT
0xffff
16-битный реальный путь, формата 8.3 (для 16-разрядной setupx.dll в MS Windows 95)
DIRID_NULL
0
Заглушка, пустой путь. Применяется для отладки.
DIRID_SRCPATH
1
Директория, где находится сам INF-скрипт. Полезна для запуска других секций в этом же скрипте посредством RunP*SetupCommands
DIRID_WINDOWS
10
Собственно, сама MS Windows. Типично, но не закон, что для Windows NT 4.0, Windows 2000 - это C:\Winnt, для остальных - C:\Windows. В командной строке эта директория также также содержится в переменных %Windir% (все MS Windows) и %SystemRoot% (NT 4 и выше)
DIRID_SYSTEM
11
Системная поддиректория MS Windows. Для NT 4, 5 и выше - это %SystemRoot%\system32, для Windows 95, 98, ME - это %Windir%\SYSTEM.
DIRID_DRIVERS
12
Директория размещения системных драйверов. Для MS Windows NT 4 и выше - это %SystemRoot%\system32\drivers, для MS Windows 95 - это %Windir%\SYSTEM\IOSUBSYS, для MS Windows 98, ME - %Windrir%\SYSTEM\DRIVERS
DIRID_COMMANDS
13
Директория с консольными DOS-утилитами, только для MS Windows 95, 98, ME. Размещение: %Windir%\Command. Для MS Windows NT 4 и выше эта переменная неизвестна и файлы, направленные туда, попадут в мусоросборник %SystemRoot%\System32\unknown
DIRID_INF
17
Типично - %Windir%\INF. Обычно этот каталог имеет атрибут "скрытый". В нём хранятся почти все INF скрипты самой системы и их бинарные кэшированные копии, нужные для ускорения построения списка драйверов.
DIRID_HELP
18
Директория %Windir%\Help. В ней находятся почти все файлы справок (расширение .chm, .hlp, .cnt, .gid).
DIRID_FONTS
20
Системные шрифты. Размещение %Windir%\Fonts. Кстати, простое копирование файлов шрифтов в этот каталог не сделает доступным этот шрифт для ваших приложений. Как правильно установить шрифт из INF-скрипта, смотрите здесь.
DIRID_VIEWERS
21
Директория модулей программы QuickView. Расположение: MS Windows 95, 98, ME - %WinDir%\SYSTEM\VIEWERS; MS Windows NT 4.0 и выше - %SystemRoot%\System32\viewers
Неизвестно, но для Windows NT 4.0 и выше, установленной на диск C:\ - это директория C:\. Скорее всего, это аналог системной переменной %SystemDrive%
DIRID_SHARED
25
Та же %SystemRoot% или %WinDir%. Почему не "Program Files" - ума не приложу.
DIRID_BOOT
30
Корневая директория загрузочного диска. Обычно C:\
DIRID_COMPBOOT
31
Корневая директория главного диска сжатого загрузочного диска. Только для MS Windows 95, 98
DIRID_SYSTEM16
50
Системная директория для 16-битных программ (хотя, кажется, на эти правила Microsoft сама плевать хотела, т.к. все 16-битные программы валяются в system32), только для MS Windows NT 4.0 и выше, %SystemRoot%\system
DIRID_SPOOL
51
Директория принтерного спула (кэша), только для MS Windows NT 4.0 и выше - %SystemRoot%\system32\spool
DIRID_SPOOLDRIVERS
52
Директория драйверов принтеров, только для MS Windows NT 4.x и выше - %SystemRoot%\system32\spool\drivers\w32x86
DIRID_USERPROFILE
53
Директория с профилем текущего пользователя. В MS Windows NT 4.0 - это %SystemRoot%\Profiles\%USERNAME%, в MS Windows 2000 и выше - это %SystemDrive%\Documents and Settings\%USERNAME%. В MS Windows 95, 98, ME - это, скорее всего, сама %WinDir%.
DIRID_LOADER
54
Только для систем NT. Путь к загрузочному каталогу, содержащему файлы ntldr или osloader.exe. В 99% случаев это C:\
DIRID_PRINTPROCESSOR
55
Если в секции "куда" [DestinationDirs] не определено ни одной директории, все файлы будут копироваться в каталог по умолчанию, каковым является DIRID_SYSTEM, описанный выше в таблице. Каталог по умолчанию можно изменить (только в сессии выполнения текущего скрипта), указав в секции [DestinationDirs] параметр DefaultDestDir. Его значение будет директорией по умолчанию. Это полезно для некоторой экономии в размере файла скрипта, к примеру, при установке множества пакетов в один программный каталог. Например:
[DestinationDirs] DefaultDestDir=24, Program Files\Program Name
Переменные путей нельзя использовать в секции [strings], в диалогах BeginPrompt и EndPrompt, в именах любых секций и в качестве обозначения типов параметров реестра. Во всех оставшихся местах, кроме секции [DestinationDirs], переменные директорий необходимо обрамлять знаками процента. В секции [DestinationDirs]этого делать нельзя. Если необходимо копировать файлы не в существующую директорию, а в её поддиректорию, необходимо указать оставшийся путь после знака запятой и пробела относительно имени переменной, как видно на примере.
При использовании расширенного формата INF-скриптов (AdvancedINF) Вы получаете возможность динамично указать переменные директории во время работы INF-скрипта, прочитав их из реестра. Полезно это, например, в случае выпуска патчей и заплат к собственному приложению, которое пользователь установил в любой удобный ему каталог. При этом INF-скрипт установщика главного приложения записал в реестре параметр со значением директории инсталляции. Этот параметр и является опорной точкой связи последующих обновлений с главным приложением. Пример значения в реестре:
Теперь рассмотрим шаги, которые необходимо выполнить, чтобы получить это значение параметра реестра Path как переменную внутри INF-скрипта: 1. Необходимо добавить к текущей выполнимой секции, например, [DefaultInstalll], параметр CustomDestination и указать в значении имя дочерней секции, в которой переменным будут присвоены возвращаемые результаты других секций. 2. Написать дочернюю секцию, указанную в параметре CustomDestination и задать используемые номера переменных и имена дочерних секций, где определяется адрес параметра в реестре, содержащего путь. Формат обозначения указан на примере ниже. Кроме того, необходимо указать ключ, определяющий поведение интерпретатора во время установления переменной пути. 3. Написать дочернюю секцию, определяющую адрес параметра в реестре. Её тело - обычно одна строка формата строки записи в реестр, где указывается имя ключа, параметра и типового значения пути.
Теперь разберём пример. В секции [dirs.CustomDest] указаны четыре числа через запятую в качестве параметра. Это имена переменных одной и той же динамической директории в разной интерпретации. Первое число (49000) содержит путь к директории "C:\Program Files\Program Name" в формате 8.3 в кодировке OEM (DOS). То есть, эта переменная содержит строку такого вида: "C:\Progra~1\Progra~1", что необходимо для поддержки 16-разрядного интерпретатора, например, setupx.dll или для других целей. Второе число (49001) содержит этот же путь к директории уже в 32-х разрядном формате путей, с поддержкой длины строки до 256 символов и в ANSI-кодировке (MS Windows). Третье число (49002) содержит строку пути в формате 8.3 в ANSI-кодировке. Нужно для формирования пути в системах с принудительно установленным форматом путей в 8.3. Четвёртое число (49003) содержит строку пути в OEM-формате (DOS), но в длинной интерпретации. Для чего это необходимо, неизвестно, вероятно, для полноты картины. При употреблении переменных можно указать любое, наиболее подходящее. Естественно, наиболее точным для MS Windows будет 49001. Несмотря на такие ухищрения, при проверке во всех четырёх переменных находится одна и та же строчка, без искажений. Быть может, это нереализованные функции перекодирования, неизвестно. С самым простым в этой главе мы разобрались - с, собственно, назначением директорий. Теперь приступим к более сложному, недокументированному и неоднозначному. Это - ключи, указываемые через запятую после имени дочерней секции, указывающей путь в реестре. В нашем примере - это строка 49000,49001,49002,49003 = RegistryDir,5. В этом случае ключ равен 5. Номер ключа в корне изменяет поведение интерпретатора: 1, 9 - Выводится диалоговое окно для указания директории назначения пользователем:
При этом, для того, чтобы добиться подобных значений на площади окна, нужно совершенно изменить формат записи строки в секции [RegistryDir]:
[RegistryDir] ,,,"Укажите директорию для распаковки","C:\Test"
После указания каталога все файлы в секции [cpf.test], а у нас это filename.ext - копируются в указанный пользователем каталог, а также все остальные файлы в секциях, в назначении которых указана эта переменная. 2, 3, 6, 10, 11 - Насколько я понимаю - эти ключи зарезервированы исключительно для вывода диалогов ошибок с произвольным текстом. Если использовать строку от примера, когда ключ равен 1, указанного выше, то появится следующее окно:
При указании нормальной строки ничего не происходит. Странное поведение интерпретатора. 4, 5, 8, 12, 13 - Обычное копирование файлов в указанную директорию. При этом наличие ключа в реестре и его значение не играют никакой роли. 16, 18, 20, 22, 24, 26, 28, 30 Копируют файлы в поддиректорию текущей директории, с путём, равным пути в реестре. То есть, если путь к INF-скрипту таков: C:\Temp, то файлы будут скопированы в C:\Temp\Software\Company_Name\Program_Name, с автоматическим созданием всех директорий. 17, 19, 21, 23, 25, 27, 29, 31 Пытаются скопировать файлы в директорию, составную из пути, указанного в реестре и текущего пути. И, в итоге, терпят ошибку - ведь директории C:\Temp\"C:\Program Files\Program Name" не существует! Вывод - тема пока не доделана, максимум можно выжать лишь собственноручное указание пользователем директории и присвоению его выбору переменной пути, а также проверку на наличие каких-либо параметров в реестре и при их отсутствии выводить ошибку и прекращать обработку скрипта. Эдакий однобокий if...then.
Во время копирования файлов посредством INF-скрипта можно переименовывать файлы, то есть указывать не только каталог назначения, но и новое имя файла в каталоге назначения, а также определять поведение интерпретатора флагами копирования во время выполнения процедуры копирования при встрече ошибок. Пример описания этих возможностей дан ниже:
[DefaultInstall] CopyFiles=cpf.files
[cpf.files] filenam2.exe,filename.ext,2
Как видно в примере, в дочерней секции копирования в каждой строке через запятую нужно указывать все условия, относящиеся к копированию конкретного файла. Здесь: filenam2.exe - имя файла, которое необходимо получить в месте назначения; filename.ext - старое имя файла, которым он обладает в директории (архиве) дистрибутива; 2 - флаг обработки события, которое наступит, если в месте назначения уже есть файл с таким же именем или же в случае сбоя при копировании. Все известные значения флагов:
ID
Значение
Описание
COPYFLG_WARN_IF_SKIP
0x00000001
Выводить предупреждающее сообщение, если пользователь пытается пропустить файл после неудачной операции копирования
COPYFLG_NOSKIP
0x00000002
Скрыть кнопку пропуска файла в случае неудачного копирования. Полезно при замене важных системных файлов.
COPYFLG_NOVERSIONCHECK
0x00000004
Не обращать внимание на версию файла, который уже присутствует в месте назначения и всегда перезаписывать файлом из дистрибутива. Не есть хорошо.
COPYFLG_FORCE_FILE_IN_USE
0x00000008
заменить файл в месте назначения, даже если он используется.Теоретически при этом интерпретатор попытается переименовать в случайное мусорное имя использующийся файл, а затем скопирует файл из дистрибутива.
COPYFLG_NO_OVERWRITE
0x00000010
Не копировать файл, если он уже существует. Например, личные настройки в INI-файле некультурно заменять настройками по умолчанию при каждом обновлении программы.
COPYFLG_NO_VERSION_DIALOG
0x00000020
не копировать и не выводить вопросов, если файл в месте назначения уже существует и его версия новее, чем версия файла в дистрибутиве
COPYFLG_OVERWRITE_OLDER_ONLY
0x00000040
Не копировать, если версии совпадают. То есть заменять только старые версии файлов
COPYFLG_REPLACEONLY
0x00000400
Осуществлять операцию копирования только если файл уже существует. Полезно при выпуске обновлений к многочисленным пакетам.
Как видно из примера, флаги можно записывать и в коротком виде, отбрасывая нули слева. Эти флаги являются составными, то есть в одном флаге можно указать несколько - прибавляя их значения. К примеру, флаг 64 - это флаг, состоящий из трёх флагов - 40, 20 и 4.
Удаление объектов можно выполнить несколькими способами. Перечислим их: 1. Удаление файлов посредством указания дочерних секций копирования в параметре DelFiles. То есть в файле скрипта уже есть секция [DestinationDirs], указывающая место расположения файлов и дочерняя секция копирования, содержащая список файлов, скопированных в каталог назначения. Остаётся лишь указать эту же секцию в параметре DelFiles. При этом секции расположения файлов в дистрибутиве ([SourceDisksFiles], [SourceDisksFiles]) не используются. Этот метод чаще всего применяется в секции деинсталляции пакета. Директории этим способом удалить нельзя, только файлы. Пример этого способа:
[DefaultInstall] CopyFiles=files
[files] filename.ext
[DestinationDirs] files= 11
[Uninstall] DelFiles=files
2. Удаление директорий параметром DelDirs из выполнимой секции. Лучше ставить ниже всех параметров DelFiles, если применяется и такой параметр - в итого сначала удалятся файлы, а затем и директории. В качестве значения к параметру DelDirs указывается дочерняя секция, содержащая просто полные пути к удаляемым каталогам. Можно применять переменные путей. Также можно указывать параметр CleanUp, теоретически предназначенный для предварительной очистки непустых директорий от файлов перед удалением. Это не спасёт от файлов, используемых системой или каким-либо приложением - Вы не сможете удалить такой каталог. Пример этого способа:
[DefaultInstall] DelDirs=dirs Cleanup=1
[dirs] "%24%\Program Files\Program Name"
3. Удаление пустых директорий посредством вызова функции с параметрами из библиотеки интерпретатора AdvancedINF. Этот метод - Windows-команда, которую можно вызывать из любых скриптов. В INF-скрипте её можно вызвать из параметров RunPreSetupCommands и RunPostSetupCommands выполняемой секции. Этот метод удаляет непустые директории. Формат записи таков:
Следующей по приоритетности задачей после копирования файлов из дистрибутива является задача изменения ключей и параметров системного реестра. Доступны следующие функции: добавление ключей реестра, добавление параметров реестра, запись значений ключей, поддержка всех типов ключей реестра, удаление ключей реестра, удаление параметров ключей реестра, замена значений параметров реестра. Из этих возможностей проистекают другие возможности, реализация которых лежит уже не на плечах интерпретатора INF-скриптов, а на плечах самой системы, а именно: Переименование объектов и смена атрибутов, Удаление файлов при следующей перезагрузке, Деинсталляция приложения, Регистрация и отмена регистрации библиотек, однократное выполнение задачи под каждым пользователем (Active Setup).
Запись и удаление ключей, параметров и значений в системном реестре MS Windows посредством INF-скрипта являются базовыми процедурами, владея которыми, можно достигать и других целей. Сначала кратко о структуре системного реестра и типах параметров. В системе существует нереляционная древовидная системная база данных для хранения всей системной информации в виде вложенных ключей, параметров ключей и их значений. Сама структура таблиц довольно проста, если не сказать "убога", потому что содержит подобие файловой системы, где объектами являются ключи содержащие данные всего двух типов: параметры и значения параметров. По сути каждый ключ является потомком INI-файла, из которого убрали понятие секций. Следует учесть, что до сих пор осталось ограничение на размер ключа со всеми его параметрами и значениями в 64 килобайта для совместимости с INI-файлами программ, написанных для MS Windows 3.1, и это накладывает дополнительные ограничения на и без того бедную возможностями функциональность этой базы данных. Физически база данных располагается в нескольких файлах, которые служат корнями "кустов" древовидной базы реестра. В зависимости от версии операционной системы, файлы разнятся по расположению и именам. Основная структура соответствий файлов и корней реестра:
INF
REGISTRY_KEY
Расположение в WIN 95, 98
Расположение в WIN NT 4, 5
HKLM
HKEY_LOCAL_MASHINE
%WinDir%\SYSTEM.DAT
%SystemRoot%\System32\config\SOFTWARE
HKCU
HKEY_CURRENT_USER
%WinDir%\USER.DAT
%USERPROFILE%\ntuser.dat
HKCR
HKEY_CLASSES_ROOT
%WinDir%\SYSTEM.DAT
%SystemRoot%\System32\config\SOFTWARE
HKU
HKEY_USERS
HKEY_USERS\.default
%WinDir%\SYSTEM.DAT
%SystemRoot%\System32\config\default
HKEY_LOCAL_MASHINE\SYSTEM
%WinDir%\SYSTEM.DAT
%SystemRoot%\System32\config\SYSTEM
HKEY_LOCAL_MASHINE\SYSTEM\ControlSet002
отсутствует
%SystemRoot%\System32\config\SYSTEM.ALT
Формат записи в реестр в строке дочерней секции, вызываемой из параметра AddReg выполняемой секции таков:
HKXX,"PATH\REGKEY","parameter",X,"value"
где: HKXX - аббревиатура корневого ключа, имеющая применение в INF-скрипте вместо имени самого родительского ключа (здесь недопустимы переменные); "PATH\REGKEY" - оставшийся после корневого ключа путь к изменяемому, удаляемому или создаваемому ключу (здесь допустимы переменные); "parameter" - имя параметра реестрового ключа (переменные допустимы); X - тип параметра ключа (переменные недопустимы); "value" - значение параметра ключа реестра (переменные допустимы). Удаление объектов реестра производится параметром DelReg в выполняемой секции и имеет идентичный синтаксис в дочерней секции, за исключением следующих деталей: не указывается значение и не указывается тип ключа. Если необходимо удалить только параметр ключа, нужно указать аббревиатуру_корня_реестра,"путь\к\ключу","имя_параметра", если весь ключ - аббревиатуру_корня_реестра,"путь\к\ключу". То есть формат записи строк в дочерней секции при удалении объектов в реестре таков:
Типов параметров в реестре несколько. Самый простой и распространённый - тип REG_SZ. Это тип данных string. Он является типом по умолчанию, если не указывать флаг типа параметра. Кроме того, существуют REG_DWORD (тип данных DWORD), REG_BINARY (тип двоичных данных), интересный абстрактный тип REG_EXPAND_SZ (тип string, поддерживающий подмену имён системных переменных их значениями) и, наконец, REG_MULTI_SZ, поддерживающий несколько строк.
ID типа
Тип параметра
Пример
FLG_ADDREG_BINVALUETYPE
1
HKLM,"%path%","Binary",1,72,00,00,00
FLG_ADDREG_NOCLOBBER
2
---
FLG_ADDREG_DELVAL
4
HKLM,"%path%","Empty_parameter",4,"any_value-this is deleted"
В каждом ключе всегда есть один параметр без имени типа REG_SZ - думается, реестр MS Windows не терпит пустых ключей. Этот параметр имеет видимое название "По умолчанию" и довольно активно используется в ключах, содержащих мало параметров. Можно сказать, это самый используемый параметр. Чтобы изменить его значение через INF-скрипт, нужно опустить имя параметра, как показано на этом примере:
HKLM,"%path%",,,"value_in_default_parameter"
Этот параметр обычно имеет тип REG_SZ, но это допустимо изменять. В строковый параметр типа REG_ADVANCED_SZ Вы можете записывать системные переменные, которые будут подменяться текущими значениями при обращениях к ним программ. Большинство программ не различает параметры REG_SZ и REG_ADVANCED_SZ. К примеру, если Вы укажете в параметре типа REG_ADVANCED_SZ переменную %USERPROFILE%, любая программа посчитает этот параметр как параметр типа REG_SZ, содержащий реальный путь к каталогу профиля текущего пользователя, например C:\Winnt\Profiles\Administrator. Мультистроковый параметр типа REG_MULTI_SZ позволяет добавлять каждый раз по одной строке данных. Это применяется, например, в формировании заданий по замещению или удалению после перезагрузки файлов, использующихся системой на данный момент. Для того, чтобы записать значение параметра этого типа после внесения всех строк, нужно добавить ещё раз этот параметр, указав закрывающий тип 8.Ниже приведён пример INF-скрипта, добавляющего в реестр параметры всех типов:
[Version] Signature="$CHICAGO$" SetupClass=BASE
[DefaultInstall] AddReg=adr.types
[adr.types] HKLM,"%Key%","Binary",1,72,00,00,00 HKLM,"%Key%","DWORD",0x10001,64 HKLM,"%Key%","REG_SZ",,"string only" HKLM,"%Key%",,,"This is value of default parameter" HKLM,"%Key%","REG_EXPAND_SZ",0x00020000,"Current user name: %USERNAME%" HKLM,"%Key%","REG_MULTI_SZ",0x00010000,"first string" HKLM,"%Key%","REG_MULTI_SZ",0x00000008,"second string" HKLM,"%Key%","",,"" HKLM,"%Key%","",,"" HKLM,"%Key%","",,"" HKLM,"%path%","DWORD2",65537,1 HKLM,"%path%","REG_SZ2",FLG_ADDREG_TYPE_EXPAND_SZ,"string only" HKLM,"%path%",,2,"this is default value" HKLM,"%path%","advanced",,"this is test value" HKLM,"%path%","REG_MULTI_SZ",0x00010000,"one string"
Параметр RenFiles содержит имена секций, которые в свою очередь содержат имена файлов, предназначенных для переименования. Папка, где будет происходить переименование должна быть определена в секции [DestinationDirs]. Требования к названию секций копирования файлов: Имя секции не должно содержать зарезервированных слов, таких как RenFiles, CopyFiles и т.д. Ниже приведен пример дочерней секции переименования файлов:
[Section.Ren] NewFileName,OldFileName
где: NewFileName - имя файла с расширением. Указывает новое имя файла, которое будет присвоено файлу OldFileName в папке, заданной в секции [DestinationDirs] OldFileName - имя файла с расширением. Указывает старое имя файла, которое должно быть обозначено в секции [SourceDisksFiles] (Более подробно в теме: "Копирование файлов"). Секция [DestinationDirs] в INF-скрипте управляет назначением всех операций переименования файлов. Если секция, указанная значением к параметру RenFiles, описана в секции [DestinationDirs], то все операции по переименованию файлов будут происходить в директории, указанной в [DestinationDirs]. В противном случае, для указания директории назначения всех операций переименования файлов, INF-скрипт будет использовать параметр DefaultDestDir.
Inf-скрипты предоставляют конечному пользователю возможность редактирования INI-файлов. Для того, чтобы изменить строки в существующем INI-файле необходимо в выполняемой секции указать параметр:
где: ini-file - этот параметр определяет имя INI-файла, в который будут вноситься изменения. Значение этого параметра должно быть выражено именем файла (filename.ini). Сам filename.ini должен находиться в директории Windows. Если файла с таким именем не существует, то будет создан новый. section-name - параметр, определяющий имя секции INI-файла, в которой будут проводится изменения. Если следующие два параметра определены, то в данной секции произойдет замещение строки old-entry на new-entry. Если параметр old-entry опущен, то в секцию добавится значение new-entry old-entry - Строка, в секции section-name, обычно выражаемая в форме "Key=Value". Значением этого параметра может быть любая строка или переменная (%String%), описанная в секции [Strings]. new-entry - Строка, которая при наличии параметра old-entry заменяет его значение, а при его отсутствии добавляется в секцию section-name. Значением этого параметра может быть любая строка или переменная (%String%), описанная в секции [Strings]. flags - Это дополнительное значение управляет интерпретацией данных old-entry и/или new-entry. Флаги могут принимать одно из следующих числовых значений:
Числовое значение
Описание
0
Значение по умолчанию. При установке этого флага скрипт ищет ключ (имя записи) old-entry, не обращая внимания на его значение Если такая запись находится, соответствующая строка заменяется значением new-entry. Если old-entry отсутствует, скрипт автоматически добавит в секцию значение new-entry. Если будет отсутствовать new-entry, то old-entry удалится.
1
Скрипт выполняет проверку в INI-файле по ключу и значению записи old-entry. Обновление строки произойдет только в том случае, если и ключ и значение записи INI-файле совпадут с записью в old-entry
2
Скрипт выполняет проверку в INI-файле строк, ключ которых совпадает с описанным в old-entry. Если такая запись в INI-файле присутствует, она не будет замещаться значением, указанным в new-entry
3
Скрипт выполняет проверку в INI-файле строк, ключ и значение которых совпадает с описанным в old-entry. Если такая запись в INI-файле присутствует, она будет замещаться значением, указанным в new-entry
С помощью параметра UpdateInis в выполняемой секции можно создавать пользовательские ярлыки в меню ПУСК. Синтаксис секции будет выглядеть следующим образом:
где: groupX - переменная, указывающая название группы. GROUPNAME - имя группы ярлыков в меню ПУСК, которое видит пользователь. Может задаваться переменной, описанной в разделе [Strings] PROGNAME - имя ярлыка в группе GROUPNAME, которое видит пользователь. Может задаваться переменной, описанной в разделе [Strings] path - Полный путь до программы, заданный с помощью переменных путей. workdir - Полный путь к рабочей директории (к папке, содержащей программу), заданный с помощью переменных путей. DESCRIPTION - Подсказка, выводимая пользователю при наведении указателя мыши на ярлык к программе. Может задаваться переменной, описанной в разделе [Strings]
Следует обратить внимание на расстановку запятых и кавычек. В данном случае, все переменные заключаются в двойные кавычки. Обязательные знаки в приведенном примере выделены жирным шрифтом. Ниже приведен пример создания и удаления ярлыка в меню ПУСК к редактору реестра:
где: NameItem - имя ярлыка в группе GROUPNAME, которое видит пользователь. Может задаваться переменной, описанной в разделе [Strings]
Числовое значение
Описание
0x00000001
Указывает программе установки создать или удалить ярлык для текущего пользователя. При отсутствии данного флага действия над ярлыками будут происходить для всех учетных записей.
0х00000002
Указывает программе установки удалить ярлык. При отсутствии данного параметра ярлык будет создан.
0х00000004
Указывает программе установки создать или удалить програмную группу. Если параметр не указан, программа установки выполняет операции только над ярлыками. Не над группами.
Path - Полный путь до программы, заданный с помощью переменных путей. workdir - Полный путь к рабочей директории (к папке, содержащей программу), заданный с помощью переменных путей. GROUPNAME - имя группы ярлыков в меню ПУСК, которое видит пользователь. Может задаваться переменной, описанной в разделе [Strings] PathIcon - Полный путь к библиотеке DLL,содержащей изображение иконки, заданный с помощью переменных путей. Если этот параметр опущен, программа установки ищет иконку в файле, указанном в параметре CmdLine IndexValue - Этот параметр указывает какую именно иконку в библиотеке DLL необходимо использовать. При отсутствии этого параметра, программа установки будет брать первую иконку из файла, указанного в параметре CmdLine HotkeyValue - Этот параметр задает значение "горячей клавиши" для вызова программы. DESCRIPTION - Подсказка, выводимая пользователю при наведении указателя мыши на ярлык к программе. Может задаваться переменной, описанной в разделе [Strings]
Вывод диалоговых окон в процессе выполнения скрипта возможен лишь с применением интерпретатора AdvancedINF. Диалоговые окна возможны двух типов: 1. С двумя кнопками (ОК, Отмена), произвольной строкой и заголовком; 2. С одной кнопкой ОК, произвольной строкой и заголовком. Первый тип вызывается параметром BeginPrompt в выполняемой секции и диалог отображается перед выполнением пакетных процедур установки, но после проверок CheckAdminRights (NTAdmin), RequiredEngine. Второй диалог отображается по завершении процедур при условии, что во время выполнения скрипта не произошло ошибок и вызывается параметром EndPrompt в выполняемой секции. Диалоги не зависят друг от друга, другими словами, их указание в выполняемой секции не зависит друг от друга. Если в начальном диалоге пользователь выбрал Отмену, дальнейшая обработка скрипта отменяется.
Значения параметров Prompt и Title в дочерних секциях принято заключать в кавычки, но необязательно. В их теле допустимо использовать переменные из секции [string], но нельзя использовать переменные директорий. Применение параметра ButtonType в дочерней секции параметра BeginPrompt не приносит никаких изменений и, скорее всего, является отладочным или нереализованным параметром, и, поэтому, необязательно.
При создании корректного инсталляционного пакета приходится задумываться о его деинсталляции, удаления из системы. Обычно в системе существует стандартная утилита удаления установленных программ, находящаяся в панели управления. Для того, чтобы зарегистрировать в её списке своё приложение, необходимо добавить в реестр новый ключ с необходимыми параметрами, а также создать функцию удаления пакета из системы. Логично будет создать в INF-скрипте новую выполняемую секцию, выполняющую это действие и скопировать при инсталляции сам скрипт в систему. Место размещения ключа деинсталляции программы Program_Name в реестре: HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall\Program_Name Ниже представлено описание параметров типового ключа удаления программы:
Поддерживается MS Windows 95, 98, NT и выше
Название
Тип строки
INF-cтрока записи в реестр*
Описание
DisplayName
REG_SZ
HKLM,"%Key%","DisplayName",,"Program_Name"
Имя программы, отображаемое в утилите деинсталляции
Кроме того, существуют дополнительные малозначимые ключи, в основном для формирования окна справки о программе, увидеть примеры которых можно, исследовав существующие ключи деинсталляции программ в реестре. Кроме того, для корректной деинсталляции Microsoft реализовала технологию точек отката реестра: "Создание точки отката реестра (AdvancedINF)". Остаётся добавить в файл скрипта новую выполняемую секцию Uninstall, добавить к инсталляционной секции задание на запись ключа деинсталляции и скопировать свой INF скрипт (setup.inf) в систему во время инсталляции программы:
Для уменьшения объёма файла INF-скрипта и для облегчения языковой локализации пакетов рекомендуется употреблять переменные, определение которых находится в отдельной секции. Имя секции [strings]. Оно встречается почти в каждом INF-файле с завидным постоянством и его использование считается правилом хорошего тона в написании INF-скриптов. В теле скрипта переменные обозначаются знаками процента (%) по краям, как и переменные директорий. Пример использования секции переменных:
По традиции секция strings располагается ниже всех остальных секций, являясь завершающей. Места, где запрещается употребление переменных: в именах любых функций, вместо названий параметров и вместо управляющих знаков ;=[],. Под раздел переменных, которые можно использовать в INF-скриптах не попадают никакие другие переменные, кроме тех, которые определены непосредственно в этом файле скрипта и переменных директорий, часть которых можно определить динамично. В значениях переменных нельзя использовать никакие другие переменные, включая переменные путей.
Существует тип самоустанавливающихся библиотечных файлов, которые в своих ресурсах содержат INF-скрипт для передачи системе нужных настроек для корректной работы библиотеки. Такие библиотеки имеют аббревиатуру OCX. Что это значит - неизвестно. Запуск INF-скрипта на выполнение из ресурсов библиотеки называется регистрацией библиотеки. Как правило, все INF-скрипты подобного рода содержат выполняемую секцию для удаления настроек библиотеки и выполнение этой секции называется отменой регистрации библиотеки. Для выполнения секций внедрённого в ресурсы скрипта в библиотеке должна существовать стандартная функция с внешней точкой входа, которая при вызове её извне регистрировала бы библиотеку. Имя точки входа должно быть известно программе, инициализирующей регистрацию. Стандартные названия точек входа для регистрации и отмены регистрации библиотеки таковы:DllRegisterServer, DllUnregisterServer. Существует стандартная системная программа regsvr32.exe, которая выполняет INF-скрипт, предоставляемый библиотекой по этим точкам входа. Для регистрации библиотеки необходимо запустить эту утилиту, передав путь и имя библиотеки параметром командной строки. Формат параметров командной строки утилиты RegSvr32:
regsvr32.exe [/u] [/s] [/n] [/i[:строка]] библиотека /u - Вызов функции DllUnregisterServer, отмена регистрации библиотеки /s - Тихий режим, отсутствие диалоговых и информационных окон (полезно в пакетном режиме) /i - Вызов функции DllRegisterServer, регистрация библиотеки. опциональная строка - другое имя точки входа для выполнения пакета процедур /n - Не вызывать функцию DllRegisterServer. Требует параметра /i:строка
Полный путь к файлу библиотеки необходим в случае, если библиотека находится не в системном каталоге Windows. Также, при запуске без ключей, лишь с указанием библиотеки, regsvr32 по умолчанию пытается зарегистрировать библиотеку. Чтобы запустить регистрацию библиотеки из скрипта, обратитесь к разделу "Последовательное выполнение списка команд (AdvancedINF)" Интерпретатор AdvancedINF умеет самостоятельно выполнять регистрацию и отмену регистрации библиотек, используя параметры RegisterOCXs и UnregisterOCXs в выполняемой секции. Пример:
Для смены ассоциации файла с расширением *.INF необходимо выполнить следующие действия в проводнике Windows: В меню Сервис - Свойства папки выбрать вкладку Типы файлов. Далее в списке расширений выбрать INF - Сведения для установки, и в самом низу диалогового окна нажать кнопку Дополнительно. В появившемся окне свойств файла по умолчанию жирным шрифтом выбран пункт открыть. Чтобы сменить поведение файла при его открытии, выбираем пункт Установить, нажимаем кнопку По умолчанию и ОК. Теперь при двойном щелчке мышью на файле с расширением *.INF система по умолчанию выполнит написанный в нем скрипт.
Также для смены ассоциации файла можно воспользоваться редактором реестра.
Действие по умолчанию: Открыть
Синтаксис *.REG файла:
Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SOFTWARE\Classes\inffile\shell] @="open"
Синтаксис *.INF файла:
HKLM,"SOFTWARE\Classes\inffile\shell",,,"open"
Действие по умолчанию: Установить
Синтаксис *.REG файла:
Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SOFTWARE\Classes\inffile\shell] @="Install"
Замечательная статья! Создание точки отката реестра (AdvancedINF)- по всей видимости автор не дописал подраздел... Нет ли ссылок на матерьялы по этому подразделу?