如何在不同的进程中运行PowerShell脚本并将参数传递给它?

时间:2016-12-16 14:41:51

标签: windows powershell process

假设我有一个剧本:

write-host "Message.Status: Test Message Status";

我设法通过以下方式在一个单独的过程中运行它:

powershell.exe -Command
{ write-host "Message.Status: Test Message Status"; }  

问题是我想将参数传递给脚本,以便我可以实现这样的目标:

write-host "I am in main process"
powershell.exe -Command -ArgumentList "I","am","here"
{
    write-host "I am in another process"
    write-host "Message.Status: $($one) $($two) $($three)";
}

但是-ArgumentList在这里不起作用

我明白了:

powershell.exe : -ArgumentList : The term '-ArgumentList' is not recognized as the name of a cmdlet, function, script file, or operable 

我需要在不同的进程中运行PowerShell脚本文件的某些部分,因为PowerShell脚本已上传到外部系统,所以我无法使用其他文件。

5 个答案:

答案 0 :(得分:3)

您可以使用-File参数并按脚本路径进行操作。后面的任何未命名参数将作为脚本参数传递。像下面的东西应该做

powershell -File "C:\ScriptFolder\ScriptwithParameters.ps1" "ParameterOneValu" "valuetwo"

答案 1 :(得分:3)

好的,如果你需要另一个进程而不是另一个文件,那么你最好的选择可能是.NET运行空间。基本上将您的代码包装在一个scriptblock

$newRunspace =[runspacefactory]::CreateRunspace()
$newRunspace.ApartmentState = "STA"
$newRunspace.ThreadOptions = "UseNewThread"         
$newRunspace.Open()
$psCmd = [PowerShell]::Create().AddScript($SB).AddArgument($arg)
$psCmd.Runspace = $newRunspace
$data = $psCmd.BeginInvoke()

然后设置如下所示的运行空间,确保使用“UseNewThread”作为线程选项。请注意,$ arg是您传递给脚本的参数

.BeginInvoke()

如果您需要在运行空间完成后从运行空间获取任何数据,则可能需要调整此项,但有几种方法可以执行此操作(如果需要帮助,请留言)。如果您需要同步执行而不是异步,请将.Invoke()更改为 manager.addAxiom( ontology,factory.getOWLSubClassOfAxiom( factory.getOWLClass("CCC", prefix ), factory.getOWLObjectIntersectionOf( Arrays.asList( factory.getOWLObjectComplementOf( factory.getOWLClass("AAA", prefix )), factory.getOWLClass("AAA", prefix )) ))) ;

答案 2 :(得分:2)

-Command参数需要scriptblock,您可以使用Param()块来定义参数。然后使用-args参数传入参数。您唯一的错误是在{/ 1}} 之前-args放置之后定义了scriptblock。

这就是它的工作原理:

-command

<强>输出:

write-host "I am in main process $($pid)"
powershell.exe -Command {
    Param(
        $one,
        $two,
        $three
    )
    write-host "I am in process $($pid)"
    write-host "Message.Status: $($one) $($two) $($three)";
} -args "I", "am", "here" | Out-Null

答案 3 :(得分:1)

所以应该让你开始,但它需要一些活动部件。 首先我们定义一个新函数:

function Run-InNewProcess{
  param([String] $code)
  $code = "function Run{ $code }; Run $args"
  $encoded = [Convert]::ToBase64String( [Text.Encoding]::Unicode.GetBytes($code))

  start-process PowerShell.exe -argumentlist '-noExit','-encodedCommand',$encoded
}

此功能将启动新流程。它使用start-process cmdlet,-Argumentlist是我们应用于powershell.exe的参数您可以删除-noExit以使新进程在完成时关闭或添加其他PowerShell标记,以及Start-Process上的标记可以根据您的要求调整窗口和行为。

接下来我们定义脚本块:

$script = {
    [CmdletBinding()]
    Param (
    [Parameter(Position=0)]
    [string]$Arg1,

    [Parameter(Position=1)]
    [string]$Arg2)

    write-host "I am in another process"
    write-host "Message.Status: $($Arg1) $($Arg2)";
}

这里我们在块的开始部分定义一些参数,它们有一个位置和名称,所以例如位置0的任何参数都在变量$arg1中。块中的其余代码是全部都在新流程中执行。

现在我们已经定义了脚本块和在新进程中运行它的函数,我们所要做的就是调用它:

Run-InNewProcess $script -Arg1 '"WHAT WHAT"' -Arg2 '"In the But"'

将此代码全部复制到您的ISE中,您将看到它的实际效果。

答案 4 :(得分:1)

Start-Job 将为其scriptblock创建一个进程,并且可以直接向其传递参数。

Write-Host "Process count before starting job: $((Get-Process |? { $_.ProcessName -imatch "powershell" }).Count)"

$job = Start-Job `
    -ArgumentList "My argument!" `
    -ScriptBlock { 
        param($arg) 
        Start-Sleep -Seconds 5; 
        Write-Host "All Done! Argument: $arg" 
    }

while ($job.State -ne "Completed")
{
    Write-Host "Process count during job: $((Get-Process |? { $_.ProcessName -imatch "powershell" }).Count)"
    Start-Sleep -Seconds 1
}
Receive-Job $job -AutoRemoveJob -Wait
Write-Host "Process count after job: $((Get-Process |? { $_.ProcessName -imatch "powershell" }).Count)"