Powershell Start-Process для запуска сеанса Powershell и передачи локальных переменных

Есть ли способ использовать командлет Powershell Start-Process для запуска нового сеанса Powershell и передачи блока сценария с локальными переменными (одна из которых будет массивом)?

Пример:

$Array = @(1,2,3,4)

$String = "This is string number"

$Scriptblock = {$Array | ForEach-Object {Write-Host $String $_}}

Start-Process Powershell -ArgumentList "$Scriptblock"

Спасибо.


person atownson    schedule 21.07.2013    source источник
comment
Сделайте шаг назад и опишите реальную проблему, которую вы пытаетесь решить, а не то, что вы считаете решением. Как вы думаете, зачем вам это нужно?   -  person Ansgar Wiechers    schedule 22.07.2013
comment
Вы можете вызвать выражение с помощью оператора &. Как & $Scriptblock в вашем примере.   -  person oɔɯǝɹ    schedule 22.07.2013
comment
Я хотел бы начать новый сеанс PowerShell и запустить блок сценария в этом сеансе. Блок сценария должен содержать локальные переменные из начального сеанса.   -  person atownson    schedule 22.07.2013
comment
@atownson, зачем нужен новый сеанс? вы пытаетесь предотвратить нежелательный вывод? Или вы хотите отправить результат в другое место?   -  person oɔɯǝɹ    schedule 22.07.2013
comment
Что ж, ниже я сделал предположение, что будет работать, но это своего рода кладжа, поэтому, если вы действительно не настроены передавать переменные в новый сеанс с помощью Start-Process , было бы неплохо последовать совету здесь и еще раз изучить, чего вы пытаетесь достичь с помощью этого, и есть ли более элегантный способ сделать это.   -  person Adi Inbar    schedule 22.07.2013


Ответы (5)


Я почти уверен, что нет прямого способа передать переменные из одного сеанса PowerShell в другой. Лучшее, что вы можете сделать, - это какой-нибудь обходной путь, например, объявить переменные в коде, который вы передаете в -ArgumentList, интерполировав значения в вызывающем сеансе. Способ интерполяции переменных в объявлениях в -ArgumentList зависит от того, какие типы переменных. Для массива и строки вы можете сделать что-то вроде этого:

$command = '<contents of your scriptblock without the curly braces>'

Start-Process powershell -ArgumentList ("`$Array = echo $Array; `$String = '$String';" + $command)
person Adi Inbar    schedule 21.07.2013

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

$ScriptBlock = {
    function Test([string]$someParameter)
    {
        # Use $someParameter to do something...
    }
}

# Run the script block and pass in parameters.
$myString = "Hello"
Start-Process -FilePath PowerShell -ArgumentList "-Command & {$ScriptBlock Test('$myString')}"
person deadlydog    schedule 19.03.2014

В параметрах командной строки для PowerShell.exe говорится, что вы должны иметь возможность для передачи аргументов при использовании блока сценария путем добавления -args:

PowerShell.exe -Command { - | <script-block> [-args <arg-array>] | <string> [<CommandParameters>] }

Однако, когда я пытаюсь это сделать, я получаю следующую ошибку:

-args: термин «-args» не распознается как имя командлета, функции, файла сценария или работающей программы. Проверьте написание имени или, если был включен путь, убедитесь, что путь правильный, и повторите попытку.

Я добавил $MyInvocation | fl в блок сценария, чтобы увидеть, что происходит, и похоже, что -args просто добавляется к десериализованным командам в блоке сценария (отсюда и ошибка, поскольку -args не является допустимой командой). Я также пробовал использовать GetNewClosure () и $ Using: VariableName, но они работают только при вызове блока сценария (в отличие от этого, когда мы используем его для сериализации / десериализации команд).

Мне удалось заставить его работать, обернув его функцией вроде ответа deadlydog.

$var = "this is a test"

$scriptblock = {
    $MyInvocation | fl #Show deserialized commands
    function AdminTasks($message){
        write-host "hello world: $message"
    }
}

Start-Process powershell -ArgumentList '-noexit','-nologo','-noprofile','-NonInteractive','-Command',$scriptblock,"AdminTasks('$var')" -Verb runAs #-WindowStyle Hidden

#Output:
MyCommand             :
                         $MyInvocation | fl #Show deserialized commands
                         function AdminTasks($message){
                         write-host hello world: $message
                         }
                         AdminTasks('this is a test')
BoundParameters       : {}
UnboundArguments      : {}
ScriptLineNumber      : 0
OffsetInLine          : 0
HistoryId             : 1
ScriptName            :
Line                  :
PositionMessage       :
PSScriptRoot          :
PSCommandPath         :
InvocationName        :
PipelineLength        : 2
PipelinePosition      : 1
ExpectingInput        : False
CommandOrigin         : Runspace
DisplayScriptPosition :


hello world: this is a test

Обертывание его в блок скрипта и использование $args[0] или $args[1] также работает, просто имейте в виду, что вам многим нужно заключить $ var0 или $ var1 в кавычки, если есть проблемы при десериализации, и использовать `$, чтобы предотвратить появление $ sb заменен на "", так как эта переменная не существует в области действия вызывающего:

$var0 = "hello"
$var1 = "world"

$scriptblock = {
    $MyInvocation | fl #Show deserialized commands
    $sb = {
        write-host $args[0] $args[1]
    }
}

Start-Process powershell -ArgumentList '-noexit','-nologo','-noprofile','-NonInteractive','-Command',$scriptblock,"& `$sb $var0 $var1"
person Greg Bray    schedule 07.01.2016
comment
вы, наверное, уже поняли это, но -args буквально не параметр. Он предназначен для получения набора параметров из хэш-таблицы через разбивка с использованием символа @. - person Steve Taylor; 22.07.2021

Мне удалось заставить это работать, соединив массив с «/» для создания строки и введя блок сценария в другой сценарий .ps1 с соответствующими параметрами и разделив объединенную строку обратно на массив во втором сценарии и используя

Start-Process Powershell -ArgumentList "&C:\script.ps1 $JoinedArray $String"

Уродливо, но это единственный способ заставить его работать. Спасибо за все отклики.

person atownson    schedule 22.07.2013

Если вы хотите передать сериализуемые объекты, но не строки, я написал решение: Есть ли способ передать сериализуемые объекты в сценарий PowerShell с помощью start-process?

person Kirk Liemohn    schedule 07.12.2015