Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/powershell/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Powershell 使用脚本中的参数调用第二个脚本_Powershell_Parameter Passing_Command Line Arguments_Invoke Command_Start Job - Fatal编程技术网

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

Powershell 使用脚本中的参数调用第二个脚本,powershell,parameter-passing,command-line-arguments,invoke-command,start-job,Powershell,Parameter Passing,Command Line Arguments,Invoke Command,Start Job,我有一个脚本,它读取一个配置文件,该文件生成一组名称-值对,我希望将这些名称-值对作为参数传递给第二个PowerShell脚本中的函数 我不知道在设计时会在这个配置文件中放置什么参数,所以就在我需要调用第二个PowerShell脚本的时候,我基本上只有一个变量,它有到第二个脚本的路径,以及第二变量,该第二变量是要传递给路径变量中标识的脚本的参数数组 因此,包含第二个脚本路径的变量($scriptPath)的值可能如下: "c:\the\path\to\the\second\script

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

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

因此,包含第二个脚本路径的变量(
$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 -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”,这显然是为了按名称标识参数,而不是设置其值

我错过了什么

编辑:

Invoke-Expression $scriptPath $argumentList
$scriptPath $argumentList
好的,这是一个名为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时,这是我当前第一次调用Invoke Expression时遇到的错误:

Invoke-Expression : You must provide a value expression on
the right-hand side of the '-' operator.

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

调用表达式
应该可以很好地工作,只要确保正确使用它即可。对于您的情况,它应该如下所示:

Invoke-Expression "$scriptPath $argumentList"

我用Get服务测试了这种方法,并且似乎按照预期工作。

Aha。事实证明,这是一个简单的问题,即脚本路径中存在空格

将调用表达式行更改为:

Invoke-Expression "& `"$scriptPath`" $argumentList"
…足以让它启动。感谢Neolisk为您提供的帮助和反馈

事实上:

方法1:

Invoke-Expression $scriptPath $argumentList
$scriptPath $argumentList
方法2:

& $scriptPath $argumentList
方法3:

Invoke-Expression $scriptPath $argumentList
$scriptPath $argumentList

如果您的
scriptPath
中有空格,请不要忘记将其转义
`“$scriptPath`”

这里有一个答案,它涵盖了从PS脚本调用另一个PS脚本这一更一般的问题,如果您正在编写许多小型、用途狭窄的脚本,您可能会这样做

我发现这只是一个使用点源的例子。也就是说,您只需执行以下操作:

# This is Script-A.ps1

. ./Script-B.ps1 -SomeObject $variableFromScriptA -SomeOtherParam 1234;
我发现所有的Q/A都非常混乱和复杂,最终找到了上面简单的方法,这就像调用另一个脚本,就好像它是原始脚本中的一个函数一样,我觉得这更直观

Dot sourcing可以使用以下方法“导入”另一个脚本的全部内容:

. ./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查询一样执行它。 首先,构建命令/表达式并存储在变量中,然后执行/调用

$command =  ".\yourExternalScriptFile.ps1" + " -param1 '$paramValue'"
这是相当超前的,我认为不需要解释。 现在所有人都准备好执行你的命令了

Invoke-Expression $command
我建议在这里捕获异常,我们可以使用它:

& $command @args
其中,
@args
()被飞溅到参数数组中


在PS,5.1下,我假设您希望从另一个.ps1文件运行.ps1文件[这里是$scriptPath以及存储在$argumentList中的多个参数]

Invoke-Expression "& $scriptPath $argumentList"

这段代码可以很好地工作

如果您为每个脚本提供源代码,它也会有所帮助。例如,创建说明您的问题的POC(概念验证)项目。然后我们可以测试和使用它,也许有人会找到一个解决方案或解决办法。是的,我正在尝试制作一个迷你版来说明。将很快发布…调用表达式“$scriptPath$argumentList”将立即返回,并且似乎没有运行脚本。如果我将其更改为调用表达式“powershell$scriptPath$argumentList”,PowerGui就会显示为挂起。@Hoobajoob:Invoke表达式不会立即返回,它会耐心地等待,直到调用的脚本结束—我刚刚在一个POC项目上测试过。您所针对的脚本一定有问题。嗯-我已经从批处理文件、visual studio IDE、DOS命令行和powershell控制台会话以多种不同的方式运行了第二个脚本,但这是我第一次尝试从另一个powershell脚本运行它。脚本本身会有什么样的东西阻止它通过调用表达式成功启动?这只有在参数列表中的对象都是字符串类型时才起作用,尽管是对的?@Backwards\u Dave:
$scriptPath
$argumentList
这里是字符串。字符串可以包含非字符串参数(写为字符串)。希望它能回答你的问题