Поделиться через


Глава 7. Работа с WMI

WMI и CIM

Windows PowerShell поставляется по умолчанию с командлетами для работы с другими технологиями, такими как инструментарий управления Windows (WMI). Командлеты WMI устарели и недоступны в PowerShell 6+, но рассматриваются здесь, так как они могут возникнуть в старых сценариях, работающих в Windows PowerShell. Для новой разработки используйте вместо этого командлеты CIM.

Несколько собственных командлетов WMI существуют в PowerShell без необходимости устанавливать любое другое программное обеспечение или модули. Get-Command можно использовать для определения того, какие командлеты WMI существуют в Windows PowerShell. Ниже приведены результаты из системы Windows 11 под управлением PowerShell версии 5.1. Результаты могут отличаться в зависимости от используемой версии PowerShell.

Get-Command -Noun WMI*
CommandType     Name                                               Version
-----------     ----                                               -------
Cmdlet          Get-WmiObject                                      3.1.0.0
Cmdlet          Invoke-WmiMethod                                   3.1.0.0
Cmdlet          Register-WmiEvent                                  3.1.0.0
Cmdlet          Remove-WmiObject                                   3.1.0.0
Cmdlet          Set-WmiInstance                                    3.1.0.0

Командлеты Common Information Model (CIM) появились в PowerShell 3.0 и группируются в выделенном модуле. Чтобы вывести список всех доступных командлетов CIM, используйте Get-Command командлет с параметром module , как показано в следующем примере.

Get-Command -Module CimCmdlets
CommandType     Name                                               Version
-----------     ----                                               -------
Cmdlet          Export-BinaryMiLog                                 1.0.0.0
Cmdlet          Get-CimAssociatedInstance                          1.0.0.0
Cmdlet          Get-CimClass                                       1.0.0.0
Cmdlet          Get-CimInstance                                    1.0.0.0
Cmdlet          Get-CimSession                                     1.0.0.0
Cmdlet          Import-BinaryMiLog                                 1.0.0.0
Cmdlet          Invoke-CimMethod                                   1.0.0.0
Cmdlet          New-CimInstance                                    1.0.0.0
Cmdlet          New-CimSession                                     1.0.0.0
Cmdlet          New-CimSessionOption                               1.0.0.0
Cmdlet          Register-CimIndicationEvent                        1.0.0.0
Cmdlet          Remove-CimInstance                                 1.0.0.0
Cmdlet          Remove-CimSession                                  1.0.0.0
Cmdlet          Set-CimInstance                                    1.0.0.0

Командлеты CIM по-прежнему обеспечивают взаимодействие с WMI, поэтому не удивляйтесь, если кто-то скажет: "Когда я запрашиваю WMI с помощью командлетов CIM PowerShell".

Как упоминалось ранее, WMI является отдельной технологией от PowerShell, и вы просто используете командлеты CIM для доступа к WMI. Вы можете найти старый VBScript, использующий язык запросов WMI (WQL) для запроса WMI, например в следующем примере.

strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
    & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\CIMV2")

Set colBIOS = objWMIService.ExecQuery _
    ("Select * from Win32_BIOS")

For each objBIOS in colBIOS
    Wscript.Echo "Manufacturer: " & objBIOS.Manufacturer
    Wscript.Echo "Name: " & objBIOS.Name
    Wscript.Echo "Serial Number: " & objBIOS.SerialNumber
    Wscript.Echo "SMBIOS Version: " & objBIOS.SMBIOSBIOSVersion
    Wscript.Echo "Version: " & objBIOS.Version
Next

Запрос WQL можно взять из VBScript и использовать его с командлетом Get-CimInstance без каких-либо изменений.

Get-CimInstance -Query 'Select * from Win32_BIOS'
SMBIOSBIOSVersion : 090006
Manufacturer      : American Megatrends Inc.
Name              : Intel(R) Xeon(R) CPU E3-1505M v5 @ 2.80GHz
SerialNumber      : 3810-1995-1654-4615-2295-2755-89
Version           : VRTUAL - 4001628

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

Get-CimInstance -ClassName Win32_BIOS
SMBIOSBIOSVersion : 090006
Manufacturer      : American Megatrends Inc.
Name              : Intel(R) Xeon(R) CPU E3-1505M v5 @ 2.80GHz
SerialNumber      : 3810-1995-1654-4615-2295-2755-89
Version           : VRTUAL - 4001628

Если требуется только серийный номер, передайте выходные данные Select-Object и укажите только свойство SerialNumber .

Get-CimInstance -ClassName Win32_BIOS |
    Select-Object -Property SerialNumber
SerialNumber
------------
3810-1995-1654-4615-2295-2755-89

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

Get-CimInstance -ClassName Win32_BIOS -Property SerialNumber |
    Select-Object -Property SerialNumber
SerialNumber
------------
3810-1995-1654-4615-2295-2755-89

Предыдущие результаты вернули объект. Чтобы вернуть строку, используйте параметр ExpandProperty .

Get-CimInstance -ClassName Win32_BIOS -Property SerialNumber |
    Select-Object -ExpandProperty SerialNumber
3810-1995-1654-4615-2295-2755-89

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

(Get-CimInstance -ClassName Win32_BIOS -Property SerialNumber).SerialNumber
3810-1995-1654-4615-2295-2755-89

Запрос удаленных компьютеров с помощью командлетов CIM

Вы по-прежнему должны запускать PowerShell в качестве локального администратора и пользователя домена. При попытке запросить данные с удаленного компьютера с помощью командлета Get-CimInstance вы получите сообщение об ошибке отказано в доступе.

Get-CimInstance -ComputerName dc01 -ClassName Win32_BIOS
Get-CimInstance : Access is denied.
At line:1 char:1
+ Get-CimInstance -ComputerName dc01 -ClassName Win32_BIOS
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : PermissionDenied: (root\cimv2:Win32_BIOS:Stri
   ng) [Get-CimInstance], CimException
    + FullyQualifiedErrorId : HRESULT 0x80070005,Microsoft.Management.Infra
   structure.CimCmdlets.GetCimInstanceCommand
    + PSComputerName        : dc01

Многие люди имеют проблемы безопасности в отношении PowerShell, но у вас есть те же разрешения в PowerShell, что и в графическом интерфейсе. И никак иначе. Проблема в предыдущем примере заключается в том, что у пользователя, на котором запущена PowerShell, нет прав на запрос сведений WMI с сервера DC01. Вы могли бы повторно запустить PowerShell в качестве администратора домена, поскольку Get-CimInstance не имеет параметра Credential. Но это не рекомендуется, так как все, что вы запускаете из PowerShell, будет выполняться в качестве администратора домена. В зависимости от ситуации этот сценарий может быть опасным с точки зрения безопасности.

Используя принцип наименьших привилегий, повышайте привилегии до учетной записи администратора домена на командной основе, используя параметр Credential, если у команды он есть. Get-CimInstance Не имеет параметра Credential , поэтому решение в этом сценарии — сначала создать CimSession . Затем используйте CimSession вместо имени компьютера для запроса WMI на удаленном компьютере.

$CimSession = New-CimSession -ComputerName dc01 -Credential (Get-Credential)
cmdlet Get-Credential at command pipeline position 1
Supply values for the following parameters:
Credential

Сеанс CIM был сохранен в переменной с именем $CimSession. Обратите внимание, что командлет также указан Get-Credential в скобках, чтобы он выполнялся сначала, запрашивая альтернативные учетные данные перед созданием нового сеанса. Я показываю вам еще один более эффективный способ указать альтернативные учетные данные позже в этой главе, но важно понимать эту базовую концепцию, прежде чем сделать ее более сложной.

Теперь вы можете использовать сеанс CIM, созданный в предыдущем примере, с Get-CimInstance командлетом для запроса данных BIOS из WMI на удаленном компьютере.

Get-CimInstance -CimSession $CimSession -ClassName Win32_BIOS
SMBIOSBIOSVersion : 090006
Manufacturer      : American Megatrends Inc.
Name              : Intel(R) Xeon(R) CPU E3-1505M v5 @ 2.80GHz
SerialNumber      : 0986-6980-3916-0512-6608-8243-13
Version           : VRTUAL - 4001628
PSComputerName    : dc01

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

Командлет Get-CimInstance использует протокол WSMan по умолчанию, что означает, что для подключения к удаленному компьютеру требуется PowerShell версии 3.0 или более поздней. На самом деле это не версия PowerShell, которая имеет значение, это версия стека. Версию стека можно определить с помощью командлета Test-WSMan . Она должна быть версии 3.0, которую вы найдете с PowerShell версии 3.0 и более поздней.

Test-WSMan -ComputerName dc01
wsmid           : http://schemas.dmtf.org/wbem/wsman/identity/1/wsmanidentit
                  y.xsd
ProtocolVersion : http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd
ProductVendor   : Microsoft Corporation
ProductVersion  : OS: 0.0.0 SP: 0.0 Stack: 3.0

Командлеты WMI старых версий используют протокол DCOM, который совместим с более старыми версиями Windows. Однако брандмауэр обычно блокирует DCOM в более новых версиях Windows. Командлет New-CimSessionOption позволяет создать подключения по протоколу DCOM для использования с New-CimSession. Этот параметр позволяет Get-CimInstance командлету взаимодействовать с версиями Windows как старыми, как Windows Server 2000. Эта возможность также означает, что PowerShell не требуется на удаленном компьютере при использовании командлета с CimSession, настроенного для использования Get-CimInstance протокола DCOM.

Создайте параметр протокола DCOM с помощью командлета New-CimSessionOption и сохраните его в переменной.

$DCOM = New-CimSessionOption -Protocol Dcom

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

$Cred = Get-Credential
cmdlet Get-Credential at command pipeline position 1
Supply values for the following parameters:
Credential

У меня есть сервер с именем SQL03 под управлением Windows Server 2008 (не R2). Это новейшая операционная система Windows Server, которая по умолчанию не установлена PowerShell.

Создайте CimSession в SQL03 с помощью протокола DCOM.

$CimSession = New-CimSession -ComputerName sql03 -SessionOption $DCOM -Credential $Cred

Обратите внимание, что в предыдущей команде вы указываете переменную с именем $Cred в качестве значения для параметра Credential вместо повторного ввода учетных данных вручную.

Выходные данные запроса одинаковы независимо от базового протокола.

Get-CimInstance -CimSession $CimSession -ClassName Win32_BIOS
SMBIOSBIOSVersion : 090006
Manufacturer      : American Megatrends Inc.
Name              : Intel(R) Xeon(R) CPU E3-1505M v5 @ 2.80GHz
SerialNumber      : 7237-7483-8873-8926-7271-5004-86
Version           : VRTUAL - 4001628
PSComputerName    : sql03

Командлет Get-CimSession используется для просмотра подключений CimSessions и используемых протоколов.

Get-CimSession
Id           : 1
Name         : CimSession1
InstanceId   : 80742787-e38e-41b1-a7d7-fa1369cf1402
ComputerName : dc01
Protocol     : WSMAN

Id           : 2
Name         : CimSession2
InstanceId   : 8fcabd81-43cf-4682-bd53-ccce1e24aecb
ComputerName : sql03
Protocol     : DCOM

Извлеките и сохраните ранее созданные CimSessions в переменной с именем $CimSession.

$CimSession = Get-CimSession

Опросите оба компьютера с помощью одной команды: один через протокол WSMan, а другой через DCOM.

Get-CimInstance -CimSession $CimSession -ClassName Win32_BIOS
SMBIOSBIOSVersion : 090006
Manufacturer      : American Megatrends Inc.
Name              : Intel(R) Xeon(R) CPU E3-1505M v5 @ 2.80GHz
SerialNumber      : 0986-6980-3916-0512-6608-8243-13
Version           : VRTUAL - 4001628
PSComputerName    : dc01

SMBIOSBIOSVersion : 090006
Manufacturer      : American Megatrends Inc.
Name              : Intel(R) Xeon(R) CPU E3-1505M v5 @ 2.80GHz
SerialNumber      : 7237-7483-8873-8926-7271-5004-86
Version           : VRTUAL - 4001628
PSComputerName    : sql03

Одна из моих статей в блоге о командлетах WMI и CIM содержит функцию PowerShell, которая автоматически определяет, следует ли использовать WSMan или DCOM, и настраивает соответствующий сеанс CIM для вас. Дополнительные сведения см. в разделе "Функция PowerShell" для создания CimSessions на удаленных компьютерах с резервным подключением к Dcom.

Завершив работу с сеансами CIM, удалите их с помощью командлета Remove-CimSession . Чтобы удалить все сеансы CIM, направьте Get-CimSession в Remove-CimSession.

Get-CimSession | Remove-CimSession

Сводка

В этой главе вы узнали об использовании PowerShell для работы с WMI на локальных и удаленных компьютерах. Вы также узнали, как использовать командлеты CIM для работы с удаленными компьютерами, используя протоколы WSMan и DCOM.

Отзыв

  1. Какова разница в командлетах WMI и CIM?
  2. По умолчанию какой протокол Get-CimInstance используется командлетом?
  3. Каковы некоторые преимущества использования сеанса CIM вместо указания имени компьютера с Get-CimInstance?
  4. Как указать альтернативный протокол, отличный от используемого по умолчанию Get-CimInstance?
  5. Как закрыть или удалить сеансы CIM?

Ссылки