[英]How to pass quoted arguments to elevated batch script via powershell Start-Process
[英]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.