none
Invoke-Command ? RRS feed

  • Вопрос

  • Здравствуйте, не могу понять как передать аргумент в скрипт-блок.
    Задача:
    В переменной $script содержится текст файла TestScript.ps1:
    if(!$args)
    {   "Args null"  }
    else
    {  $args;     }

    Мне требуется выполнить это скрипт.
    Invoke-Expression $scrit подходит, но не позволяет передать параметры.
    Попробовал
    Invoke-Command -ScriptBlock { iex $script} -ArgumentList "Test"

    выводит всё-равно "Args null". Как мне передать параметры в $args???
    Спасибо.

    4 сентября 2009 г. 8:55

Ответы

  • PS C:\> $sb = {if(!$args){"Args null"}else{"Args is $args"}}
    PS C:\> & $sb
    Args null
    PS C:\> & $sb 123
    Args is 123

    Впрочем и через Invoke-Command работает:

    PS C:\> Invoke-Command -ScriptBlock $sb
    Args null
    PS C:\> Invoke-Command -ScriptBlock $sb -ArgumentList 123
    Args is 123

    Надо понимать, что текстовая строка не является скриптблоком, независимо от её содержимого. Аналогия: файл .txt не является исполняемым скриптом, даже если в нём содержится код скрипта :)
    Преобразовать строку в скриптблок можно так:
    $line = 'if(!$args){"Args null"}else{"Args is $args"}'
    $sb = $executioncontext.InvokeCommand.NewScriptBlock($line)

    Напрямую выполнить текстовую строку как код можно только с помощью Invoke-Expression
    PS C:\> Invoke-Expression $line
    Args null
    Правда чтобы еще передать аргументы, всё равно понадобится выполнять скриптблок ;)
    PS C:\> Invoke-Expression "& {$line} 123"
    Args is 123

    AKA Xaegr, MCSE: Security, Messaging; MCITP: Server\Enterprise Administrator; Блог: http://xaegr.wordpress.com
    • Предложено в качестве ответа Vasily GusevModerator 5 сентября 2009 г. 8:58
    • Помечено в качестве ответа OlegGel 5 сентября 2009 г. 9:19
    5 сентября 2009 г. 8:58
    Модератор

