Запуск windows powershell с помощью wmi что это такое

Блог компании RUVDS.com, Системное администрирование, Разработка под Windows, Системное программирование, PowerShell


Рекомендация: подборка платных и бесплатных курсов таргетированной рекламе — https://katalog-kursov.ru/

В операционных системах Windows поддерживаются различные объектные инфраструктуры. Для доступа к ним можно использовать интерфейсы прикладного программирования (API), но разработка полноценных приложений не всегда оправдана. В PowerShell существуют специальные командлеты, позволяющие обращаться к объектам .NET, COM, WMI (CIM) и ADSI в интерактивном режиме. В четвертой части цикла мы изучили основы с упором на классы .NET Core, а сейчас хотим углубить тему и разобрать особенности взаимодействия PowerShell с внешними объектами.

Оглавление:

Работа с JSON, XML и CSV
Работа с WMI и CIM
Работа с COM-объектами
Работа со службой каталогов ADSI
Форматирование вывода

Работа с JSON, XML и CSV

В сценариях PowerShell довольно часто приходится разбирать данные в форматах JSON, XML и CSV. Обычно такая необходимость возникает при работе с интернет-сервисами или с конфигурационными файлами. Некоторые администраторы пытаются парсить данные с помощью регулярных выражений, но идти на такие жертвы необязательно: в PowerShell есть специальные командлеты для конвертации, притом в обе стороны.

Формат JSON позволяет описывать разнообразные объекты и по сути представляет собой допускающую вложенность хэш-таблицу. Соответственно преобразовать объект JSON в объект .NET при помощи PowerShell несложно. Поскольку интернет-сервисы обычно отдают вместо красиво отформатированного файла очень длинную строку, это преобразование может пригодиться и для работы в интерактивном режиме. В примере ниже для описания объекта JSON мы использовали многострочную текстовую переменную:

$user = @"
{
   "firstName": "Ivan",
   "lastName": "Danko",
   "address": {
       "streetAddress": "Kremlin",
       "city": "Moscow"
   },
   "phoneNumbers": [
       "+7 495 1234567",
       "+7 499 1234567"
   ]
}
"@ | ConvertFrom-Json

Обратная задача решается сходным образом:

$file = Get-ChildItem C:WindowsSystem32notepad.exe
$file.VersionInfo | ConvertTo-Json

Полученную строку в формате JSON нетрудно отправить другому приложению по сети. Это может быть, например, некий RESTful сервис. Работа с командлетами ConvertFrom-Csv, ConvertTo-Csv и ConvertTo-Xml строится примерно так же, предлагаем читателям изучить ее самостоятельно.

Для работы с XML и CSV нам потребуются и другие командлеты:

Используя эти инструменты нужно понимать, что преобразование бинарного объекта в текстовый формат сохраняет только значение его свойств, но не методы. Преобразование данных в формате JSON, XML или CSV в объект .NET с помощью PowerShell возможно, только если они валидны.

Работа с WMI и CIM

Windows Management Instrumentation (WMI) — это разработанная в Microsoft и адаптированная под Windows реализация стандарта WBEM (Web-Based Enterprise Management). В его основе лежит идея создания универсального решения для мониторинга распределенной информационной среды предприятия и управления ее компонентами. Структура данных WBEM в свою очередь основана на Common Information Model (CIM), реализующей объектно-ориентированный подход к представлению компьютерных систем. Дальнейшая разработка и поддержка WMI в Windows прекращена, Microsoft рекомендует использовать для управления инфраструктурой сходный механизм — объекты CIM. Для работы ними в PowerShell 3.0 появились специальные командлеты, которые мы будем рассматривать параллельно с аналогами для WMI. Если в коде есть вызовы командлетов для работы с WMI, его по возможности стоит переписать.

В рамках модели CIM (она же используется в WMI) данные операционной системы представлены в виде классов со свойствами и методами. Классы группируются в иерархически упорядоченные и логически связанные по технологии или области управления пространства имен. Существует корневое пространство имен Root, в котором имеются подпространства: CIMv2, Default, Secutiry и WMI. Для однозначной идентификации экземпляра класса (объекта) и описания состояния соответствующего ему ресурса используются свойства класса, которые обычно доступны только для чтения. Для управления ресурсом используются методы.

К экземпляру класса можно обратиться по полному пути, который имеет следующий вид:

[\ComputerNameNameSpace][:ClassName][.KeyProperty1=Value1][,KeyProperty2=Value2]…]

где
ComputerName — имя компьютера;
NameSpace — пространство имен;
ClassName — имя класса;
KeyProperty1=Value1, KeyProperty2=Value2 — свойства объекта и значения, по которым он идентифицируется.

До появления PowerShell простого инструмента работы с WMI не существовало. Для доступа к объектам приходилось писать довольно сложные программы на высокоуровневых языках (C++, Visual Basic, Java Script) либо изучать оболочку WMIC (WMI Command Line, поддержка которой также прекращена) с собственным языком. Через PowerShell объекты WMI доступны рядовому пользователю из командной строки или в сценариях. Для начала подключимся к подсистеме WMI и получим список доступных классов с помощью командлета Get-WmiObject (псевдоним gwmi). Чтобы получить список классов CIM, используйте командлет Get-CimClass.

Get-CimClass
Get-WmiObject -List

Мы вывели список классов на локальном компьютере, но можно подключиться и к удаленному:

Get-CimClass -ComputerName IP-адрес 
Get-CimClass -ComputerName Имя_компьютера

или

Get-WmiObject -ComputerName IP-адрес -List
Get-WmiObject -ComputerName Имя_компьютера -List

По умолчанию командлеты Get-CimClass и Get-WmiObject подключаются к пространству имен RootCIMV2, в котором хранится большое количество классов для управления системой. Для смены пространства имен применяется параметр -Namespace:

Get-CimClass -Namespace Root
Get-WmiObject -Namespace Root -List

Зная имя класса, нетрудно получить его экземпляры. Следующая команда возвращает все экземпляры Win32_Service, т.е. зарегистрированные на локальной машине службы:

Get-WmiObject Win32_Service

Как и в случае с объектами других типов, список свойств и методов выводится при помощи Get-Member. К методам объекта WMI можно обращаться напрямую или с помощью командлета Invoke-WmiMethod. Также к объектам WMI можно применять командлеты для сортировки, фильтрации, группировки и т.д.

Get-WmiObject Win32_Service | Get-Member

Для получения объектов (экземпляров классов) CIM используется командлет Get-CimInstance. В отличие от WMI, результирующие CIM-объекты (resultant object или экземпляры класса) не содержат методов класса. Поскольку извлечь метод непосредственно невозможно, придется вызывать командлет Invoke-CimMethod. Рассмотрим класс Win32_Service — запущенные в системе службы) и его экземпляр для службы spooler на локальной машине:

Get-CimInstance Win32_service -filter "Name='spooler'" 

Посмотрим на структуру результирующего объекта:

Get-CimInstance Win32_service -filter "Name='spooler'" | Get-Member

На этом этапе преимущества командлетов для работы с объектами CIM неочевидны. Они в первую очередь касаются удаленной работы в распределенной среде и будут подробно рассмотрены в последней статье цикла, посвященной решению практических задач администрирования.

Есть и специфичный для WMI инструментарий: язык запросов WMI Query Language (WQL), напоминающий SQL. WQL-запрос для поиска всех стартующих при запуске системы служб выглядит так:

select * from win32_service where startmode="Auto"

Из PowerShell они выполняется следующим образом:

Get-WmiObject -Query 'select * from win32_service where startmode="Auto"'

Работа с COM-объектами

Для обеспечения взаимодействия между приложениями в Windows была разработана технология связывания и внедрения объектов (Object Linking and Embedding или OLE). Позже появилась технология OLE Automation, с помощью которой приложения клиенты автоматизации могли вызывать функции других приложений — серверов автоматизации. OLE и OLE Automation были основаны на базовой технологии Component Object Model (COM), которая предлагает единый двоичный стандарт для программных компонентов. Созданные по нему и зарегистрированные в операционной системе объекты могут использоваться в других приложениях с помощью исполняемых файлов или динамических библиотек.

Примерно с середины девяностых годов вместо OLE стал использоваться другой термин — ActiveX. До появления платформы .NET технология ActiveX считалась ключевой, а объекты COM до сих пор активно используются для интеграции приложений в Windows — многие продукты Microsoft и сторонних разработчиков являются серверами автоматизации и предоставляют через них доступ к своим сервисам. Для обращения к объектам используется ProgID — символьный идентификатор, который присваивается им при регистрации в реестре Windows. Он имеет следующий вид:

Библиотека_типов.Класс.Версия

Версия обычно не указывается:

Библиотека_типов.Класс

Несколько примеров доступных ProgID: InternetExplorer.Application (приложение Internet Explorer), Word.Application (приложение Microsoft Word), WScript.Shell (класс Shell из объектной модели сервера сценариев Windows Script Host или WSH).

Создать экземпляр объекта можно с помощью рассмотренного в предыдущей статье командлета New-Object, а посмотреть его структуру — с помощью Get-Member:

$myshell = New-Object -ComObject WScript.Shell
$myshell | Get-Member

Для работы с объектами используются свойства и методы. Скажем, чтобы создать на рабочем столе пользователя ярлык, нужно вызвать метод CreateShortcut():

$link = $myshell.CreateShortcut("$HomeDesktopHome.lnk")

Обратите внимание, что ярлык — это тоже объект COM:

$link | Get-Member

Нам остается заполнить его свойства и сохранить:

$link.TargetPath = $Home
$link.Save()

Таким способом мы создали ярлык на рабочем столе активного пользователя, а теперь разберем работу с внешними сервисами автоматизации на примере COM-объекта Shell.Application. С его помощью можно автоматизировать некоторые действия в проводнике Windows:

$myshell=New-Object -ComObject Shell.Application

или для краткости:

$myshell=New-Object -com Shell.Application
$myshell | Get-Member

У объекта Shell.Application есть довольно много различных методов управления окнами. К примеру, для отображения содержимого заданного каталога используется Explore():

$myshell.Explore("c:")

Справочная система вызывается с помощью метода Help():

$myshell.Help()

Есть также три метода для вызова диалоговых окон поиска: FindFiles(), FindComputer() и FindPrinter().

$myshell.FindFiles()
$myshell.FindComputer()
$myshell.FindPrinter()

Открыть диалоговое окно запуска программ можно с помощью метода FileRun(), а для вызова окна установки даты/времени нужен метод SetTime(). Есть, к примеру, методы для вызова окна настройки панели задач, элементов панели управления с указанием одного из доступных файлов cpl, для управления открытыми окнами:

$myshell.MinimizeAll()
$myshell.UndoMinimizeAll()
$myshell.TileHorizontally()
$myshell.TileVertically()

Метод Windows() позволяет получить доступ к коллекции открытых в проводнике или в браузере Internet Explorer окон. Посмотрим доступные для этой коллекции свойства и методы:

$myshell.Windows() | Get-Member

Существуют и другие полезные COM-объекты, количество которых зависит от установленного в системе ПО. Когда-то основным средством автоматизации в Windows считался сервер сценариев WSH, объектная модель которого включает и COM-объекты: предназначенный для работы с сетевыми функциями WScript.Network и уже упомянутый нами WScript.Shell. Последний не только создает ярлыки на рабочем столе, с его помощью можно, например, выводить информационные окна с сообщениями и кнопками, переключаться между приложениями, запускать программы или имитировать нажатия клавиш.

Работа со службой каталогов ADSI

Под каталогом в общем случае подразумевается источник информации, в котором хранятся данные о некоторых объектах. Под службой каталога мы понимаем часть распределенной компьютерной системы, позволяющий обращаться к хранящимся объектам и манипулировать ими. Служба каталога может объединять данные об объектах сети и осуществляющих манипуляцию ими сервисов — она представляет собой единую точку входа для взаимодействия с сетевыми ресурсами. В гетерогенной компьютерной сети таких служб может быть множество: локальный диспетчер SAM (Security Account Manager) для не входящих в домен компьютеров, Active Directory и т.д.

Для взаимодействия с разными службами каталогов требуются различные инструменты, что создает определенные неудобства. Начиная с Windows 2000 корпорация Microsoft внедрила в операционные системы унифицированную технологию ADSI (Active Directory Service Interface) для не зависящего от конкретного сетевого протокола доступа. Чтобы находить объекты, для каталога определяется пространство имен. Поскольку разные службы каталогов используют различные способы именования, ADSI определяет позволяющее однозначно идентифицировать любой объект соглашение. Вводится понятие состоящих из двух частей строк связывания (binding string) или ADsPath. Первая часть имени определяет службу каталогов (провайдера ADSI), а вторая — расположение объекта в каталоге. Приведем примеры обозначения разных провайдеров ADSI:

LDAP:// используется для основанной на LDAP службы каталогов, в т.ч. для Active Directory;

WinNT:// используется для локальных компьютеров.

Специальных командлетов для работы с ADSI в PowerShell нет. Вместо них применяется оператор приведения типов [ADSI] после которого указывается строка связывания. Например, для подключения к пользователю Ivanov из домена test.ru нужна следующая конструкция:

$user = [ADSI]"LDAP://CN=Ivanov,DC=TEST,DC=RU"

Чтобы работать с локальными учетными записями, придется подключиться к компьютеру с соответствующим именем (для подключения к локальному компьютеру вместо имени достаточно использовать точку):

$computer = [ADSI]"WinNT://."

Для примера создадим на локальной машине нового пользователя Ivanov:

$user = $computer.Create("user","Ivanov")
$user.Put("Description","Создан из PowerShell")
$user.SetInfo()

Теперь подключимся к нему:

$user1 = [ADSI]"WinNT://./Ivanov,user"
$user1.Description

Форматирование вывода

Интерактивная работа часто требует выводить данные на экран. В других оболочках команды и утилиты сами занимаются форматированием вывода, но возвращаемые функциями и командлетами бинарные объекты обычно не умеют этого делать. В PowerShell вывод форматируют четыре специальных командлета, которым объекты «скармливаются» через конвейер. Более подробные сведения них можно получить с помощью Get-Help:

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

Format-List выводит объект как список свойств, каждое из которых отображается на новой строке. Поддерживается возможность группировки данных;

Format-Custom форматирует вывод с использованием пользовательского представления;

Format-Wide форматирует объекты в виде широкой таблицы, в которой отображается только одно свойство каждого объекта.

Если ни один из перечисленных командлетов не вызван, применяется соответствующий типу отображаемых данных модуль форматирования. Правила отображения хранятся в конфигурационных файлах в формате XML с расширением .ps1xml, которые находятся в каталоге $PSHome. Их список можно получить с помощью следующей команды:

dir $pshome*format*.ps1xm

Редактировать конфигурационные файлы вручную не рекомендуется, лучше создать собственные и включить их в список загружаемых с помощью командлета Update-FormatData. Если модуль форматирования по умолчанию для нужного типа не определен, PowerShell отображает на экране свойства объекта в виде списка.

На этом мы завершим описание работы с объектами в PowerShell, а заключительная статья цикла будет посвящена решению практических задач управления распределенной информационной средой предприятия. В ней нам пригодится весь описанный инструментарий. Основной упор будет сделан на объекты CIM и сравнение их с WMI. Прошлые части можно найти по ссылкам ниже.


Часть 1: Основные возможности Windows PowerShell
Часть 2: Введение в язык программирования Windows PowerShell
Часть 3: Передача параметров в скрипты и функции, создание командлетов
Часть 4: Работа с объектами, собственные классы

WMI (Windows Management Instrumentation) — это технология, с помощью которой можно получить и изменить достаточно широкий перечень параметров Windows.

Для примера мы хотим узнать информацию о процессоре. Мы можем использовать команду CMD sysinfo или Powershell Get-ComputerInfo, но увидеть только часть информации. С помощью WMI мы можем получить почти всю информацию.

Для получения всех классов WMI в Powershell мы можем использовать:

Get-WmiObject -List

Мы получим все классы для пространства имен rootcimv2 т.к. оно стоит по умолчанию. Если мы хотим использовать другое, то его нужно указать с ключом -Namespace.

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

Get-WmiObject -List -ComputerName CL1

Где:
-ComputerName — имя компьютера

WMI работает на 135 порту, а так же привилегированная учетная запись с правами на WMI и DCOM.

Либо у нас должен работать PSRemoting (тогда мы будем использовать Ivoke-Command). Весь процесс описан тут. 

Получение свойств класса через Powershell WMI

Если мы еще не знаем какой класс нам нужен, а вывод очень большой, то мы можем немного отфильтровать результат. На примере я искал классы где в имени есть BIOS:

Get-WmiObject -List | where {$_.name -like "*BIOS*"}

 Если мы выведем свойства класса операционной системы, то не увидим названия:

Get-WmiObject -Class Win32_OperatingSystem

Получение класса WMI Powershell

Часть свойств можно получить и так:

[wmiclass]"Win32_OperatingSystem" | Get-Member

Для того что бы отобразить все свойства нужно выполнить:

Get-WmiObject -Class Win32_OperatingSystem | Select-Object -Property *

Получение всех свойств через WMI Powershell

Либо можно объявить результат в переменную:

$result = Get-WmiObject -Class Win32_OperatingSystem

Получить все значения переменной:

$result | Get-Member

Все значения WMI Powershell

И затем вызывать через переменную. Так я получу название:

$result.Caption

Поиск свойств в Powershell WMI

У нас два способа поиска нужных свойств. Первый через ключ -Filter:

