Область состояния панели задач Windows — полезная вещь: в ней отображаются значки различных полезных программ типа антивируса и Windows Update, работающих в фоновом режиме. Благодаря области состояния мы всегда знаем, какие программы выполняются на компьютере. Но со временем в области состояния появляется все больше значков. Здесь и программы, следящие за накопителями CD-ROM и DVD, и блокировка рекламы и всплывающих окон, и управление загрузкой файлов из Internet, и еще много всего. А ведь еще множество программ работают в фоновом режиме, и они нигде не показывают свои значки.

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

Каталог автозапуска

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

При начале сеанса работы пользователя Windows выполняет запуск всех программ, помещенных в каталоги автозапуска. Их список можно просмотреть: Пуск/Все программы/Автозагрузка. В этом списке содержатся ярлыки программ, запускаемых для текущего пользователя, а также программ из общего каталога для всех пользователей данного компьютера All Users. Как правило, содержимое этих меню соответствует содержимому подкаталогов Главное менюПрограммыАвтозагрузка — каталога %USERPROFILE% для данного пользователя и каталога %ALLUSERSPROFILE% для всех пользователей (%USERPROFILE%start menuprogramsstartup и %ALLUSERSPROFILE%start menuprogramsstartup).

Запуск приложений через реестр

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

В реестре имеется несколько разделов, предназначенных для автоматического запуска приложений. Список этих разделов содержится в статье «Где найти программы автоматического запуска», опубликованной в Windows & .NET Magazine/RE № 2 за 2003 год (http://www.osp.ru/win2000/2003/02/096.htm). Подавляющее большинство программ используют разделы Run и RunOnce, каждый из которых существует в двух вариантах — для конкретного пользователя и для всех пользователей. Раздел Run применяется для запуска приложений в начале каждого сеанса работы пользователя. Раздел RunOnce позволяет выполнить однократный запуск приложения при регистрации пользователя, после чего программа автоматически удаляется из списка; таким образом, программа запускается всего один раз. Раздел RunOnсe обычно используется различными программами установки для запуска программ, завершающих процесс установки или удаления приложения. Для текущего сеанса пользователя раздел Run имеет путь HKEY_CURRENT_USERSoftwareMicrosoftWindows CurrentVersionRun, раздел RunOnce — HKEY_CURRENT_USERSoftwareMicrosoftWindows CurrentVersionRunOnce. Общие для всех пользователей компьютера разделы Run и RunOnce расположены в HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindows CurrentVersionRun и HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindows CurrentVersionRunOnce.

DumpStartups.pl

Программа DumpStartups.pl помогает управлять списком приложений, запускающихся в начале сеанса работы пользователя. Этот сценарий задействует для работы несколько модулей и расширений (бесплатных), которые по умолчанию обычно не устанавливаются. Список этих модулей и расширений приведен в табл. 1 с указанием, откуда их можно загрузить. На сайте ActiveState (http://www.activestate.com) можно бесплатно загрузить ActivePerl.

Для экономии места в листинге1приведены только наиболее важные фрагменты кода сценария, в которых происходит обработка. Полный код сценария можно получить на сайте.

В приведенном листинге 1 в метке А выполняется загрузка библиотеки Shell32.dll и обращение к функции SHGetFolderPath() для получения имен каталогов автозагрузки для текущего пользователя и для всех пользователей компьютера. При этом присваиваются значения тех переменных, которые понадобятся в дальнейшем для работы сценария.

Современные версии Windows (Windows Server 2003, Windows XP, Windows 2000 и, в некоторых случаях, Windows NT 4.0) поддерживают переменную среды pathext, определяющую список расширений исполняемых файлов, за исключением .pif и .lnk. Приведенный в метке B фрагмент кода позволяет сценарию определить, поддерживается ли в системе переменная среды pathext. Если нет, программа создает собственную переменную среды со значениями .bat, .cmd, .com и .vbs. Затем она формирует массив расширений имен файлов и собирает все расширения обратно в одну строку с символом «|» (вертикальная линия) в качестве разделителя. Далее подпрограмма использует полученную строку в качестве регулярного шаблона для определения того, что имя файла является именем исполняемого модуля.

Фрагмент кода по метке C определяет запускаемые элементы из реестра и с системного диска. Далее во фрагменте кода по метке D, в зависимости от указанных в командной строке параметров запуска программы, производится либо вывод списка запускаемых программ на экран, либо удаление запускаемых программ из реестра.

Приведенная во фрагменте по метке E подпрограмма ProcessKey() перечисляет все значения, хранящиеся в указанном разделе реестра, и создает анонимный хеш, содержащий значения и связанную с ними информацию. Этот хеш сохраняется в массиве @ValueList. Данный массив возвращается в вызывающую процедуру в конце подпрограммы.

Подпрограмма ProcessDir() выполняет для указанного каталога автозагрузки то же, что ProcessKey() для разделов реестра, — собирает массив имен всех файлов в указанном каталоге и его подкаталогах. Сценарий передает в подпрограмму имена каталогов автозагрузки текущего пользователя и каталога All Users. При обнаружении ярлыков подпрограмма определяет свойства ярлыка с помощью вызова расширения Win32::Shortcut (метка F). Далее сценарий определяет описание и имя запускаемой программы. Если описание отсутствует, сценарий выдает имя запускаемого файла. Если подпрограмма ProcessDir() обнаруживает исполняемый файл, производится попытка извлечь информацию о файле (фрагмент G). В конце концов подпрограмма сохраняет собранные данные в массив @ValueList и возвращает его в вызывающую процедуру.

Когда пользователь указывает элемент, который следует удалить, сценарий вызывает подпрограмму Remove(). Эта подпрограмма, приведенная во фрагменте H, определяет тип программы — раздел реестра или файл на диске. Если элемент представляет собой элемент реестра (то есть параметр раздела), сценарий удаляет этот элемент из реестра. Если элемент является файлом, сценарий удаляет файл с системного диска. Эти операции необратимы. Удаляемые файлы и значения реестра в «Корзину» не попадают.

Подпрограмма GetSpecialDirectory() возвращает путь к указанному каталогу. Например, каталог «Мои документы» может быть размещен на локальном диске или в общей папке на удаленном сервере. Эта подпрограмма определяет точное местонахождение каталога. Приведенный в метке I код получает значение CSLID. CSLID определяет специальные каталоги Windows (такие, как «Мои документы», временные файлы Internet). Список значений CSLID можно найти, например, в файле shlobj.h из Windows SDK. Подпрограмма GetSpecialDirectory() вызывает функцию SHGetFolderPath(), определяющую, загружался ли сценарий раньше. Функция GetSpecialDirectory() сначала выделяет буфер (переменная $pszPath) для сохранения имени каталога. Возвращаемое имя файла представлено в кодировке Unicode. Сценарий очищает полученную строку от всех символов с кодом NUL (x00), преобразуя ее тем самым в формат ANSI.

Такое псевдопреобразование из Unicode в ANSI — довольно сомнительный трюк. Если в названии каталога присутствуют символы Unicode (например, русские буквы), то удаление символов с кодом NUL даст неприемлемый результат, и получившийся путь будет ошибочным. Этот трюк применяется в том случае, если используемая версия Perl не поддерживает Unicode и строки UTF-8. Если потребуется, можно переписать эту процедуру для поддержки строк Unicode в Perl.

Выполнение сценария

Если запустить DumpStartups.pl без указания параметров командной строки, сценарий просто выводит на экран список запускаемых элементов с порядковыми номерами. Для удаления определенного элемента следует вновь запустить сценарий с ключом /r и номером удаляемого элемента. Так, для удаления элементов под номерами 3 и 8 достаточно выполнить команду

perl DumpStartups.pl /r 3 /r 8

После удаления элементов порядковые номера могут измениться, поэтому перед повторным запуском сценария для удаления следующих элементов надо запустить его без параметров, для обновления номеров элементов.

Все под контролем!

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