Системный администратор, привыкший десятилетиями получать серийный номер материнской платы одной строкой wmic bios get serialnumber, летом 2026 года обнаружил неприятный сюрприз: команда просто перестала существовать в системе. Это не сбой и не баг, а завершение долгого процесса вывода из эксплуатации утилиты командной строки WMIC, который Microsoft вела больше пяти лет. При этом сама технология опроса оборудования, стоящая за WMIC, никуда не делась, а лишь сменила интерфейс доступа: на смену текстовой обёртке пришли структурированные командлеты PowerShell, работающие поверх современной реализации стандарта CIM.

Что на самом деле стоит за аббревиатурами WMI и CIM

Путаница между терминами WMI и CIM возникает из за того, что многие годы они использовались почти как синонимы, хотя формально описывают разные вещи. Common Information Model (CIM) это открытый отраслевой стандарт, описывающий, как представлять управляемые объекты вроде процессора, диска или сетевого адаптера в виде единообразных классов с набором свойств и методов, независимо от конкретной операционной системы. Windows Management Instrumentation (WMI) это реализация этого стандарта конкретно компанией Microsoft для Windows: собственный набор поставщиков данных, пространств имён и служба, которая отвечает на запросы к этим классам. То есть WMI построена поверх CIM, а не является её противоположностью, и вопрос "WMI против CIM" на практике превращается в вопрос о том, каким именно интерфейсом пользоваться для обращения к одним и тем же данным, лежащим в основе обеих технологий.

Показательный пример этого родства: команда Get-WmiObject Win32_OperatingSystem и команда Get-CimInstance Win32_OperatingSystem, выполненные на локальном компьютере, возвращают практически идентичный набор свойств, включая директорию системы, номер сборки и версию операционной системы, с минимальными косметическими отличиями в оформлении вывода. Разница между ними проявляется не в том, какие данные доступны, а в том, как именно эти данные передаются по сети и насколько безопасен и производителен сам процесс запроса.

Командлеты WMI и их ограничения

Классические командлеты для работы с WMI в PowerShell, такие как Get-WmiObject, Invoke-WmiMethod, Register-WmiEvent, Remove-WmiObject и Set-WmiInstance, появились в самых ранних версиях PowerShell и десятилетиями оставались основным способом опроса оборудования из командной строки. Для удалённых запросов эти командлеты используют протокол DCOM (Distributed Component Object Model), который требует открытия широкого диапазона портов на межсетевом экране и считается уязвимым местом с точки зрения безопасности сетевого периметра. Настроить DCOM корректно и безопасно на практике заметно сложнее, чем современные альтернативы, а по умолчанию защита при таком подходе минимальна.

Ещё одно практическое ограничение WMI-командлетов: они физически отсутствуют в кроссплатформенной версии PowerShell, начиная с PowerShell 6 и далее, поскольку сама технология WMI жёстко привязана к платформе Windows, а современный PowerShell рассчитан на работу и в Linux, и в macOS. Скрипт, написанный с использованием Get-WmiObject, попросту завершится ошибкой "cmdlet not recognized" при попытке запустить его в PowerShell 7, и единственным выходом остаётся переписать вызовы под CIM-командлеты.

Командлеты CIM как современная замена

Начиная с PowerShell версии 3.0 Microsoft ввела отдельный набор командлетов, сгруппированных в собственном модуле и построенных вокруг стандарта CIM напрямую, а не через посредство классической WMI-инфраструры. Ключевые из них это Get-CimInstance, New-CimInstance, Set-CimInstance, Remove-CimInstance и Invoke-CimMethod, а также механизм CIM-сессий через New-CimSession, позволяющий один раз установить соединение с удалённым компьютером и затем выполнять через него множество последовательных запросов без повторного установления связи каждый раз заново.

Для удалённых запросов CIM-командлеты по умолчанию используют протокол WS-Management, известный также как WinRM, тот же самый протокол, что применяется для PowerShell Remoting. В отличие от DCOM, WinRM работает через единственный порт (5985 для обычного соединения или 5986 для защищённого через TLS), что значительно упрощает настройку межсетевого экрана и делает протокол стандартизированным, а не завязанным на специфику конкретной реализации Microsoft. Если удалённый компьютер по какой либо причине не поддерживает WinRM, например это устаревшая система без включённой службы удалённого управления, CIM-командлеты всё равно способны обратиться к ней через DCOM, но для этого нужно явно создать объект параметров сессии с протоколом DCOM:

$opt = New-CimSessionOption -Protocol Dcom
$session = New-CimSession -ComputerName OldServer -SessionOption $opt
Get-CimInstance -CimSession $session -ClassName Win32_BIOS

Официальная документация Microsoft прямо рекомендует использовать именно CIM-командлеты вместо устаревших WMI-командлетов во всех новых сценариях. Правило AvoidUsingWMICmdlet в анализаторе кода PSScriptAnalyzer помечает предупреждением любое использование Get-WmiObject, Remove-WmiObject, Invoke-WmiMethod, Register-WmiEvent и Set-WmiInstance, явно указывая на CIM-аналог для замены каждого из них.

Практические примеры запросов через Get-CimInstance

Синтаксис CIM-командлетов близок к привычному по WMI, но обладает более строгой и явной структурой параметров. Получить сведения о материнской плате и её серийном номере позволяет команда:

Get-CimInstance -ClassName Win32_BIOS | Select-Object SerialNumber, Manufacturer

Информация о процессоре, включая количество ядер и текущую тактовую частоту, извлекается запросом к соответствующему классу:

Get-CimInstance -ClassName Win32_Processor | Select-Object Name, NumberOfCores, MaxClockSpeed

Для фильтрации результатов на стороне сервера, а не после получения всего массива данных с последующей фильтрацией через Where-Object на клиенте, применяется параметр -Filter с синтаксисом языка запросов WQL:

Get-CimInstance -ClassName Win32_Service -Filter "State='Running' AND StartMode='Auto'"

Фильтрация именно на этом уровне заметно эффективнее при удалённых запросах, поскольку по сети передаётся уже отфильтрованный набор данных, а не полный список объектов с последующей обрезкой на локальной машине. Попытка передать в параметр -Filter блок сценария вместо строки WQL, по аналогии с привычным синтаксисом Where-Object, приведёт к ошибке или неожиданному поведению, поэтому это одна из самых частых ловушек при переходе с классического WQL-подхода на новый синтаксис.

Для получения данных с удалённого компьютера достаточно указать параметр -ComputerName напрямую:

Get-CimInstance -ClassName Win32_OperatingSystem -ComputerName server01

При выполнении множества последовательных запросов к одному и тому же удалённому узлу разумнее сначала создать CIM-сессию, а затем передавать её в каждый следующий вызов, поскольку установление соединения происходит только один раз, а не заново при каждом обращении:

$session = New-CimSession -ComputerName server01
Get-CimInstance -CimSession $session -ClassName Win32_BIOS
Get-CimInstance -CimSession $session -ClassName Win32_DiskDrive
Remove-CimSession -CimSession $session

Судьба утилиты wmic и что реально изменилось

Отдельного упоминания заслуживает командная утилита wmic.exe, которую многие годы использовали для быстрых однострочных запросов прямо из командной строки cmd без запуска PowerShell. Microsoft официально пометила WMIC как устаревшую начиная с версии Windows 10 21H1 и с аналогичной версии Windows Server, после чего утилита перестала активно развиваться, хотя формально ещё оставалась доступной. Далее утилита перестала присутствовать по умолчанию в новых установках Windows 11 25H2, но её ещё можно было временно вернуть через механизм добавляемых по требованию компонентов (Feature on Demand). Финальная точка была поставлена с выходом обновления Windows 11 в конце августа 2026 года: начиная с этого релиза WMIC больше не входит в состав системы и не может быть добавлена обратно даже через дополнительные компоненты, утилита удалена окончательно и бесповоротно.

Важно чётко разделять два факта, которые легко перепутать. Удаление коснулось исключительно текстовой оболочки wmic.exe как отдельной программы, тогда как сама технология Windows Management Instrumentation, её пространства имён, классы вроде Win32_OperatingSystem, Win32_BIOS и Win32_Process, а также лежащие в её основе службы остаются полностью работоспособной и поддерживаемой частью Windows. Причина отказа именно от текстовой утилиты в первую очередь связана с безопасностью: wmic.exe десятилетиями оставался одним из излюбленных инструментов вредоносного программного обеспечения и злоумышленников, использующих легитимные системные утилиты для скрытного выполнения команд по технике living-off-the-land, когда атака маскируется под обычную административную активность и не требует загрузки стороннего исполняемого файла.