Все ответы

  • Проверяйте $args[0] и далее:

    if ($args) {write-host $args[0..$($length-1)]}
    else {write-host no args}




    PS. Не знаю как дополнить комментарий после script-блока, вне его.
    PS1. Я правильно Вас понял?
    PS2. Ну сделайте уже чего-нибудь. ПХП и то лучше. имхо. Зачем мне видеть все эти "бр/"
    4 сентября 2009 г. 17:05
  • >>Я правильно Вас понял?
    Не совсем. Дело в том, что аргумент совсем не передается в скрипт-блок, записанный в переменную $script. Для этого достаточно, проверить его длину в скипте:
    $args.Length
    выведет 0.

     Я мог бы вызывать скрипт обычным способом, сохранив текст скрипта в файле. Но тут задача другого рода. У меня накопилось огромное количество скриптов и своих, и чужих и я решил их как-то каталогизировать. Местом хранения я выбрал базу данных на локальном Sql Server. В таблицу базы данных я вношу название, описание и и исходный текст скриптов.
    Затем, когда понадобится выполнить скрипт, по запросу к базе данных по имени скрипта или по его ID,  я получаю текст нужного скрипта и заношу его в переменную $scrip и выполняю. Если скрипт без входных параметров, то всё очень просто, но с параметрами возникает описанная проблема.
    Я конечно мог бы программно создавать временный файл на диске, записывать в него текст скрипта из БД, затем выполнить скрипт обычным способом и в конце удалить временный файл, но тода частично теряется смысл хранения скриптов в базе.

    >>PS2. Ну сделайте уже чего-нибудь. ПХП и то лучше. имхо. Зачем мне видеть все эти "бр/"<br/>
    Да плюс еще Opera 10 не совсем корректно работает с этими страницами ASP.NET . Приходится на форуме из под ущербного ИЕ сидеть:)

    4 сентября 2009 г. 17:52
  • >Ну сделайте уже чего-нибудь. ПХП и то лучше. имхо. Это я про форум...

    Про SQL ничего не скажу. Но аргументы от одного скрипта к другому передаются без проблем. И если передать из одного скрипта в другой аргументы в виде переменной, то эта переменная читается в вызванном скрипте. Пример:

    #1.ps1

    if
    
    
     ($args) {$script=$args[0..$($length-1)]}
    else {write-host no args}

    .\2 $script

    #2.ps1

    write-host $script "script"
    write-host $args "args"





    PS. За форматирование не отвечаю. Достало.
    4 сентября 2009 г. 18:16
  • Может быть я не совсем ясно объясняю. Вот возьмем самый первый скрипт из файла test.ps1:
    #test.ps1
    if(!$args)
    {   "Args null"  }
    else
    {  $args;     }
    --------------------------
    Я в командной строке пишу:
    $script = "";
    get-content .\test.ps1 | ForEach-Object { $script += $_.ToString() + [Environment]::NewLine };

    Теперь в $script содержится текст из файла test.ps1.
    Как мне выполнить команды, которые содержатся в переменной $script в виде строки, да еще и передать что-нибудь как входной аргумент.??
    4 сентября 2009 г. 18:38
  • наверное так:

    get-content .\test.ps1 | %{$_}

    Cейчас проверить не могу, может и так:

    get-content .\test.ps1 | %{invoke-command $_}
    4 сентября 2009 г. 19:42
  • Первый вариант просто выводит текст файла на консоль.
    Второй вариант возвращает кучу ошибок по понятным причинам. Командлет gc возвращает не строку, а массив строк, поэтому на вход к invoke-command сначала пойдет "if(!$args)" и он выполнить не сможет и выдаст ошибку, затем пойде "{" - тоже ошибка и т.д. Нужно из массива строк создать одну строку, что я и сделал выше
     
    get-content .\test.ps1 | ForEach-Object { $script += $_.ToString() + [Environment]::NewLine };
    invoke-Command -ScriptBlock { iex $script}


    В самом начале я писал, что такая штука без аргументов работает.
    Но мне требуется, чтоб заработала такое:
    Invoke-Command -ScriptBlock { iex $script} -ArgumentList "Test"
    4 сентября 2009 г. 20:09
  • PS C:\> $sb = {if(!$args){"Args null"}else{"Args is $args"}}
    PS C:\> & $sb
    Args null
    PS C:\> & $sb 123
    Args is 123

    Впрочем и через Invoke-Command работает:

    PS C:\> Invoke-Command -ScriptBlock $sb
    Args null
    PS C:\> Invoke-Command -ScriptBlock $sb -ArgumentList 123
    Args is 123

    Надо понимать, что текстовая строка не является скриптблоком, независимо от её содержимого. Аналогия: файл .txt не является исполняемым скриптом, даже если в нём содержится код скрипта :)
    Преобразовать строку в скриптблок можно так:
    $line = 'if(!$args){"Args null"}else{"Args is $args"}'
    $sb = $executioncontext.InvokeCommand.NewScriptBlock($line)

    Напрямую выполнить текстовую строку как код можно только с помощью Invoke-Expression
    PS C:\> Invoke-Expression $line
    Args null
    Правда чтобы еще передать аргументы, всё равно понадобится выполнять скриптблок ;)
    PS C:\> Invoke-Expression "& {$line} 123"
    Args is 123

    AKA Xaegr, MCSE: Security, Messaging; MCITP: Server\Enterprise Administrator; Блог: http://xaegr.wordpress.com
    • Предложено в качестве ответа Vasily GusevModerator 5 сентября 2009 г. 8:58
    • Помечено в качестве ответа OlegGel 5 сентября 2009 г. 9:19
    5 сентября 2009 г. 8:58
    Модератор
  • Спасибо большое, именно это и нужно было!

    5 сентября 2009 г. 9:19