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

我相对较新的PowerShell,并有一个脚本,读取configuration文件,导致一组名称值对,我想作为parameter passing给另一个PowerShell脚本中的函数。

我不知道在devise时将在这个configuration文件中放置什么参数,所以在我需要调用第二个PowerShell脚本的时候,我基本上只有一个variables,它有第二个脚本的path,第二个脚本该variables是传递给pathvariables中标识的脚本的参数数组。

所以包含第二个脚本path($ scriptPath)的variables可能具有如下的值:

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

包含参数($ argumentList)的variables可能如下所示:

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

我如何从这种状态中获得$ argumentList的所有参数来执行script.ps1?

我希望这个第二个脚本的任何写入主机命令对于第一个脚本被调用的控制台是可见的。

我已经尝试了点源,Invoke-Command,Invoke-Expression和Start-Job,但是我还没有find一种不会产生错误的方法。

例如,我认为最简单的第一条路线是尝试开始工作,如下所示:

 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 

…这里是一个名为invokee.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. 

第二个调用工作正常,但一个显着的区别是,第一个版本使用的path中有空格的参数,第二个版本没有。 我错误地处理这些path中的空间的存在?

Invoke-Expression应该可以正常工作,只要确保正确使用它即可。 对于你的情况应该是这样的:

 Invoke-Expression "$scriptPath $argumentList" 

我用Get-Servicetesting了这种方法,似乎按预期工作。

啊哈。 这原来是脚本path中有空格的一个简单问题。

将Invoke-Expression行更改为:

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

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

其实更简单一些 :

方法1:

 Invoke-Expression $scriptPath $argumentList 

方法2:

 & $scriptPath $argumentList 

方法3:

 $scriptPath $argumentList 

如果你的scriptPath有空格,不要忘了把它们转义成`"$scriptPath`"

这里的答案涵盖了从一个PS脚本中调用另一个PS脚本这个更一般的问题,就像你编写脚本中的许多小而窄的脚本一样。

我发现这只是使用点源的一个例子。 那就是,你只是做:

 # This is Script-A.ps1 . ./Script-B.ps1 -SomeObject $variableFromScriptA -SomeOtherParam 1234; 

我发现所有的Q / A都非常混乱和复杂,最终落在了上面这个简单的方法上,这就像调用另一个脚本一样,就好像它是原始脚本中的一个函数,我似乎更直观。

点源可以完整地“导入”其他脚本,使用:

 . ./Script-B.ps1 

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

最终,我真正想念的是我应该build立一个可重用函数模块的概念。

我尝试了使用Invoke-Expression cmdlet的可接受的解决scheme,但它不适用于我,因为我的参数上有空格。 我试图parsing这些论点,逃避这些空间,但是我不能正确地使它工作,而且在我看来,这真的是一个肮脏的工作。 所以经过一番试验,我认为这个问题是:

 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 

这个解决scheme唯一的缺点是你需要确保你的脚本没有“脚本”或“参数列表”参数。

你可以像SQL查询一样执行它。 首先,build立你的命令/expression式并存储在一个variables中,并执行/调用。

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

这是相当前进的,我不认为这需要解释。 所以所有的设置现在执行你的命令,

 Invoke-Expression $command 

我会build议在这里捕捉exception

我们可以用这个splatting :

 & $command @args 

其中@args ( 自动variables$ args )被溅到参数数组中。

在PS,5.1下

Interesting Posts