Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

Секреты Windows: статьи о реестре, rundll32.exe, программах Недокументированные возможности Windows XP. MMC. Часть 5


Продолжение, начало в выпусках: 1 2 3 4

В конец записи

оцените: 1 2 3 4 5

Книга "Недокументированные возможности Windows XP. Библиотека пользователя", Глава 3. Консоль управления Microsoft. Часть 5. Оснастки Windows XP: Управляющий элемент WMI, продолжение

Создание контрольной точки восстановления Давайте продолжим рассмотрение темы восстановления системы и опишем код для автоматического создания точки восстановления. На этот раз будет приведена только часть кода, отвечающая за работу WMI, а не весь код скрипта. То есть, обращение к моникеру winmgmts и работа с классом. Вы самостоятельно можете модифицировать приведенный выше код для того, чтобы он мог, например, автоматически включать работу SystemRestore, если возможность восстановления системы отключена, а потом уже выполнять создание контрольной точки восстановления.

Листинг 3.02. Создание контрольной точки восстановления
Set obj =  GetObject("winmgmts:{impersonationLevel=impersonate}!root/default:SystemRestore")

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

ErrorSRCode = obj.CreateRestorePoint("Точка восстановления от " & Time(), 0, 100)

Энумерация содержимого ветви реестра Стандартные методы объекта для доступа к реестру (WScript.CreateObject("Wscript.Shell")), один из которых, позволяющий считывать значения параметров из реестра, мы рассмотрели в примере скрипта для включения/отключения восстановления системы на логических дисках компьютера, позволяют выполнить базовые операции с реестром. Но данный объект имеет один очень большой недостаток — с его помощью нельзя выполнить перечисление всех параметров, расположенных в определенной ветви реестра. Данный недостаток ограничивал возможности применения скриптов сервера сценариев Windows, поэтому просто нельзя не рассказать о новом свойстве инструментария Windows, которое выполняет именно эту операцию.

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

За выполнение перечисления параметров, расположенных в ветви реестра, отвечает метод ENUMVALUES, принадлежащий классу STDREGPROV. Данный класс определяет методы для доступа к реестру Windows XP (более функциональный аналог стандартного объекта Windows, рассмотренного нами выше) и принадлежит к пространству имен ROOT\DEFAULT. Мы не будем создавать целый работоспособный скрипт для описания работы данного метода — давайте лучше создадим отдельную процедуру, которая будет выполнять перечисление параметров указанной ветви реестра, а также проверим ее работу с помощью записи в лог-файл выводимых значений.

Листинг 3.03. Энумерация параметров ветви реестра
set objFS = CreateObject("Scripting.FIleSystemObject")

"Для вывода списка содержащихся в ветви реестра параметров мы будем
"использовать файл. В нашем случае — файл enum_log.txt на диске d:\

set objTextFile = objFS.CreateTextFile("d:\enum_log.txt", 8, True)

"подключаем объект

Set obj = GetObject("winmgmts:{impersonationLevel=impersonate}!root/Default:StdRegProv")

"переменная RootKey будет определять корневой раздел ветви, параметры
"которой мы будем перечислять. При этом корневые разделы идентифицирцются 
"в соответсвии с правилами, определенными в файле Winreg.h. В файле
"определены следующие корневые разделы: HKEY_CLASSES_ROOT (0x80000000),
"HKEY_CURRENT_USER (0x80000001), HKEY_LOCAL_MACHINE (0x80000002),
"HKEY_USERS (0x80000003), HKEY_CURRENT_CONFIG (0x80000005), HKEY_DYN_DATA
"(0x80000006). В нашем случае будет использоваться корневой раздел 
"HKEY_CURRENT_USER.

RootKey = &H80000001

"Вызываем процедуру, которая и будет выполнять перечисление параметров. Для
"работы процедуры необходимо три параметра: ветвь реестра, параметры которой
"нужно перечислять (в нашем случае Control Panel\Desktop), объект,
"определяющий текстовый документ, в который будут записываться параметры
"ветви, а также корневой раздел указанной ранее ветви, записанный в нашем
"случае в параметре RootKey. После работы процедуры закрываем открытый
"текстовый файл.

