Команда искажения Powershell Invoke-Expression - PullRequest
3 голосов
/ 18 октября 2011

Я пытаюсь вызвать команду из сценария powershell. Команда отлично работает при запуске из обычной командной строки. Вот полная команда (извините, она длинная, но если я ее урежу, боюсь, я мог бы пропустить что-то существенное.)

C:\Users\Dave.Work\Desktop\wix36-binaries\candle.exe C:\Users\Dave.Work\Developer\MapCreator\install\win\product.wxs -arch x64 -dPlatform=x64 -dProductVersion=0.9.1.0 -dKarteReleaseBinDir=C:\Users\Dave.Work\Developer\MapCreator\karte-build-release\release -out C:\Users\Dave.Work\Developer\MapCreator\install\win\obj\

Если я вызову эту точно такую ​​же команду , используя Invoke-Expression, произойдет сбой. Он выдает ошибку из исполняемого файла (candle.exe), но, поскольку он отлично работает из командной строки, проблема заключается в том, что powershell каким-то образом искажает строку. Вот мой звонок:

Invoke-Expression 'C:\Users\Dave.Work\Desktop\wix36-binaries\candle.exe C:\Users\Dave.Work\Developer\MapCreator\install\win\product.wxs -arch x64 -dPlatform=x64 -dProductVersion=0.9.1.0 -dKarteReleaseBinDir=C:\Users\Dave.Work\Developer\MapCreator\karte-build-release\release -out C:\Users\Dave.Work\Developer\MapCreator\install\win\obj\'

Это приводит к следующей ошибке от candle.exe:

candle.exe : error CNDL0103 : The system cannot find the file '.9.1.0' with type 'Source'.

Каким-то образом искажается числовой номер версии? Опять же, он отлично работает из командной строки.

Как передать эту команду в Powershell?

[ПРИМЕЧАНИЕ] В конечном счете, эта команда генерируется из переменных, то есть фактическая команда будет выглядеть примерно так:

$WixDir\candle.exe $ScriptDir\product.wxs -arch $Platform -dPlatform=$Platform -dProductVersion=$ProductVersion -dKarteReleaseBinDir=$KarteReleaseBinDir -out $ScriptDir\obj\

Я использую Invoke-Expression, потому что у меня были серьезные проблемы с расширением переменных с использованием, например, оператора вызова. Но я не могу заставить его работать даже без расширения переменной. Таким образом, если решение состоит в том, чтобы экранировать определенные части командной строки, мне также необходимо знать, как применять эти экранированные переменные к переменным.

1 Ответ

7 голосов
/ 18 октября 2011

Попробуйте "-dProductVersion = 0.9.1.0" заключено в "или в". Моя утилита Get-Arg показывает, что исходная команда анализируется, поэтому -dProductVersion=0 и .9.1.0 - это разные аргументы.

На всякий случай, мой Get-Arg.exe (C #):

using System;
class GetArg
{
    static void Main(string[] args)
    {
        foreach(string s in args)
        {
            Console.WriteLine(s);
        }
    }
}

Полезно для проверки таких случаев.


Есть еще более простая иллюстрация. Этот код

function Get-Argument {
    $args
}

Get-Argument -dProductVersion=0.9.1.0

получает этот вывод:

-dProductVersion=0
.9.1.0

То есть PowerShell рассматривает такую ​​команду как наличие двух аргументов.


Объяснение

В PowerShell 2 0 Спецификация языка мы видим параметры

parameter-char:
Any Unicode character except
{   }   (   )   ;   ,   |   &   .   [
colon
whitespace
new-line-character

Примечание: '=' включено, '.' исключен В нашем случае у нас есть

-dProductVersion=0.9.1.0

Согласно спецификации все символы перед '.' действительный параметр персонажи. Итак, мы получаем, первый аргумент результата - -dProductVersion=0

Затем парсер задыхается от '.'. Технически, похоже, мы что-то делаем против правила в том числе "." в аргумент, который начинается с «-». Вот почему мы должен заключать весь аргумент с помощью 'или ".

Это, вероятно, верно и для других исключенных символов.

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