Get-WmiObject -List | where {$_.Name -Like "*share*"}
Get-WmiObject -Class Win32_Share -Filter "Status = 'OK'"

Фильтрация свойств WMI Powershell

Но если мы напишем что-то не так, то увидим язык WQL (WMI Query Language):

Get-WmiObject : Invalid query «select * from Win32_Share where Status1 = ‘OK'»

Т.е. мы можем писать и запрос WQL:

Get-WmiObject -Query "SELECT * FROM Win32_share WHERE Status='OK'"

Вызов методов WMI через Powershell

Этот метод запустит Notepad.exe на удаленном компьютере AD. В $cred будут храниться учетные данные, если мы будем запускать процесс под другим пользователем.

$cred = Get-Credential
$process = Get-WmiObject -Query "SELECT * FROM Meta_Class WHERE __Class = 'Win32_Process'" `
-Namespace "rootcimv2" -Computername 'AD' -Credential $cred
$process.Create( "notepad.exe" )

Есть другой подход, с другой командой:

Invoke-WmiMethod -Path win32_process -Name create -ArgumentList notepad.exe

Отмечу, что вызвать процесс в графической оболочке нельзя, он будет запущен в бэкграунде. Связано это с тем, что Microsoft против что бы вторгались в интерактивный сеанс пользователя кому-либо (не моя цитата). Один из вариантов решения этого помещать задачи в планировщике.

Для того что бы увидеть остальные команды по работе с WMI в Powershell можно запустить:

Get-Command -Noun *WMI*

Что бы увидеть примеры использования или получить справку:

Get-help Invoke-WmiMethod -Examples

Теги:

#powershell

#wmi

WMI (Windows Management Instrumentation) is part of Windows since Windows 2000. It is a service that can query almost every detail about a computer system. PowerShell ships with full WMI support.

These are the most important CIM (Common Information Model) cmdlets:

Cmdlet Purpose
Get-CimInstance Gets instances of WMI classes. This is the most important cmdlet.
Get-CimClass Gets a WMI class. Use it to access static WMI methods.
Invoke-CimMethod Runs a WMI method, and returns results.
Set-CimInstance Writes back changed properties.
New-CimSession Creates a new remoting session to one or more remote systems
New-CimSessionOption Defines special options for remoting connections.
Remove-CimSession Closes and removes a remoting session that is no longer used.
New-CimInstance Creates a new instances of a WMI class, i.e. for temporary use.

All of these ship in the module CimCmdlets that was introduced in PowerShell 3. To get a full list of CIM cmdlets, run the command below:

Get-Command -Module CimCmdlets

Getting Information

To get useful information from WMI, you need to know where the information resides. WMI uses namespaces and classes to organize its content:

  • Namespace: a namespace works like a folder. WMI uses a namespace tree to organize its classes. The top of this tree is always called root. The namespace root/cimv2 is the default namespace. If you want to use a different namespace, you need to explicitly use the parameter -Namespace.
  • Class: a class consists of properties (information) and methods (commands). Most properties are read-only.

The default namespace root/cimv2 contains most of the WMI classes used in scripting. So unless you need to access more exotic WMI classes in other namespaces, you don’t need to care much about namespaces.

If you do care, and would like to investigate the available namespaces (and classes), please refer to this sample code, or peek a bit down this article.

Querying Information

To get information from WMI, you ask for instances of a given class. The PowerShell code for this is always the same, so the hardest part in WMI is to figure out the name of the class that describes what you are after.

You can either use the reference and browse through the classes available in a given namespace. Or you can simply guess: most WMI classes start with “Win32_”, followed by an English word (singular) describing what you are after.

So to get information about your computer BIOS, the appropriate class name would be Win32_BIOS.

There are two cmdlets you can use to query information: Get-WmiObject and Get-CimInstance:

# original cmdlet, discontinued in PowerShell 6:
Get-WmiObject -Class Win32_BIOS

# new cmdlet, introduced in PowerShell 3:
Get-CimInstance -ClassName Win32_BIOS

Get-WmiObject was introduced in PowerShell 1 and is available in all version of Windows PowerShell.

The cmdlet was replaced by the more sophisticated Get-CimInstance in PowerShell 3. Today, Get-WmiObject is considered obsolete and should be replaced by Get-CimInstance. In *PowerShell 6 and better, Get-WmiObject was removed.

Filtering Information

WMI can filter results and return only instances where a given condition exists. For example, the WMI class Win32_LogicalDisk represents all logical drives:

Get-CimInstance -ClassName Win32_LogicalDisk

These can be all kinds of drives, and the result may look like this:

DeviceID DriveType ProviderName   VolumeName Size          FreeSpace   
-------- --------- ------------   ---------- ----          ---------   
C:       3                        OS         1007210721280 517862002688
D:       2                                   64421232640   64418349056 
Z:       4         \127.0.0.1c$ OS         1007210721280 517862002688

The property DriveType apparently identifies the type of drive, and from looking at the data, the number 3 seems to identify fixed disks.

If you want the exact meaning for WMI codes, you can always look up the class in our reference and get a precise listing of friendly names for code numbers.

In order to get back only fixed disks, you can filter the results. Either use -Filter and specify the condition that must be met, or replace -ClassName by -Query and submit a SQL-like query:

Get-CimInstance -ClassName Win32_LogicalDisk -Filter 'DriveType=3'
Get-CimInstance -Query 'Select * From Win32_LogicalDisk Where DriveType=3'

The result is the same in both cases.

Try and avoid using Where-Object to filter WMI results. Where-Object does client-side filtering and is inefficient: all data needs to be retrieved, and Where-Object is discarding unwanted data in a second step. WMI filtering in contrast produces only the information required which is much more efficient, especially across a network.

Listing Namespaces

Remember? WMI namespaces work like folders, and each namespace can contain a number of WMI classes. The default namespace root/cimv2 is the most important, but there are many more. In fact, every vendor and software producer can add their own.

There is no cmdlet to list all WMI namespaces. To examine the available namespaces, use Get-CimInstance from above: each child namespace is represented by an instance of the WMI class __Namespace inside the parent namespace.

To find all available namespaces, start with the top namespace root, and use a queue or recursive calls to examine all child namespaces:

# create a new queue
$namespaces = [System.Collections.Queue]::new()

# add an initial namespace to the queue
# any namespace in the queue will later be processed
$namespaces.Enqueue('root')

# process all elements on the queue until all are taken
While ($namespaces.Count -gt 0 -and ($current = $namespaces.Dequeue()))
{
    # find child namespaces
    Get-CimInstance -Namespace $current -ClassName __Namespace -ErrorAction Ignore |
    # ignore localization namespaces
    Where-Object Name -NotMatch '^ms_d{2}' |
    ForEach-Object {
        # construct the full namespace name
        $childnamespace = '{0}{1}' -f $current, $_.Name
        # add namespace to queue
        $namespaces.Enqueue($childnamespace)
    }

    # output current namespace
    $current
}

For more information about namespaces and a list of typical namespaces, please refer to this article.

Listing WMI Classes

Remember? WMI classes are where the beef is. Each class represents something specific, i.e. the class Win32_Processor represents CPUs, whereas the class Win32_NetworkAdapter represents network cards. To work with WMI, you need to know the exact class name that is representing what you’d like examine.

Get-CimClass returns all classes in a given namespace. Since root/cimv2 is the default namespace, this will create a sorted list of all class names living in namespace root/cimv2:

Get-CimClass | Select-Object -ExpandProperty CimClassName | Sort-Object

For more information about classes, and how to identify useful classes for scripting, please refer to this article.

Changing Information

WMI is primarily a way to describe the computer and its settings and to retrieve information. The vast majority of properties are read-only. WMI is not widely used to configure and change settings.

In some scenarios, WMI can actually change things and settings. Let’s take a look at the class Win32_Environment. This class represents Windows Environment variables, so to list all of them, ask WMI to return all instances of this class:

Get-CimInstance -ClassName Win32_Environment

Adding New Instances

When you create a new Windows Environment variable, regardless of how you do this, as a result of this, WMI adds a new instance of Win32_Environment.

As you may know, Windows Environment variables can be defined per User and per Machine. Both of these are supported by WMI. When you launch a program, it receives a copy of them (called the process set). These copied (and temporary) environment variables are not represented by Win32_Environment.

So when you create a new environment variable in PowerShell using the drive env:, this will not change the instances of Win32_Environment:

$before = Get-CimInstance -ClassName Win32_Environment

# create a temporary environment variable
$env:myNewEnv = 1

$after = Get-CimInstance -ClassName Win32_Environment

$new = $after.Count - $before.Count
"Detected $new new environment variables"

However, when you create a permanent new environment variable, i.e. via an API call, this does add a new instance to Win32_Environment:

$before = Get-CimInstance -ClassName Win32_Environment

# create a permanent environment variable
[Environment]::SetEnvironmentVariable('myNewVar', 124, 'User')

$after = Get-CimInstance -ClassName Win32_Environment

$new = $after.Count - $before.Count
"Detected $new new environment variables"

You can reverse this: by using New-CimInstance to manually add a new instance of Win32_Environment, you can actually create a new Windows Environment variable. The code below creates a new environment variable named SomeInfo in the context of the current user.

Warning: you cannot create new instances from just about any WMI class this way. In fact, most WMI classes do not support creating new instances manually. Instead, they use methods to add new instances, or don’t support adding new instances at all.

# create username for current user
$username = '{0}{1}' -f $env:USERDOMAIN, $env:USERNAME

# define initial values to create a new instance of
# Win32_Environment (new environment variable)
$initialValues = @{
    Name = 'SomeInfo'
    VariableValue = '123'
    UserName = $username
}

# create new instance
$newEnv = New-CimInstance -ClassName Win32_Environment -Property $initialValues 

$newEnv

This is a permanent change, and from now on, you can access this variable via WMI like so:

$variable = Get-CimInstance -ClassName Win32_Environment -Filter 'Name="SomeInfo"'

$variable.VariableValue

Changing Properties

Information returned by WMI objects are read-only. So when you followed the example above and created and retrieved the environment variable SomeInfo, you can read its value. When you change its value, though, the environment variable will not change.

Even though the WMI object happily accepts any change to its properties, and even stores them, they are not permanent:

# get the environment variable "SomeInfo"
# NOTE: this variable must exist! Use previous example to create it.
$variable = Get-CimInstance -ClassName Win32_Environment -Filter 'Name="SomeInfo"'

$variable.VariableValue

# properties can be changed:
$variable.VariableValue = 'NEW!'
$variable.VariableValue
# however these changes are not permanent and do not affect the
# underlying environment variable

Once you retrieve the original object again, the old value is restored:

$variable = Get-CimInstance -ClassName Win32_Environment -Filter 'Name="SomeInfo"'

# old value is restored:
$variable.VariableValue

To permanently change the property, use Set-CimInstance:

# get the environment variable "SomeInfo"
# NOTE: this variable must exist! Use previous example to create it.
$variable = Get-CimInstance -ClassName Win32_Environment -Filter 'Name="SomeInfo"'

$variable.VariableValue

# assign a new property value:
$variable.VariableValue = "NEW"

# Update the change:
$variable | Set-CimInstance

# retrieve the object again
$variable = Get-CimInstance -ClassName Win32_Environment -Filter 'Name="SomeInfo"'

# change is permanent:
$variable.VariableValue

Warning: most properties won’t allow you to change their values. Instead, they use methods to change and manage settings (if supported at all).

Calling WMI Methods

Some WMI classes can contain methods. Methods can either be implemented in specific instances that you received from Get-CimInstance, or directly in WMI classes that you received from Get-CimClass.

Use the code below to figure out more about implemented methods.

# figure out the methods supported by Win32_Process:
$className = 'Win32_Process'
# get the underlying WMI class:
$class = Get-CimClass -ClassName $className

# define a calculated property named "Implemented":
$implemented = @{
    Name = 'Implemented'
    Expression = {
        # read the method qualifiers:
        $qualifiers = $_.Qualifiers.Name

        # check to see who implements this method:
        if ($qualifiers -notcontains 'Implemented')
        {
            # this method is not implemented by anyone
            # it cannot be used:
            'Not implemented'
        }
        elseif ($qualifiers -contains 'Static')
        {
            # this is a static methods implemented by
            # the WMI class itself:
            'Class'
        }
        else
        {
            # this is a dynamic method implemented by
            # every instance of this class:
            'Instance'
        }
    }
}

# find out who implements the methods

# get all methods from this class:
$class.CimClassMethods |
  # output method details and implementation:
  Select-Object -Property Name, $implemented, ReturnType, Parameters

The result looks similar to this:

Name                    Implemented ReturnType Parameters                      
----                    ----------- ---------- ----------                      
Create                  Class           UInt32 {CommandLine, CurrentDirector...
Terminate               Instance        UInt32 {Reason}                        
GetOwner                Instance        UInt32 {Domain, User}                  
GetOwnerSid             Instance        UInt32 {Sid}                           
SetPriority             Instance        UInt32 {Priority}                      
AttachDebugger          Instance        UInt32 {}                              
GetAvailableVirtualSize Instance        UInt32 {AvailableVirtualSize}

Calling Instance Method

If a method is implemented on class instances, use Get-CimInstance to get the WMI instance(s) you need. The example below retrieves the process that is currently running your PowerShell code:

# get the process where property "ProcessID" equals the process id
# of the current PowerShell process (always available in $pid):
$me = Get-CimInstance -ClassName Win32_Process -Filter "ProcessId=$Pid"
$me

Once you have the instances, use Invoke-CimMethod to call the method. For example, to find out the process owner, call the method GetOwner():

$me = Get-CimInstance -ClassName Win32_Process -Filter "ProcessId=$Pid"
Invoke-CimMethod -InputObject $me -MethodName GetOwner

You can combine both calls, too:

# get owner of current powershell process
Invoke-CimMethod -Query "Select * From Win32_Process Where ProcessId=$Pid" -MethodName GetOwner

GetOwner() is a method that does not take any arguments. See the next section for an example on how to call methods with arguments.

Calling Class Methods

Methods implemented by the class are not related to specific instances. For Win32_Process and processes, these methods are not related to existing processes. The method Create() creates a new process.

Before you can call Create(), you need to know more about the arguments it requires. Unlike GetOwner() in the previous example, Create() does require specific information from you so it knows which process to launch.

# figure out the arguments required by the method "Create"
# exposed by the WMI class "Win32_Process":

$className =  'Win32_Process'
$methodName = 'Create'

# list all parameters
$class.CimClassMethods.Item($methodName).Parameters |
  # take only input arguments:
  Where-Object { $_.Qualifiers.Name -contains 'In' } |
  # return name and data type:
  Select-Object -Property Name, CimType

The result looks like this:

Name                       CimType
----                       -------
CommandLine                 String
CurrentDirectory            String
ProcessStartupInformation Instance

As you can see, you can submit up to three arguments to the method. Arguments are submitted to the method using a hashtable (so order does not matter). This example launches a new instance of a notepad process:

# add your arguments to a hashtable and use the
# parameter names as keys:
$arguments = @{
    CommandLine = 'notepad.exe'
}

# call the method on the WMI class, and submit the arguments:
Invoke-CimMethod -ClassName Win32_Process -MethodName Create -Arguments $arguments

Using Data Type “Instance”

When you look at the arguments supported by Create(), the argument ProcessStartupInformation is marked as using the data type Instance: this argument can be an instance of an object of type ProcessStartupInformation.

When you look up this method in our reference, you learn that this object is an instance of the WMI class Win32_ProcessStartup.

The code below creates a new PowerShell process, changes the console title, background and foreground colors, and positions the console window on the desktop:

# using a new instance of Win32_ProcessStartup to create a
# new powershell process and manipulate the console window:

# create a new instance of Win32_ProcessStartup:
# (use -ClientOnly to create a temporary in-memory instance)
$class = Get-CimClass -ClassName Win32_ProcessStartup
$instance = New-CimInstance -CimClass $class -ClientOnly

# fill properties:
$instance.Title = 'My Console Window'
$instance.X = 100
$instance.Y = 200
$instance.FillAttribute = 20

# add your arguments to a hashtable and use the
# parameter names as keys:
$arguments = @{
    CommandLine               = 'powershell.exe'
    ProcessStartupInformation = $instance
}

# call the method on the WMI class, and submit the arguments:
Invoke-CimMethod -ClassName Win32_Process -MethodName Create -Arguments $arguments

Accessing Remote Computers

WMI comes with powerful remoting techniques built-in.

If you are working in a modern Windows environment, and your current user account has sufficient privileges on the target system, you may be able to successfully connect to and run WMI code on a remote machine simply by adding -ComputerName:

# get information from local machine
Get-CimInstance -ClassName Win32_BIOS

# get information from remote machine
Get-CimInstance -ClassName Win32_BIOS -ComputerName server123
Get-CimInstance -ClassName Win32_BIOS -ComputerName 10.12.131.156

If calls fail, these are typical issues:

  • Access Denied: your current user account is not authorized to access the remote system. See below on how to use a different user account to log on
  • RPC Unavailable: a firewall blocks the call, or the target machine is turned off
  • Other: the target machine may not be set up for remoting calls (see below)

Using Different User Accounts

Get-CimInstance and all the other WMI CIM cmdlets provide no -Credential parameter to use a different user account. Instead, they all work with reusable CIM Sessions.

Whenever the default connection does not work for you, create your own CIM Session, and use this session instead. Here is code that connects to a remote machine using a different user account:

# one or more computer names or IP addresses:
$computers = 'server1', 'server2'

# authenticate with a different identity:
$cred = Get-Credential -Message 'Authenticate to retrieve WMI information:'

# create a CIM session
$session = New-CimSession -ComputerName $computers -Credential $cred


# use the CIM cmdlets with the session you previously created:
$result = Get-CimInstance Win32_Bus -CimSession $session


# when done, remove the CIM session (it can be reused with multiple
# calls until you remove it)
Remove-CimSession -CimSession $session

$result

The user account you specify needs to have Administrator privileges on the target side. Typically, on servers, built-in remoting is enabled by default. On clients, it is disabled by default and can be manually enabled using this command:

Enable-PSRemoting -SkipNetworkProfileCheck -Force

Using WinRM or DCOM Protocol

One of the fundamental differences between the old Get-WmiObject and the new Get-CimInstance is the way how machines connect. Get-WmiObject uses the old-fashioned DCOM protocol (and cannot use anything else). Some old servers may only be able to use DCOM.

Get-CimInstance uses the much more modern and safer WinRM protocol by default. So if the target machine is relatively old, or if the use of WinRM wasn’t approved in your enterprise and your servers are still connecting over DCOM, then you may experience a situation where Get-WmiObject works on remote machines whereas Get-CimInstance fails.

CIM Session uses WinRM by default but can be configured to fall back to DCOM instead. So for troubleshooting, or to access very old servers, use code like this:

$computername = '127.0.0.1'

# use old DCOM protocol:
$options = New-CimSessionOption -Protocol Dcom
# create CIM session
$session = New-CimSession -SessionOption $option -ComputerName $computername


# use session
Get-CimInstance -ClassName Win32_BIOS -CimSession $session

# remove session
Remove-CimSession -CimSession $session

Next Steps

Now that you know how to use the built-in WMI cmdlets and fundamental PowerShell principles, take a look at the hundreds of classes in the default namespace, and adapt the code samples found here to these classes.

Windows Management Instrumentation

Windows Management Instrumentation или WMI – это технология управления, являющаяся частью операционной системы Microsoft® Windows. Впервые она появилась еще в Windows NT® 4.0, и обеспечивала более стабильный и постоянный доступ к настройкам конфигурации как локального, так и удаленных компьютеров.

Долгие годы WMI была одним из самых мощных и доступных инструментов администратора для получения управленческой информации и осуществления тех или иных изменений в конфигурации, особенно на удаленных компьютерах. Однако практическое использование WMI не всегда было простым – более ранние технологии, такие как Microsoft Visual Basic® Scripting Edition (VBScript), требовали программного подхода к использованию WMI, и далеко не все администраторы могли справиться с этой задачей. Windows PowerShell предлагает администраторам самый легкий и доступный во многих отношениях способ работы с WMI.

Важно понимать, что WMI может служить совершенно разным целям для разных групп пользователей. Например, разработчики программного обеспечения взаимодействуют с WMI при создании приложений, таких как Microsoft System Center Configuration Manager. В этом модуле мы будем рассматривать WMI как административный инструмент, и будем говорить только о тех элементах WMI, которые имеют отношение к повседневной работе администратора.

Обзор WMI

WMI – это технология управления, которая внедряется в операционную систему Windows со времен Windows NT 4.0. Каждая новая версия Windows, так же, как и каждая новая версия многих других продуктов Microsoft, обновляет WMI, придавая ей новые черты и наделяя новыми возможностями.

WMI предоставляет информацию в соответствии с моделью Common Information Model или CIM, которая была разработана промышленной группой Distributed Management Task Force или DMTF при участии Microsoft и других поставщиков. Но несмотря на то, что WMI стремится отобразить информацию стандартизированным способом, она почти не устанавливает жестких правил для разработчиков программного обеспечения. В результате WMI зачастую воплощается совершенно по-разному в разных продуктах Microsoft и сторонних продуктах. К сожалению, это делает изучение WMI очень сложным, причем проблема усугубляется тем фактом, что многие варианты реализации WMI нигде не задокументированы. Windows PowerShell может упростить доступ к WMI в случае, если вы будете знать, какой именно элемент WMI вам нужен, но не может полностью решить проблему отсутствия документации или отсутствия жестких стандартов внедрения WMI.

Отчасти сложность WMI объясняется тем фактом, что она отвечает нуждам различных групп пользователей, включая разработчиков ПО, которым часто требуется более детальное и менее качественное отображение управленческой информации. В будущем, вы, возможно, будете замечать, что все больше командлетов Windows PowerShell создается в виде оболочек вокруг технологии WMI. Такие оболочки будут обеспечивать более простые и узкоспециализированные способы работы с WMI, и в то же время скрывать многие из существующих «сложностей». Возможно, что некоторые из командлетов, которыми вы уже пользуетесь, в действительности используют WMI. Но даже полный переход на WMI не представляет собой никакой опасности. Это ценная технология, и, несмотря на некоторые противоречие и прочие недостатки, она дает довольно мощные возможности.

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

Взаимодействие  WMI

Когда вы используете WMI для установления соединения с удаленным компьютером, вы, по сути, используете подсистему WMI на своем локальном компьютере для поключения к WMI сервису на удаленном компьютере. Взаимодействие двух компьютеров происходит с использованием протокола Remote Procedure Call или RPC. RPC – это старый, проверенный временем протокол, который используется в Windows более десяти лет. Однако по мере того, как локальные брандмауэры получали большее распространение, RPC становился все сложнее в использовании и управлении.

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

Windows Firewall поддерживает в качестве исключения сервис Remote Management, который может разрешить RPC, необходимый для WMI. Прочие брандмауэры могут иметь аналогичные возможности – уточнить это можно у их поставщиков. Другие настройки конфигурации, включая User Account Control (UAC) и Distributed Component Object Model (DCOM) могут также задействовать WMI-коммуникации; веб-страницы, расположенные по посещенным ранее URL адресам, выдают информацию при конфигурировании этих настроек.

Структура WMI

Между тем, WMI – это не просто цельная программа. Она включает в себя несколько провайдеров, каждый из которых соединяет WMI-сервис с конкретным продуктом, технологией, функцией и.т.д. WMI провайдер действует почти как драйвер устройства, обеспечивая WMI сервису доступ к различным продуктам Windows. Например, на компьютерах с операционной системой Windows Server, на которых установлен сервис Windows DNS, WMI провайдер позволяет WMI сервису запрашивать и создавать ресурсные записи DNS, а также настройки конфигурации DNS.

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

Пространство имени верхнего уровня является корневым. Другие пространства могут содержать:

• RootCimv2

• RootMicrosoftDNS

• RootMicrosoftActiveDirectory

• RootSecurityCenter

Не все компьютеры Windows содержат одни и те же пространства имен. Например, клиентский компьютер не будет содержать RootMicrosoftActiveDirectory, а серверный компьютер не будет содержать RootSecurityCenter.

Для того, чтобы работать с пространством имен на удаленном компьютере, это пространство не обязательно нужно устанавливать на свой компьютер. Например, если вы используете компьютер под управлением Windows 7 и хотите работать с Windows DNS на удаленном сервере, вы можете сделать это через пространство имен RootMicrosoftDNS, установленное на этом удаленном компьютере, несмотря на то, что на вашем компьютере его нет.

Классы

Внутри каждого пространства имен WMI выделяет один или несколько классов. Класс – это абстрактное значение компонента управления. Например, пространство имен RootCimv2 содержит класс, который называется Win32_TapeDrive. Этот класс определяет свойства ленточного накопителя и существует в пространстве имени независимо от того, подключен данный носитель к компьютеру или нет.

Классы пространства имен The RootCimv2 почти всегда имеют префикс Win32_, даже на 64-битных компьютерах. Этот префикс не используется в названиях классов других пространств имен. В других пространствах имен названия классов вообще редко имеют какой-либо префикс.

К другим классам пространства имен RootCimv2 относятся:

• Win32_Account

• Win32_BIOS

• Win32_Desktop

• Win32_Fan

• Win32_Group

• Win32_Keyboard

• Win32_LogicalDisk

• Win32_NetworkAdapterConfiguration

• Win32_NTDomain

• Win32_Product

• Win32_Service

Как вы видите, пространство имен RootCimv2 содержит классы, имеющие отношение к операционной системе Windows и аппаратному обеспечению компьютера. Это одно из немногих пространств имен, содержащихся на каждом компьютере с Windows, хотя классы внутри этого пространства имен различаются на серверных и клиентских компьютерах, а также на различных версиях Windows ОС. Классы определяют два важных элемента: свойства и методы. Каждый класс имеет как минимум одно свойство, и подобно другим объектам в Windows PowerShell, свойства класса обеспечивают доступ к управленческой и конфигурационной информации. Некоторые классы обладают методами, которые требуют определенных действий, например, перезагрузки компьютера или изменения конфигурации.

Экземпляры

Реальное существование класса называют экземпляром. Например, если на вашем компьютере есть четыре логических диска, то вы имеете четыре экземпляра класса Win32_LogicalDisk. Если на вашем компьютере нет подключенного ленточного накопителя, у него будет нулевой экземпляр класса Win32_TapeDrive, хотя сам класс будет существовать в виде абстрактного значения.

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

Во многих случаях экземпляры предназначены только для чтения, что означает, что вы можете извлечь значение свойства, но не можете изменить его. Особенно это касается классов в пространстве имен RootCimv2. Для того, чтобы вы могли изменить настройки конфигурации, класс должен обладать методом, который вы сможете использовать для осуществления изменений. За пределами пространства имен RootCimv2 принцип работы может быть другим. В некоторых случаях вы можете изменить значение свойства путем прикрепления к нему нового свойства. Примером этого может служить пространство имен для Internet Information Services (IIS) 6 внутри WMI. В этом заключается одно из главных противоречий WMI: в разные времена разные группы специалистов, занимающихся разработкой новых продуктов Microsoft, высказывали разные идеи по поводу того, как WMI может использоваться для управления продуктами, технологиями и функциями. Иногда идеи одной группы находили поддержку у специалистов другой группы и были адаптированы ими, что приводило к некоторой стабильности и схожести различных пространств имен; в других случаях эти идеи никогда более не были использованы, и пространства имен, использованные той или иной группой специалистов, оставались уникальными внутри WMI.

Как найти нужный класс.

При существовании десятков тысяч WMI классов найти тот единственный, который помог бы выполнить конкретную задачу, очень сложно. Центральной директории WMI классов не существует, к тому же, существует очень мало способов (конечно, кроме использования поисковых машин) поиска классов по ключевым словам. Для поиска нужного класса следует основываться на трех базовых принципах:

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

• The “Windows PowerShell” Internet newsgroup (доступна по адресу: http://go.microsoft.com/fwlink/?LinkId=193516)

www.PoshComm.org

www.PowerShell.com

www.ScriptingAnswers.com

www.ConcentratedTech.com

• Исследования. Различные «исследовательские» и «поисковые» инструменты WMI позволяют просматривать WMI хранилища как на локальном, так и на удаленных компьютерах. В хранилищах классы обычно располагаются в алфавитном порядке, что упрощает поиск класса по названию и просмотр доступных классов.

• Примеры. Используя поисковые интернет-машины для поиска по ключевым словам (например, “WMI BIOS” или “WMI disk space), зачастую можно обнаружить примеры, написанные другими людьми. Эти примеры, даже если они и не являются в точности тем, что вам нужно, могут помочь вам найти классы, имеющие отношение к выполняемой вами задаче. Хорошей стартовой точкой для поиска примеров, имеющих отношение ко многим видам административной работы, является Microsoft TechNet Script Center Repository (http://go.microsoft.com/fwlink/?LinkId=193517).

Обратите внимание, что даже примеры, имеющие отношение к другим технологиям, таким как VBScript, JScript или Perl, могут быть полезными для поиска названий WMI классов. Не исключайте такие варианты примеров лишь потому, что они не относятся исключительно к Windows PowerShell.

Помимо этого, вы можете дать Windows PowerShell команду отобразить список классов:

Get-WmiObject -list

Эта команда отображает список классов пространства имен, используемого по умолчанию. Чтобы отобразить классы из другого пространства имен, следует добавить параметр – namespace и уточнить имя пространства имен, например, RootSecurityCenter. Также оболочка может помочь найти классы, название которых содержит определенную строку символов:

Get-WmiObject -list -class *user*

Поскольку параметр –class является позиционным, вы можете даже опустить имя параметра –class:

Get-WmiObject -list *user*

WMI развивалась годами, и продолжает развиваться. Это означает, что конкретный WMI класс может вести себя слегка по-разному в разных версиях Windows, могут иметь меньше свойств или полностью отсутствовать в старых версиях Windows. Обязательно учитывайте это, особенно при работе с удаленными компьютерами. Пространства имен на разных компьютерах могут очень сильно различаться, не считая пространства имен RootCimv2. Клиентский и серверный компьютер обычно имеют разные наборы пространств имен; пространства имен часто бывают доступными только когда соответствующий продукт или технология установлены на компьютер.

Документация

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

Главные классы операционной системы, такие как классы в пространстве имен RootCimv2, последовательно задокументированы; эта документация хранится в Интернете как часть библиотеки Microsoft Developer Network (MSDN®). Поскольку библиотека периодически подвергается реорганизации, меняя URL адреса, самый простой способ найти документацию для класса – воспользоваться поисковыми системами. Например, если вы введете в строку поиска Win32_Service, вы обнаружите, что первые результаты выдачи будут вести именно в Библиотеку, а уже оттуда вы можете начать поиск других классов в пространстве имен, используя таблицу дерева контента.

Вне пространства имен RootCimv2 документация намного менее стабильна и согласованна, как по форме, так и в плане доступности. У многих групп разработчиков просто не было времени, чтобы подготовить необходимую документацию. В других случаях группы разработчиков могли создать WMI классы для собственного использования, но не думали о том, что эти классы станет использовать кто-то еще, поэтому, документация так и не была опубликована для широкого доступа.

Если документация доступна – а это чаще всего бывает с классами пространства имен RootCimv2 – обращайте пристальное внимание на детали, указывающие, с какими продуктами ли с какой версией Windows данный класс работает. Однако не забывайте, что классы могут различаться в зависимости от версии Windows. Несмотря на то, что класс Win32_Processor присутствует, например, на Windows NT 4.0, он ведет себя совсем не так, как на Windows Server 2008 R2 (хотя в данном случае в документации объясняется разница).

Безопасность WMI

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

Также по умолчанию защита WMI конфигурируется таким образом, чтобы локальные пользователи могли запрашивать почти любую информацию из WMI. Члены локальной административной группы (которая в доменной среде обычно включает доменные админские группы доменного уровня), могут запрашивать информацию удаленно. Не стоит менять настройки конфигурации системы безопасности WMI до тех пор, пока вы не будете осознавать на 100%, что вы делаете, и каковы возможные последствия. Модификация системы безопасности может привести к полной остановке WMI или негативно повлиять на продукты, основанные на WMI, такие как System Center Configuration Manager. Настройки безопасности, заданные по умолчанию, подходят для большинства ситуаций, и чаще всего самым мудрым решением будет не трогать их совсем.

Настройки безопасности WMI можно просмотреть и модифицировать с помощью оснастки WMI Control в консоли Microsoft Management Console (MMC). По умолчанию консоль не содержит эту оснастку; вам необходимо открыть новое MMC-окно или существующую консоль и добавить оснастку вручную.

Обратите внимание, что WMI чувствительна к User Account Control (UAC) на тех версиях Windows, которые поддерживают эту технологию защиты. Если вы планируете запросить WMI информацию с удаленного компьютера, вы должны обладать действующим администраторским токеном. Обычно это означает, что вы должны либо работать в Windows PowerShell как «Администратор» (чтобы иметь необходимую привилегию), либо обеспечить альтернативный мандат после установления WMI соединения.

Просмотр WMI из PowerShell

Windows PowerShell также может помочь вам изучить все классы в заданном пространстве имен, так как она может выдать список всех классов, присутствующих в пространстве имен. Чтобы получить список всех классов, содержащихся в пространстве имен, используемом по умолчанию, запустите команду:

Get-WmiObject –namespace rootcimv2 –list

Вы можете заменить название пространства имен RootCimv2 другим названием пространства имен для того, чтобы увидеть классы, содержащиеся в нем. А если добавить параметр –computerName, можно увидеть классы пространства имен на удаленном компьютере:

Get-WmiObject –namespace rootcimv2 –list –computername LON-DC1

Обычно командлет Get-WmiObject использует мандат того пользовательского аккаунта, через который вы открыли окно Windows PowerShell. Это единственный аккаунт, который может запрашивать WMI информацию локально. WMI сама по себе не позволит использование альтернативного мандата для локального соединения. Однако для удаленного соединения вы можете добавить параметр –credential, чтобы указать альтернативный аккаунт. Имя пользователя должно быть в формате DOMAINUSERNAME:

Get-WmiObject –namespace rootcimv2 –list –computername LON-DC1 –credential CONTOSOAdministrator

Наконец, чтобы увидеть список всех пространств имен, запустите в Windows PowerShell следующую команду:

get-wmiobject -namespace root -class «__namespace» | ft name

Использование WMI

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

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

Опрос WMI

Командлет Get-WmiObject отвечает за извлечение информации либо с локального компьютера, либо с одного или нескольких удаленных компьютеров. Параметр –class уточняет имя класса, которое вы хотите извлечь; по умолчанию извлекаются все экземпляры этого класса. Если класс находится вне пространства имен RootCimv2, используйте параметр –namespace для уточнения имени пространства имен, в котором можно найти класс. Также используйте параметр –computername, чтобы уточнить имя удаленного компьютера и параметр –credential, чтобы уточнить альтернативный мандат для удаленного подключения. За один раз можно запросить только один класс.

Командлет извлекает указанные экземпляры и помещает их в конвейер, например:

Get-WmiObject Win32_Service

Обратите внимание, что некоторые классы WMI перехлестываются с другими командлетами Windows PowerShell, например, Get-Service. Однако вы, возможно, уже заметили различия в их работе и способе отображения информации. Например, Get-Service использует Microsoft .NET Framework для извлечения информации о сервисах; эта информация не включает некоторые детали, такие как режим запуска сервиса или его учетная запись, поскольку такая информация не включена в Framework. Класс WMI Win32_Service, в свою очередь, включает информацию о режиме запуска и учетной записи сервиса. Вы можете увидеть эти свойства, передав экземпляр свойства по конвейеру командлету Get-Member:

Get-WmiObject Win32_Service | Get-Member

Также вы можете увидеть все свойства всех экземпляров класса, используя Format-List:

Get-WmiObject Win32_Service | Format-List *

Встроенный псевдоним командлета Get-WmiObject — gwmi.

В разделе справочника, посвященном командлету Get-WmiObject, обратите внимание на параметр –computerName. В справочнике по синтаксису он указывается в следующем виде:

[-ComputerName <string[]>]

Значение <string[]> указывает на то, что параметр может принимать несколько имен компьютеров. Одним из способов указать эти имена является их перечисление через запятую, поскольку Windows PowerShell автоматически интерпретирует такой список как набор объектов:

-computerName «LON-DC1″,»SEA-DC2»

Однако к параметру –computerName можно прикрепить все, что обозначает набор объектов. Например, вы можете создать текстовый файл, в котором в каждой строчке указано одно имя компьютера:

LON-DC1

SEA-DC2

NYC-SRV7

Для чтения этого файла вы можете использовать командлет Get-Content. Командлет обрабатывает каждую строчку текстового файла как объект строки – именно это необходимо параметру –computerName:

-computerName (Get-Content c:names.txt)

Скобки указывают оболочке на то, что команду Get-Content необходимо выполнить в первую очередь. Результаты этого командлета передаются параметру –computerName.

При соединении с несколькими удаленными компьютерами командлет Get-WmiObject все же может работать с альтернативным мандатом, на который указывает параметр –credential. Однако для всех компьютеров должен использоваться один и тот же мандат. Множественные соединения производятся последовательно, а не параллельно, поэтому, может потребоваться некоторое время для извлечения списка имен. Если командлен по каким-то причинам не может получить доступ к компьютеру (компьютер находится в режиме оффлайн, доступ заблокирован или не получено разрешение), то ситуация воспринимается как бесконечная ошибка, в результате чего командлет выдает сообщение об ошибке и продолжает работу, пытаясь подключиться к следующему в списке компьютеру.

Объекты, возвращаемые командлетом Get-WmiObject, всегда обладают свойством __SERVER, которое содержит имя компьютера, из которого поступил данный объект. Это свойство может быть полезным, когда вы отправляете запрос нескольким компьютерам, так как позволяет отсортировать и сгруппировать объекты по имени компьютера:

Get-WmiObject Win32_Service –computer (Get-Content c:names.txt) | Sort __SERVER | Format-Table –groupBy __SERVER

Командлет Get-WmiObject всегда использует Remote Procedure Calls (RPCs) для подключения к удаленным компьютерам; «родные» способности удаленной работы Windows PowerShell не задействуются. По этой причине Get-WmiObject может подключиться к любому удаленному компьютеру, на котором запущен сервис WMI, даже если на нем не установлена Windows PowerShell.

Еще одним способом запросить данные с нескольких компьютеров является использование командлета ForEach-Object. Помните, что командлет Get- Content читает текстовый файл и возвращает каждую строчку в виде объекта. ForEach-Object дает возможность перечислить все эти объекты. Если бы каждая строчка текста содержала имена компьютеров, вы бы перечисляли имена компьютеров. Преимущество этой техники состоит в том, что командлет ForEach-Object может выполнять множественные команды по отношению к каждому компьютеру:

Gc c:names.txt | ForEach-Object {

gwmi win32_computersystem;

gwmi win32_operatingsystem } |

select buildnumber,servicepackmajorversion,totalphysicalmemory

Скриптовый блок ForEach-Object содержит два WMI запроса, каждый из которых возвращает разные объекты. Объекты обоих типов отправляются по конвейеру командлету Select-Object. Select-Object затем выбирает три указанные свойства. Выходные данные будут выглядеть примерно так:

buildnumber         servicepackmajorversion                               totalphysicalmemory

————               ————————                          ——————-

                                                                                       3220758528

7600                      0

Если вы посмотрите внимательно, то заметите, что выходные данные расположены не в одну строчку. Первый объект в конвейере – это Win32_ComputerSystem, который не имеет свойства BuildNumber или ServicePackMajorversion – поэтому, данные колонки в первой строчке будут пустыми. Второй объект в конвейере не имеет свойства TotalPhysicalMemory, поэтому, эта колонка во второй строчке является пустой. Другими словами, вы увидите пример, в котором эти отдельные куски информации объединяются в один поток выходных данных.

Вы уже знаете, как использовать командлет Select-Object и добавлять новые свойства объекту. Часть значения свойства под названием Expression может содержать почти любой код Windows PowerShell, в том числе и абсолютно новый командлет. Например, следующая команда позволит извлечь сведения о логических дисках компьютера и отобразить информацию об имеющемся на них свободном месте в гигабайтах:

gwmi win32_logicaldisk |

select deviceid,drivetype,

@{Label=’freespace(gb)’;Expression={$_.freespace/1GB}}

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

gwmi win32_logicaldisk |

select deviceid,drivetype,

@{Label=’freespace(gb)’;Expression={$_.freespace/1GB –as [int]}}

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

Gwmi win32_operatingsystem | select caption

Затем вы можете добавить новое пользовательское свойство в выходные данные, и значением этого свойства будет абсолютно новый WMI запрос к классу

 Win32_ComputerSystem:

Gwmi win32_operatingsystem |

select caption,

@{Label=’PhysMemory’;

Expression={(gwmi win32_computersystem).totalphysicalmemory}}

Что мы здесь видим? Часть команды Expression выполняет новый WMI запрос. Обратите внимание, что запрос помещен в круглые скобки. Благодаря этому, результаты запроса воспринимаются как объект, что особенно важно по той причине, что этот запрос возвращает только один WMI объект (в конце концов, на любом компьютере установлена только одна операционная система). Точка после закрывающей скобки говорит о том, что вы хотите получить доступ к составной части WMI объекта, возвращенного в результате выполнения запроса, в частности, к свойству TotalPhysicalMemory. Значение этого свойства становится значением нашего пользовательского свойства PhysMemory. Попробуйте запустить вышеуказанную команду и посмотрите результат.

Что если вы пытались бы связаться с удаленным компьютером? Один из способов сделать это – просто уточнить имя компьютера для обоих WMI запросов.

Gwmi win32_operatingsystem –comp Server1 |

select caption,

@{Label=’PhysMemory’;

Expression={

(gwmi win32_computersystem –comp Server1).totalphysicalmemory}

}

Но есть способ лучше – уточнить имя компьютера только для начального WMI соединения. После того как WMI объект станет доступным, вы можете использовать специальное свойство __SERVER, чтобы получить доступ к имени компьютера. Это означает, что вам придется изменить имя компьютера только в одном месте, для того чтобы отправить запрос другому компьютеру:

Gwmi win32_operatingsystem –comp Server1 |

select caption,

@{Label=’PhysMemory’;

Expression={

(gwmi win32_computersystem –comp $_.__SERVER).totalphysicalmemory}

}

В данном примере заполнитель $_ , расположенный в скриптовом блоке Expression, содержит WMI_объект, который был передан по конвейеру командлету Select-Object. Вслед за ним идет точка, которая указывает, что мы хотим получить доступ к части объекта, содержащегося в данном заполнителе. Мы получаем доступ к параметру __SERVER, который содержит информацию об имени компьютера, из которого пришел WMI-объект. Это имя компьютера станет значением параметра –computerName в нашем следующем WMI запросе.

Отбор данных

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

Gwmi Win32_Service | Where { $_.Name –eq ‘BITS’ }

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

Командлет Get-WmiObject предлагает параметр –filter, который отправляет ваш критерий WMI-сервису. WMI-сервис может отфильтровать информацию намного быстрее и вернуть только те результаты, которые соответствуют вашим критериям. К сожалению, WMI-сервис не принимает символы сравнения Windows PowerShell, поэтому, вам придется вспомнить несколько другой синтаксис для указания критериев:

Gwmi Win32_Service –filter «Name = ‘BITS'»

Пару слов об этом синтаксисе:

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

• К знакам сравнения относятся:

= (equality)

<> (inequality)

>= (greater than or equal to)

<= (less than or equal to)

> (greater than)

< (less than)

• LIKE (разрешает групповые символы)

• Не используйте заполнитель $_, поскольку он работает только в Windows PowerShell, но не в WMI. Для указания критерия WMI указывайте имя свойства.

• Можно использовать ключевые слова AND и OR, чтобы указать несколько критериев.

Символ LIKE является особенно гибким. Применяя его, вы можете:

• Использовать % в качестве группового символа. “Name LIKE ‘%windows%’”

• Использовать _ в качестве 1-символьного группового знака.

• Использовать [ и ], чтобы обозначить ряд или набор символов: “DriveType LIKE ‘[abcdef]’”

WMI, как и Windows PowerShell, обычно нечувствительна к регистру. Ключевые слова, такие как LIKE могут быть напечатаны и строчными буквами – like; символы в командной строке, например, названия сервисов, также нечувствительны к регистру. Некоторые WMI-провайдеры чувствительны к регистру, но это, скорее, исключения.

И, наконец, лучший способ произвести фильтрацию – это расположить критерии фильтрации как можно ближе к левому краю командной строки Windows PowerShell. Когда вы можете произвести фильтрацию путем использования параметра –filter командлета, предпочтительнее использовать Where-Object для выполнения этой задачи.

WQL-синтаксис

Иногда вы можете столкнуться с языком написания запросов WMI Query Language (WQL), например, в рамках более старых технологий, таких как VBScript, где WQL был приоритетным способом составления запросов по извлечению данных. Windows PowerShell позволяет использовать такие запросы. Для этого нужно просто прикрепить строку запроса к параметру –query командлета Get-WmiObject:

Gwmi –query «SELECT * FROM Win32_Process»

Параметр –query может быть использован в сочетании с –namespace, –credential, –computername и многими другими параметрами, но не с – class, так как строка запроса должна уточнять, к какому классу обращен запрос.

В разделе справочника, посвященному Get-WmiObject, можно найти более подробную информацию об этих параметрах.

Использование параметра –query не имеет конкретных достоинств или недостатков по сравнению с другими формами командлета Get-WmiObject.

Системные свойства

Если вы попробуете передать WMI-объект по конвейеру командлету Format-List *, вы заметите несколько свойств, имена которых начинаются с двойного нижнего подчеркивания, например, __SERVER и __PATH:

Get-WmiObject Win32_Process | Format-List *

Эти системные свойства относятся непосредственно к WMI и могут содержать весьма ценную информацию. Например, вы уже видели, что свойство __SERVER содержит информацию об имени компьютера, с которого «пришел» WMI-объект. Это работает даже в том случае, если вы указали локальный хост или IP адрес для WMI-соединения:

Gwmi Win32_BIOS –computer localhost | Format-List *

__SERVER всегда содержит настоящее имя компьютера. Свойство __PATH также может быть полезным: оно содержит указатель, который может использоваться для уникальной ссылки на WMI-объект. Вы даже можете использовать его для повторного извлечения этого WMI_объекта.

WMI и ForEach-Object

Зачастую приходится извлекать несколько WMI-объектов, после чего работать с каждым из них индивидуально. Так как WMI не является частью Windows PowerShell, оболочка содержит ограниченное количество командлетов для работы с WMI-объектами. В большинстве случаев основные командлеты оболочки могут манипулировать WMI-объектами так, как это требуется для выполнения ваших задач. Но иногда, однако, вы будете вынуждены отправлять WMI_объекты командлету ForEach-Object, чтобы выполнить определенные действия над каждым из них по очереди:

Gwmi Win32_Process | ForEach-Object { $_ }

В данном примере каждый WMI-объект отправляется в конвейер, что означает, что ForEach-Object в действительности не выполняет никакой важной функции. Однако в этот скриптовый блок вы можете поместить практически любую команду Windows PowerShell или даже несколько задач.

  • Что такое WMI
  • Классы, события и безопасность WMI
  • Средства работы с WMI
  • Язык запросов WMI
  • Использование WMI в сценариях
    • Подключение к WMI
    • Подключение методом локатора
    • Подключение методом моникера
    • Использование объекта репозитория
    • Асинхронное использование объектов репозитория
    • Работа с объектами и коллекциями объектов, полученных в результате запросов
    • Примеры сценариев на VBScript
  • Использование WMI в программах
    • Пример программы на VB.NET
  • Использование специальных средств для написания запросов
    • Scriptomatic
    • WMI Code Creator
  • Заключение

Windows Management Instrumentation (WMI) в дословном переводе — это инструментарий управления Windows. Если говорить более развернуто, то WMI — это одна из базовых технологий для централизованного управления и слежения за работой различных частей компьютерной инфраструктуры под управлением платформы Windows. Технология WMI — это расширенная и адаптированная под Windows реализация стандарта WBEM, принятого многими компаниями, в основе которого лежит идея создания универсального интерфейса мониторинга и управления различными системами и компонентами распределенной информационной среды предприятия с использованием объектно-ориентированных идеологий и протоколов HTML и XML.

В основе структуры данных в WBEM лежит Common Information Model (CIM), реализующая объектно-ориентированный подход к представлению компонентов системы. CIM является расширяемой моделью, что позволяет программам, системам и драйверам добавлять в нее свои классы, объекты, методы и свойства.

WMI, основанный на CIM, также является открытой унифицированной системой интерфейсов доступа к любым параметрам операционной системы, устройствам и приложениям, которые функционируют в ней.

Важной особенностью WMI является то, что хранящиеся в нем объекты соответствуют динамическим ресурсам, то есть параметры этих ресурсов постоянно меняются, поэтому параметры таких объектов не хранятся постоянно, а создаются по запросу потребителя данных. Хранилище свойств объектов WMI называется репозиторием и расположено в системной папке операционной системы Windows:

%SystemRoot%System32WBEMRepositoryFS

Так как WMI построен по объектно-ориентированному принципу, то все данные операционной системы представлены в виде объектов и их свойств и методов.

Все классы группируются в пространства имен, которые иерархически упорядочены и логически связаны друг с другом по определенной технологии или области управления. В WMI имеется одно корневое пространство имен Root, которое в свою очередь имеет 4 подпространства: CIMv2, Default, Secutiry и WMI.

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

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

Каждому экземпляру класса можно обратиться по полному пути, который имеет следующую структуру:

[\ComputerNameNameSpace][:ClassName][.KeyProperty1=Value1][,KeyProperty2=Value2]…]
где
 ComputerName - имя компьютера
 NameSpace - название пространства имен
 ClassName - имя класса
 KeyProperty1=Value1, KeyProperty2=Value2 - свойства объекта и значения, по
   которым он идентифицируется.

Пример обращения к процессу с именем «Calc.exe», который запущен на локальной машине:

\.CIMv2:Win32_Process.Name="Calc.exe"

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

Общая безопасность в WMI реализуется на уровне операционной системы, а дополнительная политика безопасности основана на уровнях пространств имен и протокола DCOM. То есть если пользователь не имеет права делать какое-то действие через операционную систему, он не сможет это сделать и через WMI. Если же пользователю дано какое-то право в операционной системе, то это еще не означает, что это право будет и в WMI, так как в WMI действуют дополнительные параметры безопасности на уровне пространств имен.

Каждый объект операционной системы имеет свое описание безопасности (SD) со своим списком доступа (ACL), в котором перечислены идентификаторы пользователей (SID) и их привилегии. Каждое пространство имен может иметь собственное SD со своим ACL, где пользователям могут быть назначены разрешения на чтение данных, выполнение методов, запись классов и данных и другие. Данные о дополнительных разрешениях хранятся в репозитории WMI. Отдельные классы из пространств имен не имеют собственных описаний безопасности, они наследуют их от своего пространства имен.

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

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

Уровни олицетворения могут принимать следующие значения:

Anonymous Анонимный WMI-объект не может получить информацию о пользователе — доступ по такому типу не предоставляется
Identify Идентификация WMI-объект запрашивает маркер доступа пользователя — доступ предоставляется только локально
Impersonate Олицетворение WMI-объект имеет такие же права, какие имеет пользователь — рекомендуемый уровень для выполнения команд на удаленном компьютере
Delegate Делегирование WMI-объект может обратиться от имени пользователя к другому WMI-объекту — нерекомендуемый уровень, так как команды можно выполнять удаленно через цепочку из нескольких компьютеров

Уровни аутентификации (подлинности) могут принимать следующие значения:

None Отсутствует Проверка подлинности отсутствует
Default По умолчанию Стандартные настройки безопасности, которые задаются компьютером-целью команды
Connect Подключение Проверка только во время подключения к компьютеру-цели команды, проверка в ходе работы отсутствует
Call Вызов Проверка подлинности при каждом запросе к компьютеру-цели команды, заголовки пакетов подписываются, но содержимое не шифруется
Pkt Пакет Проверка подлинности всех пакетов к компьютеру-цели команды, заголовки пакетов подписываются, но содержимое не шифруется
PktIntegrity Целостность пакета Проверка подлинности и целостности всех пакетов к компьютеру-цели команды, заголовки пакетов подписываются, но содержимое не шифруется
PktPrivacy Секретность пакета Проверка подлинности и целостности всех пакетов к компьютеру-цели команды, заголовки и содержимое пакетов подписываются и шифруются

wmimgmt.msc — оснастка консоли управления MMC для настройки WMI на локальном компьютере.

Administration via WMI - wmimgmt

Оснастка консоли управления MMC для настройки WMI

winmgmt.exe — консольная утилита управления WMI локального компьютера.

Administration via WMI - winmgmt

Консольная утилита управления WMI

wbemtest.exe — графическая утилита для взаимодействия со структурой WMI на локальном или удаленном компьютере.

Administration via WMI - wbemtest

Графическая утилита для взаимодействия со структурой WMI

wmic.exe — консольная утилита для взаимодействия со структурой WMI на локальном компьютере.

Administration via WMI - wmic

Консольная утилита для взаимодействия со структурой WMI

mofcomp.exe — компилятор MOF-файлов для расширения структуры WMI, управления библиотекой классов WMI и восстановления репозитория.

Administration via WMI - mofcomp

Компилятор MOF-файлов для расширения структуры WMI

Для обращения к объектам WMI используется специфический язык запросов WMI Query Language (WQL), который является одним из разновидностей SQL. Основное его отличие от ANSI SQL — это невозможность изменения данных, то есть с помощью WQL возможна лишь выборка данных с помощью команды SELECT. Помимо ограничений на работу с объектами, WQL не поддерживает такие операторы как DISTINCT, JOIN, ORDER, GROUP, математические функции. Конструкции IS и NOT IS применяются только в сочетании с константой NULL.

Запросы WQL обычно применяются в скриптах, но их также можно протестировать в программе Wbemtest и в консольной утилите Wmic (утилита wmic не требует написания ключевого слова SELECT и полей выборки)

Общий синтаксис запроса WQL выглядит так:

SELECT свойства FROM имя_класса WHERE свойство оператор значение

Например:

' Выбрать все значения класса Win32_Product и вывести все его свойства
SELECT * FROM Win32_Product
' Выбрать все значения класса Win32_Product и вывести свойство Version
SELECT Version FROM Win32_Product
' Выбрать значения класса Win32_Product, где свойство Description равно
' "Microsoft Office", и вывести свойство Version
SELECT Version FROM Win32_Product WHERE Description = "Microsoft Office"

Как видно из примеров, оператор FROM — это источник (класс), коллекцию экземпляров которого нужно получить, а оператор WHERE — это фильтр в запросе.

В скриптах для подключения к WMI используются два метода: с использованием локатора (SWbemLocator) и с использованием моникера (WinMgmts). Метод локатора позволяет установить соединие с пространством имен от имени определенной учетной записи. Метод моникера разрешает подключаться к WMI только от имени текущей учетной записи.

Использование этого метода необходимо, когда в сценарии нужно явно задать имя и пароль учетной записи для подключения к WMI. Объект SWbemLocator создается так:

Set mSWbemLocator = CreateObject("WbemScripting.SWbemLocator")

Подключение к репозиторию WMI производится с помощью метода ConnectServer:

mSWbemServices = mSWbemLocator.ConnectServer([ServerName], [NameSpace], [User], _
 [Password], [Locate], [Authority], [SecurityFlags], [WbemNamedValueSet])
где
 ServerName - имя компьютера (если не указано, то локальный компьютер),
 NameSpace - пространство имен (если не указано, то пространство по умолчанию),
 User - имя пользователя в формате ДоменУчетнаяЗапись (если не указано, то текущий
   пользователь),
 Password - пароль указанного пользователя,
 Locate - код локализации (если не указано, то текущий язык),
 Authority - имя домена, если он не указан в параметре User (если не указано, то
   текущий домен),
 SecurityFlags - время ожидания подключения,
 WbemNamedValueSet - контекстная информация для провайдера, который используется
   для запроса.

Безопасность объекта указывается с помощью свойства Security_, в котором указывается уровень олицетворения и привилегии.

Пример использования локатора:

' Создание объекта
Set mSWbemLocator = CreateObject("WbemScripting.SWbemLocator")
' Задание уровня аутентификации (6 - секретность пакетов)
mSWbemLocator.Security_.AuthenticationLevel = 6
' Задание уровня олицетворения (3 - олицетворение)
mSWbemLocator.Security_.ImpersonationLevel = 3
' Добавление привелегии (разрешение завершать работу)
mSWbemLocator.Security_.Privileges.AddAsString("SeShutdownPrivilege")
' Подключение к репозиторию
Set mSWbemServices = mSWbemLocator.ConnectServer(".", "RootCIMv2",,,,, 128)

Моникер — это строка, задающая путь к классу WMI, экземпляр которого должен быть создан. Моникер состоит из обязательного префикса «winmgmts:», необязательных настроек безопасности, необязательного пути к требуемому классу:

Set mSWbemServices = GetObject("winmgmts:[{SecurityOptions}!]\[Server][NameSpace]")

Пример использования моникера:

' Подключение к пространству имен по умолчанию локального компьютера
Set mSWbemServices0 = GetObject("winmgmts:")

' Подключение к указанному пространству имен удаленного компьютера
' с указанием метода олицетворения
Set mSWbemServices1 = GetObject("winmgmts:{impersonationLevel=Impersonate}!" & _
 "\MyComputerRootCIMv2")

' Подключение к указанному объекту локального компьютера
' с указанием метода олицетворения и привилегий
Set mSWbemServices2 = GetObject("winmgmts:" & _
 "{impersonationLevel=Impersonate, (Shutdown, RemoteShutdown)}!" & _
 "\.RootCIMv2:Win32Process.Handle=4")

' Подключение к указанному объекту локального компьютера
Set mSWbemServices3 = GetObject("winmgmts:\.RootCIMv2:Win32Process.Handle=4")

В результате подключения к WMI получается объект SWbemServices, который обладает определенными свойствами и методами. Наиболее часто используемые из них — это Get, ExecQuery, ExecMethod.

Метод Get используется для возвращения определения класса или экземпляра управляемого ресурса:

Set mObject = Get([ObjectPath],[Flags],[WbemNamedValueSet])
где
 ObjectPath - путь к объекту WMI,
 Flags - опции,
 WbemNamedValueSet - контекстная информация для провайдера.

Пример использования метода Get:

' Подключение к пространству имен
Set mSWbemServices = GetObject("winmgmts:\.RootCIMv2")
' Получение экземпляра класса с заданным свойством
Set mProcess = mSWbemServices.Get("Win32_Process.Handle=4")

Метод ExecQuery используется для выполнения запросов на языке WQL:

Set mObject = ExecQuery(Query,[QueryLanguage],[Flags],[WbemNamedValueSet])
где
 Query - текст запроса,
 QueryLanguage - язык запроса (всегда равен "WQL")
 Flags - опции,
 WbemNamedValueSet - контекстная информация для провайдера.

Пример использования метода ExecQuery:

' Подключение к пространству имен
Set mSWbemServices = GetObject("winmgmts:\.RootCIMv2")
' Получение всех экземпляров класса с заданным свойством
Set mProcesses = mSWbemServices.ExecQuery("SELECT * FROM Win32_Process WHERE Handle = 4")

Метод ExecMethod используется для выполнения метода указанного объекта:

Set mObject = ExecMethod(ObjectPath, MethodName,[InParams],[Flags],[WbemNamedValueSet])
где
 ObjectPath - путь к объекту WMI,
 MethodName - имя метода,
 InParams - входные параметры для метода,
 Flags - опции (всегда равно нулю),
 WbemNamedValueSet - контекстная информация для провайдера.

Пример использования метода ExecMethod:

' Подключение к пространству имен
Set mSWbemServices = GetObject("winmgmts:\.RootCIMv2")
' Получение указателя на класс
Set mProcess = mSWbemServices.Get("Win32_Process")
' Создание коллекции входных параметров для метода
Set mInParams = mProcess.Methods_("Create").InParameters.SpawnInstance_
mInParams.CommandLine = "notepad.exe"
' Выполнение метода
Set mOutParams = mSWbemServices.ExexMethod("Win32_Process", "Create", mInParams)

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

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

Объект «слива событий» (от английского «sink» — раковина) создается следующим образом:

Set mSink = WScript.CreateObject("WbemScripting.SWbemSink", "Sink_")
где
 Sink_ - префикс для функций.

Наиболее часто используемые события, обрабатываемые таким «сливом» асинхронных методов, — это OnObjectReady и OnCompleted. Как можно догадаться из названий событий, первое происходит, когда возвращается очередной объект, порожденный асинхронным запросом. Второе происходит после полного завершения асихронного метода. Событие OnObjectReady выдает на выход объект, который был запрошен асихронной операцией, а событие OnCompleted — код ошибки или 0.

Пример использования асинхронного метода:

' Подключение к пространству имен
Set mSWbemServices = GetObject("winmgmts:\.RootCIMv2")
' Создание объекта "слива событий"
Set mSink = WScript.CreateObject("WbemScripting.SWbemSink", "Sink_")
' Флаг завершения асинхронного метода
mCompleted = False
' Вызов асинхрнонного запроса
mSWbemServices.ExecQueryAsync mSink, "SELECT * FROM Win32_Process"
' Зацикливание скрипта до окончание запроса (здесь можно выполнять любые другие операции)
' Как только асинхронный метод вернет какое-нибудь событие, то будет вызвана
' соотвествующая процедура, которая описана ниже, а работа основного скрипта на время
' прервется
While Not mCompleted
   WScript.Sleep 1000
Wend
' Процедура обработки события возврата очередного объекта
Sub Sink_OnObjectReady(mWbemObject, mWbemAsyncContext)
   WScript.Echo mWbemObject.Name
End Sub
' Процедура обработки события завершения запроса
Sub Sink_OnCompleted(mResult, mWbemErrorObject, mWbemAsyncContext)
   If mResult = 0 Then
       WScript.Echo "Запрос успешно завершен"
   Else
       WScript.Echo "Запрос завершен с ошибкой"
   End If
   mCompleted = True
End Sub

Рассмотренные выше методы возвращают объекты и коллекции объектов, которые обладают своими методами и свойствами. Информацию о всех свойствах и методах, поддерживаемых конкретным объектом, можно получить с помощью такого скрипта:

' Объект mObject получен методом Get
' Получение свойств и их значений
For Each mCurrentProperty in mObject.Properties_
   Wscript.Echo mCurrentProperty.Name & ": " & mCurrentProperty.Value
Next
' Получение методов
For Each mCurrentMethod in mObject.Methods_
   Wscript.Echo mCurrentMethod.Name
Next

Коллекция объектов всегда обладает общими для всех экземпляров свойствами, наиболее часто используемые свойства — это Count и Item.

Count — это свойство коллекции объекта, которое содержит количество элементов коллекции.

Item(mObjectPath) — это метод, который возвращает один объект коллекции, соответствующий указанному пути.

Как уже выяснилось, объект имеет свои методы и свойства, которые соответствуют классу данного экземпляра, но помимо классовых свойств и методов всем объектам присущи универсальные, которые оканчиваются на символ подчеркивания, чтобы отличать их от классовых. Наиболее часто используемые универсальные методы — это ExecMethod_ и Put_.

ExecMethod_(mMethod, mWbemInParamsm, mFlags, mWbemNamedValueSet) — это метод для исполнения классового метода у используемого объекта.

Put_(mFlags, mWbemNamedValueSet) — это метод для записи измененных свойств объекта в репозиторий WMI и в реальный объект.

Пример использования метода Put_ — изменение метки диска:

' Подключение к пространству имен
Set mSWbemServices = GetObject("winmgmts:\.RootCIMv2")
' Получение объекта логического диска
Set mDisks = mSWbemServices.ExecQuery("SELECT * FROM Win32_LogicalDisk WHERE DeviceID = 'C:'")
' Перебор коллекции возвращенных объектов
For Each mDisk in mDisks
   ' Смена метки диска
   oDisk.VolumeName = "System"
   ' Запись изменений
   oDisk.Put_
Next

Пример использование класса CIM_DataFile для переименования файлов:

' Целевой компьютер
mComputer = "."
' Целевая папка
mFolderPath = "C:Temp"
' Подключение к пространству имен целевого компьютера
Set mSWbemServices = GetObject("winmgmts:\" & mComputer & "RootCIMv2")
' Получение колекции файлов целевой папки
Set mFileList = mSWbemServices.ExecQuery ("ASSOCIATORS OF {Win32_Directory.Name='" _
 & mFolderPath & "'} WHERE ResultClass = CIM_DataFile")
' Обработка коллекции файлов
For Each mCurrentFile In mFileList
   ' Формирование нового имени файла
   mNewName = mCurrentFile.Drive & mCurrentFile.Path & mCurrentFile.FileName _
     & "." & mCurrentFile.Extension & ".old"
   ' Переименование файла
   errResult = mCurrentFile.Rename(mNewName)
   ' Формирование отчета о переименовании
   if errResult = 0 then
       mResultText = mResultText & "File " & mCurrentFile.Name & " renamed to " _
         & mNewName & vbCrLf
   else
       mResultText = mResultText & "Error at renaming " & mCurrentFile.Name & _
         " file" & vbCrLf
       errResult = 0
   end if
Next
' Вывод отчета о переименовании
Wscript.Echo(mResultText)

Аналогично приведенному примеру можно совершать и другие действия с файлами, так как класс CIM_DataFile поддерживает методы: копирование, удаление, переименование, NTFS-сжатие, смена разрешений, смена владельца.

Пример использования классов оборудования компьютера для получения информации о количестве портов USB 2.0 и используемых USB-устройствах:

iCounter = 0
' Целевой компьютер
mComputer = "."
' Подключение к пространству имен целевого компьютера
Set mSWbemServices = GetObject("winmgmts:\" & mComputer & "RootCIMv2")
' Получение колекции USB-контроллеров
Set mControllerList = mSWbemServices.ExecQuery("Select * From Win32_USBController")
' Обработка USB-контроллеров
For Each mCurrentController in mControllerList
   If Instr(mCurrentController.Name, "Enhanced") Then
       iCounter = iCounter + 1
   End If
Next
' Формирование отчета о USB-контроллерах
mResultText = "USB 2.0 Ports count: " & iCounter & vbCrLf & vbCrLf
' Получение колекции USB-устройств
Set mDeviceList = mSWbemServices.ExecQuery ("Select * From Win32_USBControllerDevice")
' Обработка USB-устройств
For Each mCurrentDevice in mDeviceList
   mDeviceName = mCurrentDevice.Dependent
   mDeviceName = Replace(mDeviceName, Chr(34), "")
   mDeviceNames = Split(mDeviceName, "=")
   mDeviceName = mDeviceNames(1)
   ' Получение свойств каждого устройства по его идентификатору
   Set mUSBDeviceList = mSWbemServices.ExecQuery("Select * From Win32_PnPEntity " _
     & "Where DeviceID = '" & mDeviceName & "'")
   ' Обработка свойств устройства
   For Each mCurrentUSBDevice in mUSBDeviceList
       ' Формирование отчета о USB-устройствах
       mResultText = mResultText & mCurrentUSBDevice.Description & vbCrLf
   Next    
Next
' Вывод результата
Wscript.Echo(mResultText)

Пример использования класса свойств принтеров для получения информации о настройках принтеров:

' Целевой компьютер
mComputer = "."
' Задание констант кодов типов доступа к текстовому файлу
Const ForReading = 1
Const ForWriting = 2
Const ForAppending = 8
' Создание объекта оболочки и получение текущей директории
Set oShell = CreateObject("wscript.shell")
sWorkDirectory = oShell.CurrentDirectory
' Создание объекта файловой системы и файла
Set oFSO = CreateObject ("Scripting.FileSystemObject")
Set mResultFile = oFSO.OpenTextFile(sWorkDirectory & "PrinterList.txt", ForWriting, True, 0)
' Подключение к пространству имен целевого компьютера
Set mSWbemServices = GetObject("winmgmts:\" & mComputer & "RootCIMv2")
' Получение колекции локальных принтеров
Set mPrinterList = mSWbemServices.ExecQuery("SELECT * FROM Win32_Printer WHERE Local = True")
' Запись заголовка в файл
mResultFile.WriteLine("Name;Comment;Location;ShareName;DriverName;PortName;")
' Обработка каждого принтера
For Each mCurrentPrinter in mPrinterList
   mResultFile.WriteLine(mCurrentPrinter.Name & ";" & mCurrentPrinter.Comment & ";" & _
     mCurrentPrinter.Location & ";" & mCurrentPrinter.ShareName & ";" & _
     mCurrentPrinter.DriverName & ";" & mCurrentPrinter.PortName & ";")
Next
' Закрытие файла
mResultFile.Close

Пример использования класса свойств сетевого адаптера для изменения конфигурации сетевой карты — перевода с DHCP на статическую конфигурацию:

' Целевой компьютер
mComputer = "."
' Новые сетевые параметры задаются конкретными значениями
' Аналогичные параметры задаются значением "The same"
' Пустые парамеры задаются значением ""
mNewIPAddress = "The same"
mNewSubnetMask = "The same"
mNewDNSServer = "The same"
mNewDefaultIPGateway = "The same"
mNewWINSPrimaryServer = "The same"
mNewWINSSecondaryServer = "The same"
' Рабочие массивы
Dim mDNSServerList()
Dim mDefaultIPGatewayList()
Dim mGatewayMetricList()
Dim mNewDNSServerList()
Dim mNewDefaultIPGatewayList()
Dim mNewGatewayMetricList()
' Подключение к пространству имен целевого компьютера
Set mSWbemServices = GetObject("winmgmts:\" & mComputer & "RootCIMv2")
' Получение коллекции адаптеров с указанным IP-адресом
Set mAdapterList = mSWbemServices.ExecQuery ("Select * From Win32_NetworkAdapter")
' Получение MAC-адреса адаптера локального адаптера
For Each mCurrentAdapter In mAdapterList
   If InStr(LCase(mCurrentAdapter.NetConnectionID), "локальн") > 0 _
     Or InStr(LCase(mCurrentAdapter.NetConnectionID), "local") > 0 Then
       mMACAddress = mCurrentAdapter.MACAddress
       mCaption = mCurrentAdapter.Caption
       Exit For
   End If
Next
' Получение коллекции параметров адаптера с указанным MAC-адресом
Set mAdapterConfigList = mSWbemServices.ExecQuery _
 ("Select * From Win32_NetworkAdapterConfiguration WHERE MACAddress = '" _
 & mMACAddress & "'")
' Получение текущих параметров сетевого адаптера с указанным MAC-адресом
For Each mCurrentAdapterConfig In mAdapterConfigList
   ' IP-адрес
   If IsNull(mCurrentAdapterConfig.IPAddress) = False Then
       For Each mCurrentIPAddress In mCurrentAdapterConfig.IPAddress
           mIPAddress = mCurrentIPAddress
           Exit For
       Next
   End If
   If mNewIPAddress = "The same" Then mNewIPAddress = mIPAddress
   mNewIPAddressList = Array(mNewIPAddress)
   ' Маска подсети
   If IsNull(mCurrentAdapterConfig.IPSubnet) = False Then
       For Each mCurrentIPSubnet In mCurrentAdapterConfig.IPSubnet
           mSubnetMask = mCurrentIPSubnet
           Exit For
       Next
   End If
   If mNewSubnetMask = "The same" Then mNewSubnetMask = mSubnetMask
   mNewSubnetMaskList = Array(mNewSubnetMask)
   ' DNS сервера
   If IsNull(mCurrentAdapterConfig.DNSServerSearchOrder) = False Then
       iCounter = 0
       For Each mCurrentDNSServer In mCurrentAdapterConfig.DNSServerSearchOrder
           Redim Preserve mDNSServerList(iCounter)
           mDNSServerList(iCounter) = mCurrentDNSServer
           iCounter = iCounter + 1
       Next
   End If
   If mNewDNSServer = "The same" Then
       For iCounter = 0 To UBound(mDNSServerList)
           Redim Preserve mNewDNSServerList(iCounter)
           mNewDNSServerList(iCounter) = mDNSServerList(iCounter)
       Next
   Else
       For iCounter = 0 To UBound(Split(mNewDNSServer,";"))
           Redim Preserve mNewDNSServerList(iCounter)
           mNewDNSServerList(iCounter) = Split(mNewDNSServer,";")(iCounter)
       Next
   End If
   ' Шлюзы
   If IsNull(mCurrentAdapterConfig.DefaultIPGateway) = False Then
       iCounter = 0
       For Each mCurrentDefaultIPGateway In mCurrentAdapterConfig.DefaultIPGateway
           Redim Preserve mDefaultIPGatewayList(iCounter)
           mDefaultIPGatewayList(iCounter) = mCurrentDefaultIPGateway
           Redim Preserve mGatewayMetricList(iCounter)
           mGatewayMetricList(iCounter) = iCounter + 1
           iCounter = iCounter + 1
       Next
   End If
   If mNewDefaultIPGateway = "The same" Then
       For iCounter = 0 To UBound(mDefaultIPGatewayList)
           Redim Preserve mNewDefaultIPGatewayList(iCounter)
           mNewDefaultIPGatewayList(iCounter) = mDefaultIPGatewayList(iCounter)
           Redim Preserve mNewGatewayMetricList(iCounter)
           mNewGatewayMetricList(iCounter) = iCounter + 1
       Next
   Else
       For iCounter = 0 To UBound(Split(mNewDefaultIPGateway,";"))
           Redim Preserve mNewDefaultIPGatewayList(iCounter)
           mNewDefaultIPGatewayList(iCounter) = Split(mNewDefaultIPGateway,";")(iCounter)
           Redim Preserve mNewGatewayMetricList(iCounter)
           mNewGatewayMetricList(iCounter) = iCounter + 1
       Next
   End If
   ' WINS сервера
   If IsNull(mCurrentAdapterConfig.WINSPrimaryServer) = False Then
       mWINSPrimaryServer = mCurrentAdapterConfig.WINSPrimaryServer
   End If
   If mNewWINSPrimaryServer = "The same" Then
       If IsNull(mCurrentAdapterConfig.WINSPrimaryServer) = True Then
           mNewWINSPrimaryServer = ""
       Else
           mNewWINSPrimaryServer = mWINSPrimaryServer
       End If
   End If
   If IsNull(mCurrentAdapterConfig.WINSSecondaryServer) = False Then
       mWinsSecondaryServer = mCurrentAdapterConfig.WINSSecondaryServer
   End If
   If mNewWinsSecondaryServer = "The same" Then
       If IsNull(mCurrentAdapterConfig.WINSSecondaryServer) = True Then
           mNewWinsSecondaryServer = ""
       Else
           mNewWinsSecondaryServer = mWINSSecondaryServer
       End If
   End If
   Exit For
Next
' Формирование сообщения по текущей и по будущей конфигурациям сетевого адаптера
mInfoMessage = "Network adapter: " & mCaption & vbCrLf _
 & "MAC address: " & mMACAddress & vbCrLf _
 & "Current configuration:" & vbCrLf _
 & vbTab & "IP address: " & mIPAddress & vbCrLf _
 & vbTab & "Subnet mask: " & mSubnetMask & vbCrLf _
 & vbTab & "Default Gateway: " & Join(mDefaultIPGatewayList,";") & vbCrLf _
 & vbTab & "DNS servers: " & Join(mDNSServerList,";") & vbCrLf _
 & vbTab & "WINS Primary Server: " & mWINSPrimaryServer & vbCrLf _
 & vbTab & "WINS Secondary Server: " & mWINSSecondaryServer & vbCrLf _
 & "New configuration:" & vbCrLf _
 & vbTab & "IP address: " & mNewIPAddress & vbCrLf _
 & vbTab & "Subnet mask: " & mNewSubnetMask & vbCrLf _
 & vbTab & "Default Gateway: " & Join(mNewDefaultIPGatewayList,";") & vbCrLf _
 & vbTab & "DNS servers: " & Join(mNewDNSServerList,";") & vbCrLf _
 & vbTab & "WINS Primary Server: " & mNewWINSPrimaryServer & vbCrLf _
 & vbTab & "WINS Secondary Server: " & mNewWINSSecondaryServer & vbCrLf _
 & vbCrLf & "Please confirm the changes" & mNewWINSSecondaryServer & vbCrLf
' Окно подтверждения изменения настроек сетевого параметра
mChangeFlag = MsgBox(mInfoMessage, vbOKCancel, "Network card settings change")
If mChangeFlag = vbOK Then
   ' Установка нового IP адреса
   For Each mCurrentAdapterConfig in mAdapterConfigList
       errEnable = mCurrentAdapterConfig.EnableStatic _
         (mNewIPAddressList, mNewSubnetMaskList)
       errGateways = mCurrentAdapterConfig.SetGateways _
         (mNewDefaultIPGatewayList, mNewGatewayMetricList)
       errWINS = mCurrentAdapterConfig.SetWINSServer _
         (mNewWINSPrimaryServer, mNewWinsSecondaryServer)
       errDNS = mCurrentAdapterConfig.SetDNSServerSearchOrder _
         (mNewDNSServerList)
       Exit For
   Next
   ' Pезультат операции
   mInfoMessage = "Operation result:" & vbCrLf _
     & "IP address error code: " & errEnable & vbCrLf _
     & "Gateway error code: " & errGateways & vbCrLf _
     & "DNS error code: " & errDNS & vbCrLf _
     & "WINS error code: " & errWINS & vbCrLf
Else
   mInfoMessage = "The operation is canceled"
End If
Wscript.Echo(mInfoMessage)

Ресурсы WMI доступны не только через скрипты, к ним можно обращаться из других языков программирования и даже из программ.

Существует два способа обращения к WMI через Visual Basic.NET.

Первый способ берет свое начало из скриптов VBS. Он использует обращение к инстументу winmgmts, как это делалось в методе моникера:

oComputerSystem = GetObject("winmgmts:[Options!]WMINameSpace).ExecQuery(WQLQuery)

Пример запроса модели комьютера (консольное приложение)

Module TestModule
   Sub Main()
       ' Объявление переменных
       Dim oWMIObject As Object
       Dim oComputerSystem As Object
       Try
           ' Подключение к WMI
           oWMIObject = GetObject("winmgmts:{impersonationLevel=impersonate}!\.rootcimv2")
           ' Выполнение запроса
           oComputerSystem = oWMIObject.ExecQuery("Select * from Win32_ComputerSystem")
           For Each oConfigutation As Object In oComputerSystem
               ' Вывод результатов в консоль
               Console.Write(oConfigutation.Model)
           Next
       Catch ex As Exception
           Console.Write("Ошибка запроса к WMI")
       End Try
End Module

Второй способ является более правильным с точки зрения Visual Studio. Он использует классSystem.Managementдля запросов к WMI, в котором указываются пространство WMI, параметры подключения и WQL запрос:

' Задание параметров подключения
mOptions = New Management.ConnectionOptions([Options])
' Задания WMI пространства имен
mScope = New Management.ManagementScope(WMINameSpace, mOptions)
' Задание WQL запроса
mQuery = New Management.ObjectQuery(WQLQuery)
' Создание объекта поиска по WMI с указанными параметрами
mSearcher = New Management.ManagementObjectSearcher(mScope, mQuery)
' Выполнение запроса
mQueryCollection = mSearcher.Get()

Использование полученных объектов аналогично использованию в скриптах.

Пример запроса сервисов локального комьютера (консольное приложение):

Module TestModule
   Sub Main()
       ' Объявление переменных
       Dim mOptions As Management.ConnectionOptions
       Dim mScope As Management.ManagementScope
       Dim mQuery As Management.ObjectQuery
       Dim mSearcher As Management.ManagementObjectSearcher
       Dim mQueryCollection As Management.ManagementObjectCollection
       ' Задание параметров подключения
       mOptions = New Management.ConnectionOptions
       ' Задания WMI пространства имен
       mScope = New Management.ManagementScope("\.rootcimv2", mOptions)
       ' Задание WQL запроса
       mQuery = New Management.ObjectQuery("SELECT * FROM Win32_Service")
       ' Создание объекта поиска по WMI с указанными параметрами
       mSearcher = New Management.ManagementObjectSearcher(mScope, mQuery)
       Try
           ' Выполнение запроса
           mQueryCollection = mSearcher.Get()
           ' Вывод результатов в консоль
           For Each mObject As Management.ManagementObject In mQueryCollection
               Console.WriteLine(mObject.Item("DisplayName").ToString)
           Next
       Catch ex As Exception
           Console.Write("Ошибка запроса к WMI")
       End Try
   End Sub
End Module

В качестве примера прораммы использования WMI в Visual Basic.Net представлено консольное приложение управления сервисом печати компьютера. Приложение запрашивает модель компьютера и выводит результат в консоль. После чего запрашивает состояние сервиса печати и, если он остановлен, предлагает запустить его.

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

Листинг файла WMIClass.vb:

Public Class WMIClass

' Функция получения модели копьютера
#Region "GetModel 1.0"
   Public Function GetModel(Optional ByVal IPAddress As String = ".") As String
       Dim mTempValue As String = Nothing
       Try
           Dim oComputerSystem = GetObject("winmgmts:{impersonationLevel=impersonate}!\" & _
             IPAddress & "rootcimv2").ExecQuery("Select * from Win32_ComputerSystem")
           For Each oConfigutation As Object In oComputerSystem
               mTempValue = oConfigutation.Model
           Next
       Catch ex As Exception

       End Try
       Return mTempValue
   End Function
#End Region

' Функция получения состояния сервиса компьютера
#Region "GetServiceState 1.0"
   Public Function GetServiceState(Optional ByVal IPAddress As String = ".", _
     Optional ByVal ServiceName As String = "winmgmt") As Boolean
       Dim mOptions As Management.ConnectionOptions
       Dim mScope As Management.ManagementScope
       Dim mQuery As Management.ObjectQuery
       Dim mSearcher As Management.ManagementObjectSearcher
       mOptions = New Management.ConnectionOptions
       mScope = New Management.ManagementScope("\" & IPAddress & "rootcimv2", mOptions)
       mQuery = New Management.ObjectQuery("SELECT * FROM Win32_Service " & _
         "WHERE DisplayName = '" & ServiceName & "'")
       mSearcher = New Management.ManagementObjectSearcher(mScope, mQuery)
       Try
           Dim mQueryCollection As Management.ManagementObjectCollection = mSearcher.Get()
           For Each mObject As Management.ManagementObject In mQueryCollection
               If mObject("State") = "Running" Then
                   Return True
               Else
                   Return False
               End If
           Next
           Return False
       Catch ex As Exception
           Return False
       End Try
   End Function

   Public Function GetServiceStateFull(Optional ByVal IPAddress As String = ".", _
     Optional ByVal ServiceName As String = "winmgmt") As String
       Dim mOptions As Management.ConnectionOptions
       Dim mScope As Management.ManagementScope
       Dim mQuery As Management.ObjectQuery
       Dim mSearcher As Management.ManagementObjectSearcher
       mOptions = New Management.ConnectionOptions
       mScope = New Management.ManagementScope("\" & IPAddress & "rootcimv2", mOptions)
       mQuery = New Management.ObjectQuery("SELECT * FROM Win32_Service " &
         "WHERE DisplayName = '" & ServiceName & "'")
       mSearcher = New Management.ManagementObjectSearcher(mScope, mQuery)
       Try
           Dim mQueryCollection As Management.ManagementObjectCollection = mSearcher.Get()
           For Each mObject As Management.ManagementObject In mQueryCollection
               Return mObject("State")
           Next
           Return "No data"
       Catch ex As Exception
           Return "No data"
       End Try
   End Function
#End Region
	
' Процедура управления сервисом компьютера
#Region "Manage Service 1.0"
   Public Sub ManageService(Optional ByVal IPAddress As String = ".", _
     Optional ByVal ServiceName As String = "winmgmt", _
     Optional ByVal Action As String = "StartService")
       Dim mOptions As Management.ConnectionOptions
       Dim mScope As Management.ManagementScope
       Dim mQuery As Management.ObjectQuery
       Dim mSearcher As Management.ManagementObjectSearcher
       Dim mQueryCollection As Management.ManagementObjectCollection
       mOptions = New Management.ConnectionOptions
       mScope = New Management.ManagementScope("\" & IPAddress & "rootcimv2", mOptions)
       mQuery = New Management.ObjectQuery("SELECT * FROM Win32_Service " & _
         "WHERE DisplayName = '" & ServiceName & "'")
       mSearcher = New Management.ManagementObjectSearcher(mScope, mQuery)
       Try
           mQueryCollection = mSearcher.Get()
           For Each mObject As Management.ManagementObject In mQueryCollection
               mObject.InvokeMethod(Action, Nothing)
           Next
       Catch ex As Exception

       End Try
   End Sub
#End Region
	
End Class

Листинг файла TestModule.vb:

Module TestModule
   ' Создание экземпляра класса WMIClass
   Private mWMIClass_Instance As New WMIClass

   Sub Main()
       Dim mKeyNumber As Integer
       ' Получение модели компьютера и результата в консоль
       Console.WriteLine("Модель компьютера: " & mWMIClass_Instance.GetModel())
       ' Проверка состояния сервиса "Диспетчер печати"
       If mWMIClass_Instance.GetServiceState(, "Диспетчер печати") = True Then
           Console.WriteLine("Служба ""Диспетчер печати"" запущена")
       Else
           Console.WriteLine("Служба ""Диспетчер печати"" остановлена")
           Console.Write("Запустить службу ""Диспетчер печати""? Y/N: ")
           ' Чтение символа с клавиатуры
           mKeyNumber = Console.Read
           If mKeyNumber = 89 Or mKeyNumber = 121 Then
               Console.WriteLine("Запуск службы ""Диспетчер печати""...")
               ' Попытка запуска сервиса "Диспетчер печати"
               mWMIClass_Instance.ManageService(, "Диспетчер печати", "StartService")
               ' Ожидание 5 секунда
               Threading.Thread.Sleep(5000)
               ' Проверка состояния сервиса "Диспетчер печати"
               If mWMIClass_Instance.GetServiceState(, "Диспетчер печати") = True Then
                   Console.WriteLine("Служба ""Диспетчер печати"" успешно запущена")
               Else
                   Console.WriteLine("Запуск службы ""Диспетчер печати"" не удался")
               End If
           End If

       End If
       Console.WriteLine("Нажмите любую клавишу для продолжения")
       ' Ожидание нажатия любой клавиши
       Console.ReadKey()
   End Sub
End Module

Для того, чтобы облегчить написание скриптов и программ, существуют специальные утилиты, которые помогают просмотреть структуру пространства WMI и показавают примеры использования всех классов. Наиболее распространенные утилиты — это Scriptomatic и WMI Code Creator.

Инструмент Scriptomatic предствляет из себя HTA-приложение, которое генерирует код, использующий WMI, на VBSScript, JScript, Perl и Python. Сам по себе WMI может оказаться трудным для изучения, поэтому рекомендуется использовать Scriptomatic для освоения классов WMI, а также для быстрого создания шаблонов обращения к ресерсум WMI. Scriptomatic позволяет выбрать интересующий объект WMI, а затем генерирует код на указанном языке программирования. Полученный код можно выполнить непосредственно в оболочке программы, а результаты вывести в консоль, текстовый файл, HTML, Excel или XML. Инструмент доступен на сайте Microsoft по этой ссылке.

Administration via WMI - wmiscriptomatic

WMI Scriptomatic — Инициализация

Administration via WMI - wmiscriptomatic

WMI Scriptomatic — Win32_OpepatingSystem

Программа WMI Code Creator представляет из себя генератор кода, который использует WMI для получения информации и для осуществления задач упраления компьютерами. Программа может помочь научиться использовать WMI-скрипты и WMI-приложения для управления как локальным, так и удаленным компьютером. Инструмент доступен на сайте Microsoft по этой ссылке.

Используя WMI Code Creator можно найти любую информацию о компьютере: имя и версия операционной системы, свободное место на диске, состояние сервисов и так далее. Можно выполнить метод из WMI класса для осуществления управления компьютером: создать или удалить сервис, запустить или закрыть программы, назначить разрешения на папку или файл и многое другое. Этот инструмент так же позволяет просматривать доступное WMI-пространство и WMI-классы, чтобы найти нужную для программирования инстанцию с ее описанием, свойствами, методами и примером использования.

Administration via WMI - wmicodecreator

WMI Code Creator — Query

Administration via WMI - wmicodecreator

WMI Code Creator — Method

Administration via WMI - wmicodecreator

WMI Code Creator — Event

Administration via WMI - wmicodecreator

WMI Code Creator — Namespace

Итак, Windows Management Instrumentation — это мощный инструмент для администрирования операционных систем семейства Windows с помощью скриптов. С помощью WMI можно управлять устройствами, учетными записями, сервисами, процессами, сетевыми интерфейсами и другими программами, которые расширяют базовую структуру WMI своими классами.

Помимо скриптов WMI может применяться и в полноценных программах, то есть программисты могут внедрять запросы к WMI в исполняемый код, завязывая свою программу с работой WMI, благодаря чему программа становится проще и легче, но зависимой от правильности работы Windows Management Instrumentation.

Интересно, что новая командная оболочка Windows PowerShell связана с WMI как технической точки зрения, так и с точки зрения создания запросов — утилита Wmic.exe функционирует в некотором смысле аналогичным образом. В Windows PowerShell поддержка WMI, представлена в точно таком же согласованном объектном виде, как и другие возможности данной оболочки, поэтому при изучении этой оболочки применение WMI не становится такой сложной задачей, как это было в VBScript — не нужно изучать синтаксис и механизмы языка, отличного от языка скрипта.

Инструменты для написания скриптов ScriptReference.zip.

Более подробно о Windows PowerShell можно будет прочитать в следующих выпусках статей сайта www.SysEngineering.ru.

Виталий Бочкарев

Last time we’ve dealt with objects: PowerShell for Beginners (Part 8): The Power of PowerShell – Getting in Touch with Objects (Get-Member, Select-Object). Of course, I was thinking something. Part 8 is a prerequisite for this part. We are now going to make a huge step forward. And this part is full of examples. But before we begin, the answer of the last exercise. We will also have a quick review what we’ve learned so far in Part 8.

All parts of the series can be found here: PowerShell for Beginners (Series)

Review (Part 8)

Here are the assignments and the solutions from part 8:

Attributes

Create a directory C:Temp1. Create a text file testfile1.txt in C:Temp1. Use only PowerShell. If you need assistance use the help (Get-Help). Open the file. Now show the following attributes with Select-Object or another technique: The name of the file, the file extension and the date of last access.

Let’s create a new directory and a new file.

New-Item -ItemType Directory -Path C:Temp1; New-Item -ItemType File -Path C:Temp1testfile1.txt

Unbenannt.PNG

The next task is to show only a few attributes. Run Get-Member to explore all of them.

Get-ChildItem C:Temp | Get-Member

We now find the attributes Name, Extension and LastAccessTime. Let’s put this all together in Select-Object.

Get-ChildItem C:temp1testfile1.txt | Select-Object Name,Extension,LastAccessTime

Unbenannt.PNG

Methods

Calculate back 10 years using Get-Date from today. Answer the following question: Which day of the year was that? (1..365?)

The next task is to calculate 10 years back. For this we can use the .NET method.

(Get-Date).AddYears(-10)

Unbenannt.PNG

Now use Get-Member to find the attribute DayOfYear. Just add that to the last command.

(Get-Date).AddYears(-10).DayOfYear

Unbenannt.PNG

Review Part 8


You have to deal with Objects. Otherwise you will never realize the power of PowerShell. Use Get-Member to explore objects. Attributes show you what an Object is. Use Select-Object to retrieve attributes. Methods can change or do something. Put the command and the method values in brackets.


The Power of WMI

Windows Management Instrumentation is a basic Windows technology. WMI (Windows Management Instruments) provides read and write access to almost all Windows settings. WMI is one of the most important interfaces for the administration and remote maintenance of workstations and servers.

WMI is a Windows service. Open Windows PowerShell. Run

wmimgmt.msc

Unbenannt.PNG

To give you a little foretaste of what’s coming up the further parts of this post a quick and powerful example.

Which software is installed on Client01? Note, that I’m logged on another computer. This is a remote call.

Get-WmiObject win32_product -ComputerName client01 | Select-Object Name,InstallDate

Unbenannt.PNG

Get-WmiObject has to be used to explore WMI Objects. But there’s also Get-CIMInstance. This could be a little confusing. Just remember WMI = CIM and CIM =WMI.

For the further part, I will use Get-CIMInstance, because it’s the newer and more flexbile command. More about this later.

Get-CimInstance win32_product -ComputerName client01 | Select-Object Name,InstallDate

Unbenannt.PNG

Summary


WMI (Windows Management Instruments) provides read and write access to almost all Windows settings. WMI is one of the most important interfaces for the administration. There are two important cmdlets: Get-WmiObject and Get-CimInstance.


Exploring WMI Objects

Do you remember my 2 step method from part 8 to explore objects? The same goes here, with WMI.

1. Inquiry of all possibilities: Run Get-Member

Get-CimInstance win32_product | Get-Member -MemberType property

1.PNG

2. Call the attribute or method with (). or select-object or select

Get-CimInstance win32_product | Select-Object Name,InstallDate ,InstallSource,Vendor,Packagename

1.PNG

The question is now how to find all WMI Classes? So far, we’ve only looked at win32_product.

To view all WMI Classes run Get-WmiObject with the list parameter.

Get-WmiObject -List

A huge number of objects fill the screen.

Another option is – if you know about what you’re searching for – using Get-CimInstance and pressing TAB. For example if you want to view something about your BIOS then type

Get-CimInstance win32_bi

and press TAB. The third one is the right one.

Unbenannt.JPG

It is impossible to go through all instances and classes here. That’s why from now on we will focus on examples you can build on.

What have we learned so far?


Run Get-WmiObject -List for discovering WMI Objects. Run Get-CimInstance and press TAB to discover WMI Objects. 


WMI Examples

win32_OperatingSystem

One of the most used wmi queries is related to win32_operatingsystem.

Get-CimInstance win32_operatingsystem

Unbenannt.JPG

Hmm… Are you impressed? Not really. REMEMBER the 2 step method. There’s more. Find it out!

Get-CimInstance win32_operatingsystem | Get-Member -MemberType property

1.JPG

What do you think about this command:

Get-CimInstance win32_operatingsystem | Select-Object InstallDate,LastBootUpTime,SystemDrive,Version,Serialnumber,OSType,FreePhysicalMemory,Status,NumberOfUsers,WindowsDirectory

1.JPG

win32_UserAccount

Another useful WMI instance is win32_useraccount.

Get-CimInstance Win32_UserAccount

Unbenannt.JPG

There’s more. Again: Run Get-Member!

Get-CimInstance Win32_UserAccount | Get-Member

There we find hidden attributes. Let’s display some of them!

Get-CimInstance Win32_UserAccount | Select-Object Name,SID,PasswordChangeable,PasswordExpires,PasswordRequired,Status

I am now anticipating something that will be the subject of the next part. What if we want to display the properties of one user. How to achieve this? For this, we can use Where-Object. Let’s assume we want to list all user names that contain the value “schwarzen” in the name.

Here we go:

Get-CimInstance Win32_UserAccount | Where-Object Name -like '*schwarzen*' | Select-Object Name,SID,PasswordChangeable,PasswordExpires,PasswordRequired,Status

Unbenannt.JPG

Ok, filtering and Where-Object will be the topic of the next post. Let’s move to the next useful instance.

Win32_PhysicalMemory

Do you know the Everest tool? It’s a hardware inventory tool. From now on we don’t need this 3rd party tool anymore. 😉 If you want to find out your type of memory (for example if you have to replace your memory) run

Get-WmiObject win32_physicalmemory | Format-Table Manufacturer,Banklabel,Configuredclockspeed,Devicelocator,Capacity,Serialnumber -autosize

Unbenannt.PNG

Why Format-Table and not Select-Object? I wanted a sweeter view in table format.

Win32_ComputerSystem

Don’t forget to run Get-Member for discovering all the properties you see in the example below.

Get-CimInstance Win32_ComputerSystem | Select-Object Name,Manufacturer,ThermalState,KeyboardPasswordStatus,NumberOfProcessors

WMI Remoting (Side Note for Active Directory Administrators)

Before we come to the end of this article one more piece of information for Active Directory Systems Engineers. If you are working in an Active Directory environment, then you are able to execute remote WMI queries.

For example, you would like to find out which software is installed on computer dc01 run Get-CimInstance or Get-WmiObject and use the ComputerName parameter.

Get-CimInstance win32_product -ComputerName dc01 | Select-Object Name,InstallDate

2.JPG

Exercise

Here’s the exercise to the next part.

Retrieve information about your hard disk. Use Get-WmiObject or Get-CimInstance. First, search for the WMI Object and once you’ve found it show the Name, the Partitions, the Model,  the Firmware and the Serial Number.

See you next time with the topic: Powershell for Beginners (Part 10): Filtering and Where-Object.

Patrick Gruenauer, MVP Powershell

  • 04.10.2021
  • 4 633
  • 0
  • 6
  • 6
  • 0

Windows PowerShell

  • Содержание статьи
    • Вступление
    • Что такое Powershell?
    • Знакомство с PowerShell
    • Параметры
    • Конвейер
    • Получение сведений об объектах
    • Безопасность
    • Псевдонимы
    • Диски PowerShell
    • Профили PowerShell
    • Работа с объектами WMI
    • Заключение
    • Добавить комментарий

Вступление

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

Наиболее распространенным средством «экономии времени и избавления от головной боли» стала запись и последовательное пакетное исполнение необходимых операций — исполнение сценариев или скриптов в интерпретаторе команд операционной системы.

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

В составе MS-DOS и Windows 9x таким интерпретатором, позволяющим выполнять обработку пакетных файлов (bat-файлов), являлся command.com, впоследствии (начиная с выхода Windows NT) замененный cmd.exe. Позднее появился Windows Script Host.

Тем не менее, процесс написания и выполнения сценариев в ОС Windows не развит так хорошо, как, например, в UNIX-системах. Одна из причин этого – сам графический интерфейс ОС Windows, видимо и сделавший ее столь популярной среди обычных, не корпоративных пользователей. Возможность управления некоторыми элементами среды Windows с помощью графического интерфейса не всегда можно реализовать с помощью системных утилит, выполняемых в командной строке. С другой стороны, возможности каких-то системных программ, поставляемых в составе Windows, не всегда представлены в GUI. К тому же интерпретаторы в Windows имеют довольно ограниченный набор команд, «зашитых» в саму оболочку. Windows Script Host не интегрирован с командной строкой и сам по себе представляет потенциальную опасность – его использует достаточно большое количество вредоносных программ.

Попытки улучшить состояние дел в области управления и администрирования Windows с помощью командного интерфейса привели не к адаптации чужеродного для системы языка сценариев или созданию супер-утилиты, работающей в DOS, а к появлению Windows PowerShell – новой командной оболочки. По некоторым данным, ее появление связано с использованием платформы .NET при создании командного интерфейса для WMI. В данный момент PowerShell является отдельным приложением, который можно установить на любую систему, использующую платформу .Net 2.0 (Windows XP, Vista, Server 2003). Начиная с Server 2008, PowerShell будет являться встроенным компонентом Windows-систем. Если же у вас не Server 2008, для знакомства с PowerShell предварительно необходимо будет его загрузить (возможно, вам понадобится и установка .NET).

Что такое Powershell?

PowerShell — расширяемое средство автоматизации от Microsoft с открытым исходным кодом, состоящее из оболочки с интерфейсом командной строки и сопутствующего языка сценариев

Знакомство с PowerShell

Запустив PowerShell, вы не обнаружите поначалу никаких различий между ним и cmd.exe (разве что цвет фона окна у PowerShell по умолчанию — синий). Более того, вскоре вы обнаружите, что операции копирования/вставки в PowerShell реализованы также безобразно, как и в cmd.exe. Но первое впечатление о схожести этих оболочек, скажем так, не совсем соответствует действительности.

То обстоятельство, что работа оболочки PowerShell основана на .NET Framework, является главным ее отличием от предыдущих командных оболочек Windows. PowerShell полностью объектно-ориентирована. Результатом выполнения команды в PowerShell является не некий «текст сам по себе», а объект платформы .NET. Этот объект представляет собой собственно данные и имеет набор присущих ему свойств и методов.

Внутренние команды (точнее, командные структуры) для работы с объектами в PowerShell называются командлетами. Для них придумано специальное единообразное именование в виде комбинации действие-цель. Например, для получения данных используется действие “set”, для получения – “get”, для вывода — “out” и т. д. Цель – это тип объекта, к которому будет применено действие. Командлеты можно рассматривать как мини-программы, исполняемые в среде PowerShell. Для повышения функциональности можно создавать собственные командлеты или устанавливать командлеты сторонних разработчиков. Кроме командлетов, PowerShell позволяет выполнять функции, внешние сценарии (хранятся в файлах с расширением ps1) и внешние исполняемые файлы.

В состав PowerShell включена довольно обширная справочная система. Для начала работы с ней можно выполнить команду Get-Help.

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

Параметры

Строго говоря, следуя духу единообразного именования в PowerShell, все передаваемые командлету имена параметров должны следовать за символом «-». Однако для простоты написания названия некоторых параметров можно опускать. Например, для вызова справки по командлету Get-Content вместо полного указания

Get-Help –name Get-Content

можно ввести команду

Get-Help Get-Content

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

Get-Help Get-Content –Detailed

Конвейер

В PowerShell реализован механизм передачи данных от одного процесса другому или вывод их в файл. Поскольку, как отмечалось выше, PowerShell оперирует не текстом, а объектами, при перенаправлении элементом обмена информации является объект, вместе со своей структурой. Такая возможность позволяет оперировать с объектами — отбирать их по заданному фильтру, сортировать, группировать их и т. д. Для организации такого конвейера (в документации на английском языке используется термин pipeline — трубопровод или канал) в тексте сценария используется знак вертикальной черты. При обнаружении такого знака интерпретатор передает объекты от одного командлета другому в качестве входных параметров.

В качестве примера конвейера и возможности получать доступ к свойствам передаваемых по нему объектов, приведем следующую ситуацию. Для проверки, не выполняются ли на компьютере некие подозрительные программы, мы хотим получить список всех запущенных процессов, получить пути и названия файлов, их запускающих, а также посмотреть дату создания таких файлов. В дополнение, отсортируем такой список по дате создания в убывающем порядке и отберем 10 наиболее «свежих» из них. Добавим к выводной информации также время последней модификации файла. Процессы с именами «System» и «Idle» из рассмотрения исключим, так как они не содержат пути к файлам.

Как говорится, хорошо сформулированный вопрос — уже половина решения. Взгляните:

Get-Process | 
where-Object {"System", "Idle" -notContains $_.Name} | 
Get-Item | Sort CreationTime -desc | 
Select Directory, Name, CreationTime, LastWriteTime -first 10

Вводя код, вы всегда можете разбить строку, поставив в месте переноса знак «`» после пробела. Можно даже просто нажать клавишу Enter, не закончив строки. В этом случае PowerShell изменит приглашение на >>, давая пользователю понять, что интерпретатор считает код не завершенным и ожидает окончания его ввода.
Как и множество других скриптовых языков, PowerShell позволяет использовать переменные. Обозначением переменной служит знак «$». В случае передачи объекта по конвейеру, переменная $_ указывает на сам передаваемый объект.

Рассмотрим действия кода «по шагам». Сначала мы получаем список процессов с помощью командлета Get-Process. Эти данные передаются по конвейеру далее и фильтруются по условиям, заданным в where-Object (мы откидываем процессы с именами «System» и «Idle»).

Следующий элемент конвейера — Get-Item возвращает атрибуты отобранных объектов. Осталось их отсортировать (время создания в убывающем порядке) и выбрать интересующие нас значения (имена папки и исполняемого файла, время создания и последней модификации файла). Последний параметр, -first 10 указывает, что выводиться будут лишь первые 10 элементов из списка объектов. Попробуем выполнить:

Замечательно, то что надо. Однако при попытке выполнить тот же код в среде Windows XP или Server 2003 обнаружилось, что там это выглядит не столь гладко:

При просмотре результатов выполнения

Get-Process | Select Path

выяснилось, что пути двух процессов — winlogon и csrss — в Windows XP и Server 2003 PowerShell интерпретирует как ??C:WINDOWSsystem32. За разъяснением такого поведения я обратился к Василию Гусеву, специалисту по PowerShell. Он пояснил, что эти процессы не используют Win32API, и столь разная реакция на них в XP/Vista со стороны .NET, вероятно, вызвана различием платформ этих операционных систем.

Решив, что использовать механизмы обработки ошибок (в части обхода «непонятного» пути с подавлением вывода сообщения об ошибке) или исключения из списка процессов winlogon и csrss в данном случае не годится (возможно, они инфицированы, а дату их модификации в результатах мы уже не увидим), команды были изменены следующим образом:

Get-Process | 
ForEach-Object {
  if ($_.Path -ne $NULL )
  {
    Get-Item ($_.Path -replace "\??\", "")
  }
} | Sort CreationTime -desc | Select FullName, Name, CreationTime, LastWriteTime -first 10

А читатель может получить некоторое представление об использовании в PowerShell условий и регулярных выражений. Небольшие пояснения к коду. На втором этапе конвейера применен командлет ForEach-Object, позволяющий выполнить заданную операцию для каждого объекта из набора, передаваемого на его вход. Как указывалось выше, текущий объект, над которым выполняется операция, представлен переменной $_. В качестве заданной операции здесь выступает условие вида if (условие){исполняемый код, если условие истинно}. Так же, как и в cmd.exe, для операторов сравнения используются не символы вида < или >, а аббревиатуры — в данном случае это «не равно»(not equal): -ne. Итак, если путь процесса содержит какое-либо значение (в случае с «System» и «Idle» путь просто отсутствует), с помощью функции replace все символы «??» в пути будут удалены (пожалуй, более детально затрагивать вопрос регулярных выражений мы пока не будем), а командлет Get-Item предоставит доступ к свойствам текущего процесса. Ну а далее — все, как и в первом примере. Результат выполнения теперь одинаков:

Получение сведений об объектах

Возможно, у читателя уже возник вопрос — а как, вообще говоря, можно узнать, какую информацию можно получить в результате выполнения той или иной команды? Какие действия можно произвести с полученными данными? Например, в вышеописанном случае, откуда можно было узнать, что мы сможем получить дату создания файла? Одним из простых способов анализа объекта, возвращаемого командой, является передача этого объекта на вход командлета Get-Member. Этот командлет выводит сведения о типе объекта и всех его элементов. Как правило, объекты имеют большое количество разнообразных свойств и результатом работы Get-Member может стать весьма объемный текст, который не очень удобно просматривать. В этом случае можно либо разделять информацию на части, либо ее отфильтровывать. Пример получения информации об объекте, возвращаемом командлетом Get-Process, просмотр которой можно осуществлять постранично:

Get-Process | Get-Member | Out-Host -Paging

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

Get-Process | Get-Member -MemberType Properties

выведет лишь свойства объекта, а

Get-Process | Get-Member -MemberType Methods

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

Безопасность

Как уже отмечалось, использование сценариев VBScript/JScript представляет потенциальную опасность для системы — для их исполнения достаточно щелкнуть по значку мышью. Опасность еще более возрастает, если пользователь вошел под учетной записью, входящей в группу администраторов. В PowerShell скрипт с расширением ps1 невозможно запустить на исполнение с помощью мыши — в системе такой файл будет открыт не в командной оболочке, а в Блокноте. Для запуска сценария необходимо запустить саму оболочку PowerShell, ввести имя файла и нажать клавишу Enter.

В новой оболочке так же невозможна подмена команд. Суть этого приема, применяемого злоумышленниками, заключается в следующем. Обычно у пользователя, не имеющего прав администратора, есть некоторые папки с разрешениями на запись и выполнение файлов. Характерный пример — папка C:Documents and Settingsимя_пользователя. Вредоносная программа создает в такой папке исполняемый файл с именем, совпадающим с именем команды оболочки или именем исполняемой системной программы. К примеру, я создал в «своей» папке документов ipconfig.vbs, выводящий простое сообщение. Теперь, если, запустив cmd.exe, и находясь в своей папке, я попытаюсь выполнить команду Windows ipconfig, то получу вот такой результат:

Для полноты иллюстрации можно поместить в папку с документами и исполняемый файл, переименованный в нашем случае в ipconfig.exe. Тогда даже при вызове с указанием расширения будет запускаться файл из текущей папки, а не из system32. С PowerShell такой фокус не пройдет — для вызова скрипта, путь к которому не совпадает с путями, заданными в системной переменной %Path, необходимо явно указать его расположение. Даже в том случае, когда скрипт расположен в папке, являющейся для оболочки текущей, необходимо указать путь в таком виде: .имя_файла. Точка с обратным слешем указывают интерпретатору на текущую папку.

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

  • Restricted — настройка по умолчанию, запуск любых сценариев запрещен
  • AllSigned — разрешен запуск сценариев, имеющих цифровую подпись надежного издателя; сценарии, созданные пользователем, также должны быть заверены центром сертификации
  • RemoteSigned — разрешен запуск сценариев, если они не являются доверенными, но созданы локальным пользователем; сценарии, загруженные из Интернета, не имеющие подписи, не исполняются
  • Unrestricted — разрешен запуск любых сценариев

Текущий режим политики можно узнать, выполнив команду Get-ExecutionPolicy в оболочке. Для изменения режима выполните команду Set-ExecutionPolicy с необходимым названием политики в качестве параметра.

Также к инструментам, помогающим повысить безопасность при работе с PowerShell, я бы отнес параметры команд из разряда «а что будет, если…». Их два — whatif и confirm. Первый позволяет определить, какое действие и с каким объектом будет произведено, однако само действие реализовано не будет. Что-то вроде моделирования. Второй перед выполнением действия будет запрашивать подтверждения пользователя, и в случае утвердительного ответа — запускать необходимую команду фактически. То есть, такой вид подстраховки.

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

Get-Process | Stop-Process

то через несколько секунд его будет ждать синий экран со STOP-ом. PowerShell, как и следует из текста команды, последовательно начнет «прибивать» все запущенные в системе процессы, что и приведет к ее критическому останову. Если же запустить:

Get-Process | Stop-Process -whatif

ничего страшного не произойдет — просто PowerShell покажет, что бы он сделал, если бы команда выполнялась без ключа -whatif:

Псевдонимы

Оболочка имеет встроенный механизм псевдонимов команд. С одной стороны, псевдонимы используются для упрощения ввода команд. Как правило, в этом случае в качестве псевдонима используется сокращенное наименование командлета (например, gc для Get-Content или fl для Format-List). С другой стороны, этот механизм обеспечивает совместимость интерфейсов различных командных интерпретаторов. К примеру, имея опыт работы с cmd.exe, вы привыкли выводить содержимое папки с помощью команды dir. Выполнение этой команды в PowerShell приведет к тому же результату, хотя на самом деле оболочка вместо псевдонима dir будет выполнять командлет Get-ChildItem. Список всех доступных псевдонимов можно получить с помощью команды Get-Alias. Пользователь может создавать собственные псевдонимы, используя команду Set-Alias.

Диски PowerShell

Так же, как Windows оперирует с данными, используя файловую систему, оболочка PowerShell работает с хранилищами данных, представленных в виде дисков. Физические диски системы являются не единственным встроенным в оболочку видом хранилищ, с которыми обеспечивается взаимодействие. Пользователь может работать с реестром, встроенными переменными и переменными среды, хранилищами сертификатов точно так же, как и с обычными дисками, папками и файлами. Реализация такого взаимодействия и обеспечение абстракций, позволяющих пользователю применять одинаковые команды и методы к различным хранилищам данных, выполняется провайдерами — программами .NET.

Список провайдеров, доступных в данный момент оболочке, можно получить командой Get-PSProvider. Изначально в PowerShell присутствуют следующие «диски» — псевдонимы (Alias), переменные среды (Env), физические диски системы (C, D, и т. д.), функции, системный реестр, внутренние переменные (Variable) и хранилище сертификатов.

Вот пример чтения содержимого ветки реестра HKLMSoftwareMicrosoft

Как видно, использованы те же команды, что для получения сведений о файловой системе. Но структура получаемых данных, естественно, различна. Кроме названия и свойств для каждого элемента выводится номер подраздела (SKC) и номер записи (VC). С помощью PowerShell пользователь может просматривать сведения о реестре, добавлять, удалять и модифицировать ключи. Позволю привести себе что-то вроде шпаргалки по работе с элементами реестра:

И код для примера выполнения различных манипуляций с ключами реестра и их параметрами:

# Создаем новый подраздел с именем valks в ветке HKEY_CURRENT_USERSoftware
New-Item -path HKCU:Softwarevalks
# Добавляем в созданный раздел новый строковый параметр с именем Param1 и значением StringValue
New-ItemProperty -path HKCU:Softwarevalks -name Param1 -propertyType String -value StringValue
# Создадим подраздел SubFolder
New-Item -path HKCU:SoftwarevalksSubFolder
# Добавляем еще один параметр - Param2 типа DWord и значением 12
New-ItemProperty -path HKCU:Softwarevalks -name Param2 -propertyType DWord -value 12
# Получаем список всех параметров
Get-ItemProperty HKCU:Softwarevalks
# Получаем значение параметра Param2
Get-ItemProperty HKCU:Softwarevalks | Format-list Param2
# Или можем считать раздел в переменную $key
$key = Get-ItemProperty HKCU:Softwarevalks
# И вывести значение нужного параметра
Write-Host "Значение параметра Param2: " $key.Param2
# Изменим значение параметра Param2 на 193
Set-ItemProperty HKCU:Softwarevalks -name Param2 -value 193
# Изменим название параметра Param1 на Параметр1
Rename-ItemProperty -path HKCU:Softwarevalks -name Param1 -newname Параметр1
# Удаляем Параметр1
Remove-ItemProperty HKCU:Softwarevalks -name Параметр1
# Удаляем весь подраздел valks
Remove-Item HKCU:Softwarevalks

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

function GetAutoexec ($hives) {
  # Если функции не передается входной массив ключей реестра,
  # используем этот:
  $hives = "HKCU:SoftwareMicrosoftWindowsCurrentVersionRun", `
  "HKLM:SOFTWAREMicrosoftWindowsCurrentVersionRun", `
  "HKLM:SOFTWAREMicrosoftWindowsCurrentVersionpoliciesExplorerRun"
  # Выодим заголовок и переносим строку
  Write-Host "Список автозагрузки`n"
  # Начинаем перебирать элементы массива - ветви реестра
  Foreach ($hive in $hives){
    # Выводим название ветви зеленым цветом
    Write-Host "Ветвь $hive" -ForegroundColor Green
    # Проверяем, существует ли ветвь в реестре
    if (Test-Path $hive){
      # Получаем очередной ключ реестра
      [Microsoft.Win32.RegistryKey]$param = Get-Item $hive
      # для каждого ключа...
      foreach ($p in $param){
        # ...получаем список его параметров
        foreach ($key in $p.getvalueNames()){
          # выводим название параметра и его значение
          "Загрузка $key из " + $p.GetValue($key)
        }
      }
    }
    # переносим строку
    Write-Host "`n"
  }
}
# осуществляем вызов самой функции
GetAutoexec

Пользователь может создавать собственные диски, используя существующие провайдеры. Вот пример создания диска PowerShell с именем Win, содержимое которого будет являться корневой папкой C:Windows:

New-PSDrive -Name Win –PSProvider FileSystem -Root "C:Windows"

После создания диска PowerShell к нему можно обращаться точно так же , как к обычному диску системы.

Однако необходимо знать, что по завершении сеанса работы с PowerShell он будет автоматически удален. Так же, как и псевдонимы, функции и переменные, созданные пользователем в течение сеанса. Для того, чтобы сохранить перечисленные изменения, необходимо создать профиль PowerShell.

Профили PowerShell

Профиль — это файл с расширением ps1. Фактически, это тот же скрипт, выполняемый оболочкой при ее запуске. Профили в оболочке не создаются автоматически — они должны быть созданы пользователем самостоятельно. Созданные профили будут загружаться при каждом запуске PowerShell, если политикой выполнения разрешено загружать конфигурационные файлы. Возможна обработка до четырех различных профилей. Расположение файлов в порядке последовательности их загрузки:

  • %windir%system32WindowsPowerShellv1.0profile.ps1 — профиль, применяемый ко всем пользователям и оболочкам
  • %windir%system32WindowsPowerShellv1.0 Microsoft.PowerShell_profile.ps1 — профиль, применяемый ко всем пользователям только оболочки PowerShell
  • %UserProfile%My DocumentsWindowsPowerShellprofile.ps1 — применяется для текущего пользователя во всех оболочках
  • %UserProfile%My DocumentsWindowsPowerShellMicrosoft.PowerShell_profile.ps1 — применяется для текущего пользователя только в оболочке PowerShell

Под различными оболочками здесь нужно учитывать то обстоятельство, что PowerShell может оказаться не единственным приложением, использующим файлы профилей ps1. Некоторые интегрированные среды разработки (IDE) также могут использовать их. Один из характерных примеров — инструмент PowerGUI, разработанный Quest Software, предоставляющий средства графического интерфейса для работы с PowerShell.

Путь к профилю текущего пользователя только оболочки PowerShell хранится во встроенной переменной $profile. Для его создания выполните команду:

New-Item -Path $profile -ItemType file -force

После создания его можно открыть любым текстовым редактором, например Блокнотом:

notepad $profile

и сделать в нем необходимые изменения. Не забудьте проверить, разрешен ли политикой выполнения запуск скриптов.

Работа с объектами WMI

WMI (Windows Management Interface, интерфейс управления Windows) — набор интерфейсов для управления ОС Windows с помощью специальных компонентов. Возможно управление локальным компьютером, и находящимся в сети. WMI — разновидность Web-Based Enterprise Management (WBEM) и Common Information Model (CIM), разработанная Microsoft. Входит в состав Windows Vista, Windows Server 2003, Windows XP, Windows Me и Windows 2000. Для Windows 95 и Windows 98 доступна в виде отдельно устанавливаемого компонента. Поддерживает использование скриптовых языков, таких как VBScript или Windows PowerShell для управления персональными компьютерами и серверами, работающими под управлением Microsoft Windows.

Объекты WMI являются для PowerShell вполне «родными». Достаточно выполнить команду:

Get-WmiObject -List

чтобы увидеть большое количество классов, обеспечивающих доступ к объектам WMI в оболочке. В случае подключения к WMI на удаленном компьютере, состав классов будет зависеть от ОС и установленных на нем расширений WMI. Для получения сведений о доступных классах на удаленной машине, необходимо указать его IP-адрес или имя в качестве параметра:

Get-WmiObject -List -ComputerName Server

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

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

PS C:Documents and SettingsАдминистратор> Get-WmiObject -Class Win32_OperatingSystem
SystemDirectory : C:WINDOWSsystem32
Organization    : Nrest
BuildNumber     : 3790
RegisteredUser  : Сергей
SerialNumber    : 69889-650-3137304-45684
Version         : 5.2.3790
     
PS C:Documents and SettingsАдминистратор> Get-WmiObject -Class Win32_OperatingSystem | 
Format-List Locale, Version, CurrentTimeZone, OSLanguage, InstallDate
     
Locale          : 0419
Version         : 5.2.3790
CurrentTimeZone : 180
OSLanguage      : 1049
InstallDate     : 20081022233211.000000+240

А вот небольшой пример опроса всех компьютеров в локальной сети с адресом 192.168.1.0 и маской подсети 255.255.255.0:

1..254| 
ForEach-Object -Process 
  {
    Get-WmiObject -Class Win32_PingStatus 
    -Filter ("Address='192.168.1." + $_ + "'")
    -ComputerName .
  } |
Select-Object -Property Address,ResponseTime,StatusCode

В первом элементе конвейера генерируется массив чисел от 1 до 254. На втором этапе каждое число из массива подставляется в IP-адрес, который будет пинговаться при помощи средств WMI. Результаты будут выводиться в таблицу с тремя столбцами — адрес хоста, время отклика и статус ответа. В случае ответа хоста возвращается статус с кодом «0».

Заключение

Конечно, в одной статье невозможно описать все возможности PowerShell. К тому же Microsoft продолжает работу над его улучшением — вторая версия должна поддерживать управление удаленными компьютерами непосредственно самой оболочкой. Ожидаются и другие нововведения. Учитывая, что PowerShell будет являться компонентом новых ОС, не приходится сомневаться в том, что сфера его применения в продуктах Microsoft будет только расширяться.

Автор выражает признательность Василию Гусеву за помощь, оказанную при подготовке статьи

Понравилась статья? Поделить с друзьями:
  • Запуск windows powershell с помощью wmi kaspersky
  • Запуск windows media player с параметрами
  • Запуск windows media player в полноэкранном режиме автоматически
  • Запуск windows installer в безопасном режиме windows 10
  • Запуск windows defender через командную строку