call EnumV("Control Panel\Desktop", objTextFile, RootKey)
objTextFile.Close


Sub EnumV(Path, objTextFile, RootKey)


 objTextFile.WriteLine " :::: Ветвь реестра: HKEY_CURRENT_USER\" & Path & vbCrLf

"Выполняем перечисление параметров, расположенных в ветви реестра 
"HKEY_CURRENT_USER\Control Panel\Desktop. Для этого используется метод 
"EnumValues для работы которого необходимы следующие параметры:
" - Корневой раздел ветви (в нашем случае параметр RootKey)
" - Остальной путь к ветви реестра (в нашем случае параметр RootKey,
"указываемый при вызове процедуры)
" – Переменная, в которую будут помещаться содержащиеся в ветви реестра
"параметры. В нашем случае назовем эту переменную Names
" – Переменная, в которую будет помещаться идентификатор типа параметра.
"В нашем случае назовем ее Types.

 obj.EnumValues RootKey, Path, Names, Types

"Проверяем, существуют ли в указанной ветви реестра параметры. Во-первых,
"проверяется равенство нулю переменной Names, содержащей названия
"параметров. А во вторых, проверяем на равенство нулю переменную Types.
"Переменные нужно проверять именно на равенство нулю, так как ноль
"возвращается методом EnumValues в случае происхождения ошибки.

 if not IsNull(Names) and not IsNull(Types) Then

"Выполняем цикл, количество итераций которого указывается границамм
"переменной types (количеством элементов в переменной types, так как это
"массив). То есть, выполняем цикл столько раз, сколько переменных было
"найдено в указанной ветви реестра.

     for i = lbound(types) to ubound(types)

"При этом мы будем выполнять запись в текстовый файл, в зависимости
"от типа переменной, укаазанного в переменной types. Для этого мы будем
"использовать выражение select case из-за особенности метода EnumValues.
"Особенностью этого метода является способ указания типа найденной
"переменной. Для этого используется массив types (в нашем случае), в
"в который помещаются идентификаторы типа переменной, определенные
"в файле Winreg.h. Возможны следующие идентификаторы:
"1 – определяет переменную строкового типа;
"2 – определяет переменную расширенного строкового типа;
"3 – определяет переменную типа REG_BINARY;
"4 – определяет переменную типа REG_DWORD;
"7 – определяет переменную типа REG_MULTI_SZ;

  select case types(i)

"Порверяем тип параметра и в зависимости от этого типа используем
"разный метод для получения значения параеметра. Все методы для
"получения значений параметров реестра также описаны в классе
"StdRegProv. Мы используем следующие методы.
"GetStringValue — получение значения строкового типа.
"GetExpandedStringValue — получение значения расширенного строкового типа.
"GetBinaryValue — получение значения параметра типа REG_BINARY.
"GetDWordValue — получение значения параметра типа REG_DWORD.
"GetMultiStringValue — получение значения параметра типа REG_MULTI_SZ.
"Все эти методы используют для своей работы следующие переменные:
"идентификатор корневого раздела ветви реестра, остальной путь к ветви
"реестра, имя параметра (в нашем случае элемент массива names), а также
"название переменной, в которую будет считываться значение данного
"параметра.

      case 1
   obj.GetStringValue RootKey, path, names(i), value

