簡體   English   中英

如何在不同的進程中運行PowerShell腳本並將參數傳遞給它?

[英]How to run PowerShell script in a different process and pass arguments to it?

假設我有一個腳本:

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腳本上傳到外部系統,我無法使用其他文件。

-Command參數需要一個scriptblock ,您可以在其中使用Param()塊定義參數。 然后使用-args參數傳入參數。 您唯一的錯誤是定義scriptblock 之前-args放在-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

輸出:

I am in main process 17900
I am in process 10284
Message.Status: I am here

您可以使用-File參數並按腳本路徑進行操作。 后面的任何未命名參數將作為腳本參數傳遞。 下面應該做的事情

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

好的,如果你需要另一個進程而不是另一個文件,那么你最好的選擇可能就是.NET運行空間。 基本上將您的代碼包裝在一個scriptblock中

$SB = {
  *Your Code*
}

然后設置如下所示的運行空間,確保使用“UseNewThread”作為線程選項。 請注意,$ arg是您傳遞給腳本的參數

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

如果您需要在完成后從運行空間獲取任何數據,則可能需要調整此項,但有幾種方法可以執行此操作(如果需要幫助,請留言)。 如果需要同步執行而不是異步,則將.BeginInvoke()更改為.Invoke()

所以應該讓你開始,但它需要一些活動部分。 首先我們定義一個新函數:

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中,您將看到它正在運行中。

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)"

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM