Что такое cmd / batch альтернатива устаревшему wmic? - PullRequest
1 голос
/ 26 сентября 2019

Мне известно о том, что по состоянию на 2012 год wmic устарело, и теперь я все равно обычно использую PowerShell, поэтому уже отошел от него.

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

Мой вопрос таков: при устаревании wmic, что является рекомендуемой альтернативой для продолжения доступа к инструментарию управления Windows из командной строки ииз пакетных файлов?

Лучшее, что я могу себе представить, это что-то вроде:

powershell -command "(Get-CimInstance Win32_Processor) | select *" | some_other_program.exe

(этот пример для получения атрибутов процессора)

Но один главныйнедостатком этого является то, что уровни ошибок и среда больше не доступны.Таким образом, команда powershell завершается успешно, даже если команда этого не делает).И изменения, внесенные в среду в команде powershell, не распространяются на командный файл.

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

1 Ответ

0 голосов
/ 26 сентября 2019

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

Самый простой способ заставить команду PowerShell, вызываемую через интерфейс командной строки PowerShell, сообщать о ненулевом коде выходавыдает ошибку завершения скрипта (завершения потока), которая приводит к коду ошибки 1, который ваш пакетный файл может проверить:

@echo off

:: # Simulate a failing CIM call
powershell -c "$ErrorActionPreference='Stop'; Get-CimInstance Win32_NoSuchClass" 

:: # Exit, if the PowerShell command failed.
if ERRORLEVEL 1 echo Error: Get-CimInstance failed>&2 & exit /b %ERRORLEVEL%

echo Moving on...

$ErrorActionPreference='Stop' в начале команды обеспечиваетчто любая последующая ошибка становится оканчивающейся скриптом.
Чтобы выборочно игнорировать не прерывающиеся ошибки, используйте -ErrorAction Ignore по-отдельности для команды.
Если ошибок не возникает, код выхода неявно 0.

Обработка ошибок в PowerShell очень сложна;см. эту проблему GitHub для получения полной сводки.

Примечание:

  • Собственные команды PowerShell, такие как Get-CimInstance, не устанавливают выходкоды;лучшее, что вы можете сделать, это сопоставить ошибки с кодом выхода 1 и успешно завершить с кодом выхода 0.

  • Если вы вызываете внешние программы из PowerShell, их код выхода отображаетсяв автоматической переменной $LASTEXITCODE;вы можете использовать exit $LASTEXITCODE для передачи этого кода завершения из командной строки PowerShell;однако обычно вы можете просто напрямую вызывать внешние программы из своего пакетного файла - обход через PowerShell не требуется.


А изменения, внесенные в среду в команде powershell, делаютне распространяются на командный файл.

True, команда PowerShell неизменно выполняется в дочернем процессе , среда которого не влияет на вызывающий процесс.

Обычно:

  • Захватывать выводить из команды PowerShell в файл или обрабатывать его в памяти с помощью цикла for /f (см. Пример ниже) - если не передать выходные данные - достаточно.

  • Если вам действительно нужно изменить среду вызывающего пакетного файла , команда PowerShell выведет данные для этих модификаций и примените их в командном файле.

    • Например, если вы хотите, чтобы ваша команда PowerShell устанавливала переменные среды, сделайте так, чтобы она выводила <name>=<value> пар строк, которыеПакетный файл можно использовать для установки этих переменных.

Пример настройки вывода команды PowerShell для анализа в пакетном файле с помощью for /f;обратите внимание, что цитирование может быть хитрым:

@echo off

:: # Get the .Name and .MaxClockSpeed property values from the Win32_Processor instance.
for /f "tokens=1,* delims==" %%i in ('powershell -c "$ErrorActionPreference='Stop'; Get-CimInstance Win32_Processor | %% { foreach ($n in 'Name', 'MaxClockSpeed') { \""$n=$($_.$n)\"" } }"') do (
  echo [%%i]=[%%j]
)

:: # Exit, if the PowerShell command failed.
if ERRORLEVEL 1 echo Error: Get-CimInstance failed>&2 & exit /b %ERRORLEVEL%

Выше приведено что-то вроде:

[Name]=[Intel(R) Core(TM) i5-7360U CPU @ 2.30GHz]
[MaxClockSpeed]=[2304]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...