"После считывания значения параметра, мы проверяем, не произошла ли ошибка
"при считывании (как обычно, значение нуль в переменной). И если ошибки нет,
"мы записываем параметр и его значение в текстовый файл. Аналогично
"выполняется работа и с другими типами параметров, поэтому их мы описывать
"не будем.

   If not isnull(names(i)) or not isnull(value) then
       objTextFile.WriteLine  names(i) & " = REG_SZ: " & value
   end if
      case 2
   obj.GetExpandedStringValue RootKey, path, names(i), value
   if not isnull(names(i)) or not isnull(value) then
       objTextFile.WriteLine names(i) & " = REG_EXPAND_SZ: " & value
   end if
      case 3
   obj.GetBinaryValue RootKey, path, names(i), value
   for j = lbound(value) to ubound(value)
       value(j) = hex(cint(value(j)))
   next
   if not isnull(names(i)) or not isnull(value) then
       objTextFile.WriteLine names(i) &" = REG_BINARY : "& _
           join(value, ",")
   end if
      case 4
   obj.GetDWordValue RootKey, path, names(i), value
   if not isnull(names(i)) or value then
       objTextFile.WriteLine names(i) & " = REG_DWORD : " & _
           hex(value)
   end if
      case 7
   obj.GetMultiStringValue RootKey, path, names(i), value
   for j = lbound(value) to ubound(value)
       value(j) = value(j)
   next
   if not isnull(names(i)) or not isnull(value) then
       objTextFile.WriteLine names(i) &" = REG_MULTI_SZ : "& _
           join(value, ",")
   end if
  end select
     next
 end if

    End Sub

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

  • CreateKey. Данный метод создает подраздел в ветви реестра. Для его вызова необходимы следующие два параметра: идентификатор корневого раздела ветви реестра (аналог переменной ROOTKEY приведенного скрипта), а также остальной путь к ветви реестра, которую нужно создать (в том числе и сам создаваемый подраздел реестра).

    Если идентификатор корневого раздела не указан, тогда будет использоваться стандартный идентификатор &H80000002, говорящий о том, что ветвь находится в корневом разделе HKEY_LOCAL_MACHINE.

  • DeleteKey. Данный метод удаляет подраздел в ветви реестра. Для его вызова также необходимы следующие два параметра: идентификатор корневого раздела ветви реестра (аналог переменной ROOTKEY приведенного скрипта), а также остальной путь к ветви реестра, которую нужно удалить (в том числе и сам удаляемый подраздел реестра).
  • EnumKey. В скрипте мы рассмотрели метод для энумерации параметров указанной ветви реестра, этот же метод возвращает подразделы, вложенные в указанную ветвь реестра. Для его работы необходимы следующие параметры: идентификатор корневого раздела ветви реестра (аналог переменной ROOTKEY приведенного скрипта), остальной путь к ветви реестра, подразделы которой нужно перечислить, а также переменную, используемую для хранения массива найденных в указанной ветви подразделов (например, аналог переменной NAMES нашего скрипта).
  • DeleteValue. Данный метод удаляет указанный параметр из ветви реестра. Для его работы необходимо указать следующие три параметра: идентификатор корневого раздела ветви реестра (аналог переменной ROOTKEY приведенного скрипта), остальной путь к ветви реестра, содержащей удаляемый параметр, а также название удаляемого параметра (если название не указано, тогда будет удалено значение параметра по умолчанию).
  • SetDWORDValue. Данный метод создает или изменяет указанный параметр DWORD-типа в ветви реестра. Для его работы необходимо указать следующие четыре параметра: идентификатор корневого раздела ветви реестра (аналог переменной ROOTKEY приведенного скрипта), остальной путь к ветви реестра, содержащей изменяемый параметр, название изменяемого параметра (или создаваемого), а также новое значение, которое необходимо присвоить указанному параметру. Если название изменяемого параметра указано не будет, тогда изменить значение параметра по умолчанию данной ветви реестра.
  • CheckAccess. Данный метод определяет, разрешен ли пользователю доступ к указанной ветви реестра. Если метод выполнился успешно, тогда метод возвратит значение 0, иначе любое другое значение. Для работы данного метода необходимы следующие четыре параметра: идентификатор корневого раздела ветви реестра (аналог переменной ROOTKEY приведенного скрипта), остальной путь к ветви реестра, права на которую необходимо проверить, флаг для определения проверяемых прав, а также переменная, в которую будет помещен результат выполнения метода (если значение данной переменной будет равно TRUE, тогда пользователь обладает нужными правами на данную ветвь реестра, иначе возвращается значение FALSE).

Флаг для определения проверяемых прав является битовой маской, значения которой определены в файле Winnt.h. Данный флаг может содержать следующие значения.

  • 0X0001 — KEY_QUERY_VALUE (разрешено запрашивать значения из дочерних подразделов нашей ветви реестра).
  • 0X0002 — KEY_SET_VALUE (разрешено создание, удаление и установка значений параметров нашей ветви реестра).
  • 0X0004 — KEY_CREATE_SUB_KEY (разрешено создание и удаление дочерних подразделов нашей ветви реестра).
  • 0X0008 — KEY_ENUMERATE_SUB_KEYS (разрешена энумерация дочерних подразделов нашей ветви реестра).
  • 0X0010 — KEY_NOTIFY (разрешен вывод подтверждения на запрос изменения параметров или дочерних подразделов нашей ветви реестра).
  • 0X0020 — KEY_CREATE_LINK (используется системой).
  • 0x00010000 — DELETE (разрешено удаление).
  • 0x00020000 — READ_CONTROL.
  • 0X00040000 — WRITE_DAC.
  • 0X00080000 — WRITE_OWNER (разрешено изменение владельца ветви).

Также в классе STDREGPROV описаны методы SETBINARYVALUE, SETEXPANDEDSTRINGVALUE, SETMULTISTRINGVALUE, SETSTRINGVALUE, но мы их описывать не будем, так как их вызов аналогичен вызову описанного выше метода SETDWORDVALUE.

Подробнее о классе StdRegProv можно узнать из стандартного файла Windows XP regevent.mfl, расположенного в каталоге %systemroot%\SYSTEM32\wbem.

Создание, завершение и просмотр учетной записи процесса К другим основным возможностям инструментария управления WMI относятся возможности работы с процессами, запущенными на удаленном или локальном компьютере. При этом инструментарий предоставляет возможности не только по запуску или завершению процесса, но и по определению учетной записи, от имени которой запущен определенный процесс. Для работы с процессами используется класс WIN32_PROCESS, принадлежащий к пространству имен ROOT\CIMV2. Давайте рассмотрим маленький пример по созданию нового процесса с использованием метода CREATE.

Листинг 3.04. Создание нового процесса
set obj = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\.\root\cimv2:Win32_Process")

obj.Create "C:\WINDOWS\regedit.exe"

Действительно маленький пример. А теперь давайте подробнее рассмотрим методы класса WIN32_PROCESS, направленные на работу с процессами.

  • Create. Как мы уже знаем, данный метод используется для создания процесса. При этом после своего выполнения данный метод возвращает следующие значения (это не все): 0 (успешное завершение), 2 (пользователь не имеет доступа к запрашиваемым данным), 3 (у пользователя нет достаточных привилегий), 8 (неизвестная ошибка), 9 (пользователь не имеет необходимых привилегий), 21 (указан недопустимый параметр). Несмотря на то, что при вызове данного метода мы использовали только один параметр, на самом деле для работы с методом используется четыре параметра. Во-первых, это путь к файлу, который будет вызван (в нашем случае мы использовали только этот параметр). Во-вторых, это путь к каталогу, который должен использоваться вызываемым процессом (если он не задан, тогда будет использоваться каталог, в котором находится запускаемый файл). В-третьих, этот строка начальной конфигурации процесса (если она не задана, тогда будет использоваться пустая строка (\"\")). В-четвертых, это переменная, которой будет присвоен идентификатор созданного нами процесса.
  • Terminate. Прекращает процесс и все дочерние процессы этого процесса.
  • GetOwner. Возвращает учетную запись пользователя, от имени которого был запущен процесс, а также домен, к которому он принадлежит.
  • GetOwnerSid. Возвращает SID пользователя, от имени которого был запущен процесс.
  • SetPriority. Устанавливает приоритет выполнения определенного процесса.
  • AttachDebugger. Вызывает отладчик данного процесса.

За более детальной информацией обращайтесь к файлу cimwin32.mfl, расположенному в каталоге %systemroot%\SYSTEM32\wbem.

Выключение, перезагрузка компьютера, завершение сеанса пользователя Также с помощью инструментария WMI можно выключить удаленный или локальный компьютер, перезагрузить его или завершить сеанс текущего пользователя. Давайте рассмотрим пример завершения сеанса текущего пользователя на локальном компьютере (если у вас есть удаленный компьютер, тогда при подключении к пространству имен вместо точки необходимо указать его имя). Особенность данного примера состоит в другом способе подключения к классу — с помощью базы данный CIMOM.

Листинг 3.05. Завершение сеанса пользователя компьютера
'подключаемся к пространству имен root\cimv2

set objWMIService = GetObject("winmgmts:" & "{impersonationLevel =  impersonate}!\\.\root\cimv2")

'Выполняем SQL-запрос для подключения к классу

set colSoftware = objWMIService.ExecQuery("Select * from Win32_OperatingSystem")

'вызываем метод для завершения сеанса пользователя. Данный метод для своей
'работы использует один параметр (точнее, два, но второй параметр на данный
'момент не используется) – флаг, указывающий на необходимое действие. В
'нашем случае флаг равен 0, что говорит о необходимости завершения сеанса
'пользователя. Для осуществления возможности перезагрузки или выключения
'компьютера необходимо, чтобы инициирующий перезагрузку процесс обладал
'правом SE_SHUTDOWN_NAME. Остальные значения флага определяются от бита
'установленного в нем. Биты описаны следующим образом: "Завершение работы",
'"Перезагрузка", "Принудительно", "Питание выключено"

for each objSoftware in colSoftware
   objSoftware.Win32Shutdown 0
next

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

Кроме метода WIN32SHUTDOWN класс WIN32_OPERATINGSYSTEM содержит описание еще трех методов.

  • Reboot. Если вызывающий процесс обладает правом SE_SHUTDOWN_NAME, тогда будет выполнена перезагрузка компьютера. Метод не имеет параметров, но при успешном выполнении возвращает 0.
  • Shutdown. Если вызывающий процесс обладает правом SE_SHUTDOWN_NAME, тогда будет выполнено выключение компьютера. Метод не имеет параметров, но при успешном выполнении возвращает 0.
  • SetDateTime. Если вызывающий процесс обладает правом SE_SYSTEMTIME_NAME, тогда будет выполнена установка системного времени компьютера. Данный метод для своей работы требует один параметр, определяющий новое время, которое нужно установить (имеет тип DATETIME имеющий довольно странный формат, например, установка данного параметра равным "00000000000000.000000:000" обнуляет время).

Получение сведений об установленных на компьютере программах Это еще одна интересная возможность WMI, которой можно воспользоваться. То есть, вы можно удаленно узнавать о том, установлена ли на компьютере какая-либо программа, когда она была установлена, а также просмотреть весь список установленных на компьютере программ. Давайте для примера попробуем создать текстовый файл, содержащий в себе сведения об установленных на компьютере программах, их описании, а также дате установки. В приведенном ниже коде будет использоваться еще одна возможность WMI — получение сведений непосредственно из ее базы данных.

Листинг 3.03. Создание списка установленных на компьютере программ
'объявляем объект для доступа к файловой системе, а потом создаем файл,
'в который будут записываться сведения о установленных на компьютере 
'программах (например, файл Program_list.txt в каталоге e:\)

set objFSO = CreateObject("Scripting.FIleSystemObject")
set objTextFile = objFSO.CreateTextFile("e:\Program_list.txt", True)

'подключаемся к пространству имен root\cimv2

set objWMIService = GetObject("winmgmts:" & "{impersonationLevel = impersonate}!\root\cimv2")

'Выполняем SQL-запрос на получение всех записей из таблицы Win32_Product
'Конечно, можно было бы использовать SQL-запрос для получения только
'отдельных записей или колонок таблицы, но для примера нам такой сложный
'запрос не нужен

set colSoftware = objWMIService.ExecQuery("Select * from Win32_Product")

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

for each objSoftware in colSoftware
   objTextFile.WriteLine "- Программа:   " & objSoftware.Caption
   objTextFile.WriteLine "Описание: " & objSoftware.Description
   objTextFile.WriteLine "Установлена:   " & objSoftware.InstallDate2
next
objTextFile.Close

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

  • objSoftware.IdenttifyiungNumber. Серийный номер программы;
  • objSoftware.InstallLocation. Каталог, в который установлена программа;
  • objSoftware.Name. Название программы, как правило, не отличается от objSoftware.Caption;
  • objSoftware.Vendor. Производитель программы;
  • objSoftware.Version. Версия программы;

Продолжение следует

Оригинал статьи: http://www.onestyle.com.ua/txt.php?u=146

В избранное