Bcdedit.exe из PowerShell

Недавно я столкнулся с необходимостью отредактировать элементы загрузки с помощью утилиты bcdedit.exe. Эта утилита используется в системах начиная с Vista, для управления хранилищем конфигурации загрузки, которое заменило boot.ini.

Разумеется я решил запускать утилиту из PowerShell (так как дело происходило на Windows Server 2008R2, то PowerShell было запустить даже проще и быстрее чем cmd.exe 😉 ).

Я ознакомился со справкой программы, вызвав её с ключём /?, и хотел выполнить простое действие – переименовать элемент загрузки. Сначала вызвал bcdedit /enum чтобы посмотреть на список элементов, и узнать идентификатор того который буду переименовывать (identifier).

PS C:\Windows\System32> bcdedit /enum
...
Windows Boot Loader
-------------------
identifier              {c2b02f79-36b4-11dd-9e1b-99d426d57382}
device                  partition=Q:
path                    \Windows\system32\winload.exe
description             Microsoft Windows Vista
...

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

PS C:\Windows\System32> bcdedit /set {c2b02f79-36b4-11dd-9e1b-99d426d57382} description "Windows Vista"
The set command specified is not valid.
Run "bcdedit /?" for command line assistance.
The parameter is incorrect.

В чём же проблема? Вроде бы и синтаксис соответствует указанному в справке, и идентификатор системы я скопировал через буфер обмена, так что ошибок в нём быть не должно… Попробуем создать простой файл .cmd выводящий имена полученных аргументов, и попробовать ту же команду на нём. Я назвал его testargs.cmd и поместил в него следующий текст:

@echo Arg1: [%1]
@echo Arg2: [%2]
@echo Arg3: [%3]
@echo Arg4: [%4]
@echo Arg5: [%5]

Весьма просто, неправда ли? Попробуем на нём ту же команду

PS C:\Windows\System32> testargs.cmd /set {c2b02f79-36b4-11dd-9e1b-99d426d57382} description "Windows Vista"
Arg1: [/set]
Arg2: [-encodedCommand]
Arg3: [YwAyAGIAMAAyAGYANwA5AC0AMwA2AGIANAAtADEAMQBkAGQALQA5AGUAMQBiAC0AOQA5AGQANAAyADYAZAA1ADcAMwA4ADIA]
Arg4: [description]
Arg5: ["Windows Vista"]

Неудивительно что bcdedit ругался на синтаксис. Насколько я понимаю, PowerShell увидев конструкцию в фигурных скобках, посчитал её блоком кода (scriptblock), и решил перед отправкой команде назначения закодировать с помощью base64 и передать после параметра –encodedCommand. Сам то PowerShell.exe без проблем разобрался бы с такой конструкцией, но вот bcdedit.exe удивился 😉

Как же обойти этот неприятный эффект? Ну напеример поместить идентификатор в кавычки:

PS C:\Windows\System32> testargs.cmd /set "{c2b02f79-36b4-11dd-9e1b-99d426d57382}" description "Windows Vista"
Arg1: [/set]
Arg2: [{c2b02f79-36b4-11dd-9e1b-99d426d57382}]
Arg3: [description]
Arg4: ["Windows Vista"]
Arg5: []

Двойные, или одинарные, в данном случае не важно. Главное что PowerShell теперь будет считать этот аргумент обычной строчкой, и передаст дальше в неизменном виде:

PS C:\Windows\System32> bcdedit /set "{c2b02f79-36b4-11dd-9e1b-99d426d57382}" description "Windows Vista"
The operation completed successfully.

Второй вариант решения – просто напросто экранировать фигурные скобки, раз уж они смущают PowerShell. Экранирование в PowerShell выполняется с помощью символа ` (обратный апостроф):

PS C:\Windows\System32> bcdedit /set `{c2b02f79-36b4-11dd-9e1b-99d426d57382`} description "Windows Vista"
The operation completed successfully.

Проблема решена! 🙂 Но тема к сожалению не закрыта. Я постараюсь разобрать другие случаи взаимодействия PowerShell с всевозможными реализациями синтаксиса внешних утилит в других постах. А вы можете рассказать о встретившихся вам ситуациях, в комментариях 🙂

Опубликовано в Command line parsing. Метки: , , . 5 комментариев »

комментариев 5 to “Bcdedit.exe из PowerShell”

  1. Oleg Medvedev Says:

    А вот я как раз сегодня впёрся в проблему как раз со скобками, только с квадратными.
    То есть когда надо скопировать, прочесть или переименовать — проблем по большей части нет: ставь -LiteralPath где надо и вся недолга.
    А вот проблема: надо обработать файл некоей внешней утилиткой. А файл этот может находиться в каталоге, в названии которого присутствуют [].
    Пробовал я так:
    type.exe «d:\work\num[1]\file.txt»
    Не работает. Не работает также, если поставить перед [ и ] знак ` в различных количествах и комбинациях.
    type.exe ‘d:\work\num[1]\file.txt’
    Также не работает и с `.

    Может, есть какая-то команда типа execute -LiteralPath [имяпроги] [параметры]?

    type.exe здесь чисто для иллюстрации, естественно и для лёгкости проверки.
    powershell 2.0 CTP.

  2. itanko Says:

    У меня работает вариант:

    gc ‘tst`[2`]\hooy.txt’

  3. abeshkov Says:

    Интересно а каких либо .Net интерфейсов делающих тоже что и bcdedit нет? Может проще было бы их напрямую вызывать?

  4. Особенности Net.exe Share « PowerShell и другие скрипты Says:

    […] как эта команда выглядит для net.exe поможет файл testargs.cmd который я описал в предыдущем посте из […]

  5. Vasily Gusev Says:

    2 Oleg Medvedev: А где вы взяли type.exe? 🙂 У меня нигде нет такой утилиты 🙂
    В PowerShell — type является псевдонимом для Get-Content, а в Cmd.exe это встроенная команда.


Обсуждение закрыто.