Тема: Командные файлы и сценарии JScript, совмещённые с файлами реестра
На сайте «Rob van der Woude's Scripting Pages» есть пример командного файла, использующего себя как файл реестра:
REGEDIT4
; @ECHO OFF
; CLS
; REGEDIT.EXE /S "%~f0"
; EXIT
[HKEY_CURRENT_USER\Software\Test]
"TestVal"="Succeeded"
— первой строкой должна быть «REGEDIT4», иначе не будет распознан формат файла реестра; при этом заголовок «Windows Registry Editor Version 5.00» файлов реестра в кодировке Unicode использовать нельзя, т.к. командные файлы не могут быть в Unicode. Поскольку, скорее всего, в текущем каталоге и в каталогах, перечисленных в переменной окружения %PATH%, нет исполняемого файла с именем REGEDIT4, эта строка вызовет сообщение об ошибке (поэтому в примере следом идёт команда очистки окна), но работу командного файла не прервёт (работу командного файла могут прервать лишь синтаксические ошибки в нём);
— точка с запятой является признаком начала комментария в файлах реестра, а с точки зрения обработчика командной строки она (как и запятая) приравнена к пробелу и не мешает исполнению следующей за ней команды (от себя скажу, что это излишняя предосторожность — см. далее).
Ну и для порядка совсем очевидное:
— «REGEDIT.EXE /S "%~f0"» заставляет редактор реестра добавить в реестр данные из самого командного файла, рассматриваемого как файл реестра; ключ /S отключает вывод диалоговых окон подтверждения и успешности действия;
— команда EXIT (я: лучше EXIT /B) завершает работу командного файла и предотвращает попытки исполнения следующих за ней строк в формате файла реестра как строк командного файла.
Если всё же в текущем каталоге или в каталогах, перечисленных в переменной окружения %PATH%, окажется исполняемый файл с именем REGEDIT4, то последствия могут быть непредсказуемыми.
--------------------
От этой превратности застрахованы сценарии JScript, совмещённые с файлами реестра. В этом случае:
— для сокрытия строк JScript от редактора реестра (на самом деле это необязательно) по-прежнему годится точка с запятой: она будет рассматриваться JScript как признак конца оператора начатого на предыдущей строке или просто пустого оператора;
— для сокрытия строк файла реестра (кроме его заголовка — первой строки файла) от JScript (это обязательно) используем блочный комментарий (открывающая «/*» и закрывающая «*/» скобки которого в свою очередь могут быть скрыты от редактора реестра точками с запятыми) — это вопросов не вызывает;
— в качестве первой строки файла (заголовка файла реестра) по прежнему нельзя использовать «Windows Registry Editor Version 5.00», т.к. эта строка ничему не соответствует в синтаксисе JScript, поэтому нельзя использовать кодировку Unicode; первой строкой может быть только «REGEDIT4», которая соответствует идентификатору переменной или функции в JScript.
Предположим, мы скрываем от редактора реестра точками с запятыми все строки JScript. В таком случае в первой строке мы получаем оператор «REGEDIT4», представляющий собой выражение возвращающее значение переменной REGEDIT4. Это не вызовет ошибку, если на глобальном уровне будет объявлена переменная или функция с таким именем:
REGEDIT4
;var REGEDIT4
;var WshShell = new ActiveXObject("WScript.Shell")
;WshShell.Popup("Будет создан ключ реестра HKEY_CURRENT_USER\\_Test")
;WshShell.Run("regedit.exe \"" + WScript.ScriptFullName + "\"")
;/*
[HKEY_CURRENT_USER\_Test]
@="JS + REG = Hello, world!"
;*/
Впрочем, опыт показывает, что если в файле реестра имеются строки ошибочные с точки зрения его формата, то это не препятствует обработке правильных строк и этот пример можно переписать с меньшими предосторожностями:
REGEDIT4
= void null; delete REGEDIT4 /* можно и не удалять, а использовать переменную */;
//или вместо предыдущей строки:
//(); function REGEDIT4() {/* может быть и какой-нибудь код */}
var WshShell = new ActiveXObject("WScript.Shell");
WshShell.Popup("Будет создан ключ реестра HKEY_CURRENT_USER\\_Test");
WshShell.Run("regedit.exe \"" + WScript.ScriptFullName + "\"");
/*
[HKEY_CURRENT_USER\_Test]
@="JS + REG = Hello, world!"
*/