Практическая рекомендация для тех, кто продолжает встречать команды вида wmic path win32_process get name в старых пакетных файлах, скриптах развёртывания или сторонних инструментах мониторинга, звучит однозначно: такие вызовы необходимо переписывать на Get-CimInstance, а не на устаревший Get-WmiObject, поскольку последний хотя формально ещё работает в Windows PowerShell версии 5.1, сам находится в статусе устаревшего и полностью отсутствует уже в PowerShell 6 и всех последующих версиях. Переписывание сразу под CIM-командлеты избавляет от необходимости проходить через промежуточный этап миграции дважды.

Насколько на самом деле различается синтаксис запросов

Распространено ошибочное мнение, что переход от Get-WmiObject к Get-CimInstance требует освоения принципиально другого языка запросов, но на практике разрыва здесь почти нет. У командлета Get-WmiObject уже давно есть точно такое же разделение параметров, что и у более нового аналога: класс задаётся через -Class, условие фильтрации через -Filter, а пространство имён через -Namespace, и единая текстовая строка через -Query была лишь одним из допустимых вариантов вызова, а не единственным способом. Microsoft намеренно сделала синтаксис обоих командлетов максимально похожим именно для того, чтобы миграция сводилась по сути к замене одного глагола в команде на другой без переписывания логики запроса.

Языком запросов по умолчанию для обоих подходов остаётся один и тот же WQL (WMI Query Language). У Get-CimInstance действительно есть параметр -QueryDialect, который в теории позволяет переключиться на альтернативный диалект CQL (CIM Query Language), являющийся частью более широкого стандарта CIM, но значением по умолчанию для этого параметра остаётся именно WQL, а не CQL. На практике подавляющее большинство скриптов, использующих параметр -Filter или -Query у Get-CimInstance, продолжают писать условия ровно в том же синтаксисе WQL, что применялся и в командах через Get-WmiObject, просто теперь этот же язык запросов работает поверх более современного и безопасного транспорта.

Реальная разница между двумя подходами лежит не в синтаксисе построения запроса, а глубже, в самой природе возвращаемых объектов. Get-WmiObject возвращает "живые" COM-объекты, у которых методы исходного класса можно вызывать напрямую через точечную нотацию прямо на полученном объекте. Get-CimInstance, напротив, возвращает "отсоединённые" объекты, представляющие собой снимок состояния на момент запроса без привязанных методов: чтобы вызвать метод соответствующего CIM-класса, требуется отдельный командлет Invoke-CimMethod, передающий обратно на сервер и целевой объект, и имя метода, и его аргументы. Именно эта архитектурная разница, а не мнимое различие языков запросов, чаще всего ломает старые скрипты при их прямолинейном переписывании под новые командлеты, если автор скрипта по привычке пытается вызвать метод объекта напрямую вместо использования Invoke-CimMethod.

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

При локальных запросах разница в скорости между Get-WmiObject и Get-CimInstance практически не ощущается: оба командлета обращаются к одной и той же локальной службе WMI и возвращают сопоставимые по объёму данные за сопоставимое время. Разница становится заметна именно при удалённых запросах и при работе с большими объёмами данных: оптимизированный протокол WS-Management и более строгая типизация объектов в CIM-подходе снижают накладные расходы на сериализацию и передачу данных по сети по сравнению с DCOM, особенно при опросе десятков или сотен машин подряд в рамках инвентаризации парка оборудования.

Для нового кода, который предполагается использовать в актуальных версиях Windows и PowerShell, выбор однозначен в пользу CIM-командлетов: они безопаснее по транспорту, официально рекомендованы производителем, совместимы с кроссплатформенным PowerShell и не подвержены риску внезапного исчезновения, как это произошло с утилитой wmic.exe. Единственный сценарий, где обращение к классическим WMI-командлетам ещё оправдано, это поддержка устаревшего кода на системах, где по каким либо причинам невозможно включить WinRM и недоступна альтернатива через DCOM-сессию, но даже в этом случае такой код стоит рассматривать как временное решение, подлежащее переписыванию при первой возможности.