[英]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.