使用脚本中的参数调用第二个脚本

我有一个脚本,它读取一个配置文件,该文件生成一组名称值对,我希望将这些名称值对作为参数传递给第二个 PowerShell 脚本中的函数。

我不知道在设计时这个配置文件中会放置什么参数,所以就在我需要调用第二个 PowerShell 脚本的时候,我基本上只有一个变量有第二个脚本的路径,第二个变量是一个参数数组,传递给在 path 变量中标识的脚本。

因此,包含第二个脚本路径($scriptPath)的变量可能具有如下值:

"c:\the\path\to\the\second\script.ps1"

包含参数($argumentList)的变量可能类似于:

-ConfigFilename "doohickey.txt" -RootDirectory "c:\some\kind\of\path" -Max 11

如何使用 $argumentList 中的所有参数从这种状态执行 script.ps1?

我希望第二个脚本中的任何 write-host 命令对于调用第一个脚本的控制台都是可见的。

我已经尝试过点源、调用命令、调用表达式和启动作业,但是我还没有找到一种不会产生错误的方法。

例如,我认为最简单的第一条路线是尝试 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”,这显然是为了通过名称来识别参数,而不是设置其值。

我错过了什么?

编辑:

好的,这里有一个待调用脚本的模型,在一个名为 invowkee.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.

第二个调用工作得很好,但一个重要的区别是,第一个版本使用的参数的路径中有空格,而第二个版本没有。我是否错误地处理了这些路径中存在的空间?

219759 次浏览

Invoke-Expression应该可以很好地工作,只要确保你正确地使用它:

Invoke-Expression "$scriptPath $argumentList"

我用 Get-Service 测试了这种方法,似乎正如预期的那样工作。

原来这是一个简单的问题,在脚本的路径中存在空格。

将 Invoke-Expression 行更改为:

Invoke-Expression "& `"$scriptPath`" $argumentList"

... 足以让它开始。感谢 Neolisk 的帮助和反馈!

实际上,很多 更简单:

方法一:

Invoke-Expression $scriptPath $argumentList

方法2:

& $scriptPath $argumentList

方法三:

$scriptPath $argumentList

如果在 scriptPath中有空格,不要忘记转义它们

下面的答案涵盖了从 PS 脚本调用另一个 PS 脚本这一更为普遍的问题,如果您使用许多小的、用途狭窄的脚本编写脚本,则可能会这样做。

我发现这只是一个使用点外包的例子,也就是说,你只需要:

# This is Script-A.ps1


. ./Script-B.ps1 -SomeObject $variableFromScriptA -SomeOtherParam 1234;

我发现所有的问答都非常令人困惑和复杂,并最终使用了上面提到的简单方法,这实际上就像调用另一个脚本,就好像它是原始脚本中的一个函数一样,我似乎觉得这种方法更直观。

点源可以“导入”其他脚本的全部内容,使用:

. ./Script-B.ps1

现在这两个文件好像合并了。

最终,我真正缺少的是我应该构建一个可重用函数模块的概念。

我尝试了使用 Invoke-Expression cmdlet 这种公认的解决方案,但它对我不起作用,因为我的参数上有空格。我试图解析论点,逃避空白,但我不能正确地使它工作,而且在我看来,它真的是一个肮脏的工作。 经过一些实验,我对这个问题的看法是:

function Invoke-Script
{
param
(
[Parameter(Mandatory = $true)]
[string]
$Script,


[Parameter(Mandatory = $false)]
[object[]]
$ArgumentList
)


$ScriptBlock = [Scriptblock]::Create((Get-Content $Script -Raw))
Invoke-Command -NoNewScope -ArgumentList $ArgumentList -ScriptBlock $ScriptBlock -Verbose
}


# example usage
Invoke-Script $scriptPath $argumentList

这个解决方案的唯一缺点是您需要确保您的脚本没有“ Script”或“ ArgumentList”参数。

您可以像执行 SQL 查询一样执行它。 首先,构建命令/Expression 并存储在变量中,然后执行/调用。

$command =  ".\yourExternalScriptFile.ps1" + " -param1 '$paramValue'"

这很直接,我不认为需要解释。 所以现在都准备好执行你的命令了,

Invoke-Expression $command

我建议在这里捕捉异常

我们可以使用 血肉横飞:

& $command @args

其中 @args(自动变量 $args)被分成参数数组。

PS 下面是5.1

我猜你想逃跑。Ps1文件[这里是 $scriptPath 以及存储在 $argumentList 中的多个参数]。Ps1文件

Invoke-Expression "& $scriptPath $argumentList"

这段代码可以正常工作