У меня есть сценарий, который считывает файл конфигурации, в результате чего получается набор пар "имя-значение", которые я хотел бы передать в качестве аргументов функции во втором сценарии PowerShell.
Я не знаю, какие параметры будут помещены в этот файл конфигурации во время разработки, поэтому прямо в тот момент, когда мне нужно вызвать этот второй сценарий PowerShell, у меня в основном есть только одна переменная, которая имеет путь к этому второму сценарию, а вторая переменная, представляющая собой массив аргументов для передачи скрипту, указанному в переменной пути.
Таким образом, переменная, содержащая путь ко второму сценарию ($scriptPath
), может иметь такое значение, как:
"c:\the\path\to\the\second\script.ps1"
Переменная, содержащая аргументы ($argumentList
), может выглядеть примерно так:
-ConfigFilename "doohickey.txt" -RootDirectory "c:\some\kind\of\path" -Max 11
Как мне перейти от такого положения дел к выполнению script.ps1 со всеми аргументами из $ argumentList?
Я бы хотел, чтобы любые команды write-host из этого второго скрипта были видны консоли, из которой вызывается этот первый скрипт.
Я пробовал использовать точечный источник, Invoke-Command, Invoke-Expression и Start-Job, но не нашел подхода, который бы не приводил к ошибкам.
Например, я подумал, что проще всего сначала попробовать Start-Job, который называется следующим образом:
Start-Job -FilePath $scriptPath -ArgumentList $argumentList
... но это не сработает с этой ошибкой:
System.Management.Automation.ValidationMetadataException:
Attribute cannot be added because it would cause the variable
ConfigFilename with value -ConfigFilename to become invalid.
... в этом случае ConfigFilename является первым параметром в списке параметров, определенном вторым скриптом, и мой вызов, по-видимому, пытается установить его значение на -ConfigFilename, которое, очевидно, предназначено для идентификации параметра по имени, а не для установки его ценить.
Что мне не хватает?
РЕДАКТИРОВАТЬ:
Хорошо, вот макет вызываемого скрипта в файле с именем invokee.ps1
Param(
[parameter(Mandatory=$true)]
[alias("rc")]
[string]
[ValidateScript( {Test-Path $_ -PathType Leaf} )]
$ConfigurationFilename,
[alias("e")]
[switch]
$Evaluate,
[array]
[Parameter(ValueFromRemainingArguments=$true)]
$remaining)
function sayHelloWorld()
{
Write-Host "Hello, everybody, the config file is <$ConfigurationFilename>."
if ($ExitOnErrors)
{
Write-Host "I should mention that I was told to evaluate things."
}
Write-Host "I currently live here: $gScriptDirectory"
Write-Host "My remaining arguments are: $remaining"
Set-Content .\hello.world.txt "It worked"
}
$gScriptPath = $MyInvocation.MyCommand.Path
$gScriptDirectory = (Split-Path $gScriptPath -Parent)
sayHelloWorld
... а вот макет вызывающего скрипта в файле с именем invoker.ps1:
function pokeTheInvokee()
{
$scriptPath = (Join-Path -Path "." -ChildPath "invokee.ps1")
$scriptPath = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($scriptPath)
$configPath = (Join-Path -Path "." -ChildPath "invoker.ps1")
$configPath = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($configPath)
$argumentList = @()
$argumentList += ("-ConfigurationFilename", "`"$configPath`"")
$argumentList += , "-Evaluate"
Write-Host "Attempting to invoke-expression with: `"$scriptPath`" $argumentList"
Invoke-Expression "`"$scriptPath`" $argumentList"
Invoke-Expression ".\invokee.ps1 -ConfigurationFilename `".\invoker.ps1`" -Evaluate
Write-Host "Invokee invoked."
}
pokeTheInvokee
Когда я запускаю invoker.ps1, я получаю эту ошибку при первом вызове Invoke-Expression:
Invoke-Expression : You must provide a value expression on
the right-hand side of the '-' operator.
Второй вызов работает нормально, но одно существенное отличие состоит в том, что первая версия использует аргументы, пути которых содержат пробелы, а вторая - нет. Неправильно ли я обращаюсь с пробелами на этих путях?