如何使用 powershell 模块在 runspacepool 中调用带有参数的 powershell ps1 文件

How to call powershell ps1 file with argument in runspacepool with powershell module

我正在学习 powershell。目前我有一个严格的要求。我需要从 powershell 模块 (psm1) 并行调用 powershell 脚本 (ps1)。 ps1 任务如下

param(
    [Parameter(Mandatory=$true)]
    [String] $LogMsg,
    [Parameter(Mandatory=$true)]
    [String] $FilePath
)
Write-Output $LogMsg
$LogMsg | Out-File -FilePath $FilePath -Append

文件路径类似于“C:\Users\user\Documents\log\log1.log” 在 psm1 文件中,我使用 runspacepool 来执行异步任务。喜欢下面的demo

$MaxRunspaces = 5

$RunspacePool = [runspacefactory]::CreateRunspacePool(1, $MaxRunspaces)
$RunspacePool.Open()

$Jobs = New-Object System.Collections.ArrayList

Write-Host $currentPath
Write-Host $lcmCommonPath

$Filenames = @("log1.log", "log2.log", "log3.log")

foreach ($File in $Filenames) {
    Write-Host "Creating runspace for $File"
    $PowerShell = [powershell]::Create()
    $PowerShell.RunspacePool = $RunspacePool
    $FilePath = -Join("C:\Users\user\Documents\log\",$File)
    $PowerShell.AddScript("C:\Users\user\Documents\foo.ps1").AddArgument($FilePath) | Out-Null
    
    $JobObj = New-Object -TypeName PSObject -Property @{
        Runspace = $PowerShell.BeginInvoke()
        PowerShell = $PowerShell  
    }

    $Jobs.Add($JobObj) | Out-Null
}

但是有两个严重的问题。

  1. 无法将参数传递给 ps1 文件。 我只是尝试在 ps1 文件端创建文件路径,它有效并创建了文件。但是当我尝试从 psm1 文件传递​​参数时。文件未创建。我也尝试使用脚本块,它可以传递参数。但是由于我的 ps1 代码太大(以上只是其中的一部分),所以使用脚本块是不真实的。我需要一种方法将参数传递给 ps1 文件。
  2. 当 psm1 仍然是 运行
  3. 时,无法在 ps1 文件中获取写入主机信息

如果 runspacepool 对将参数传递给 ps1 文件有限制,是否有其他解决方案来处理 powershell 脚本的异步任务?谢谢

Can't pass the parameters to ps1 file.

使用 AddParameter() 而不是 AddArgument() - 这将允许您通过名称将参数绑定到特定参数:

$PowerShell.AddScript("C:\Users\user\Documents\foo.ps1").
            AddParameter('FilePath', $FilePath).
            AddParameter('LogMsg', 'Log Message goes here') | Out-Null

Can't get write-host information in ps1 file while psm1 is still running

正确 - 您无法从未附加到主机应用程序默认运行空间的脚本中获取主机输出 - 但如果您使用的是 PowerShell 5 或更新版本,您 可以 收集结果信息来自 $PowerShell 实例并中继,如果你想:

# Register this event handler after creating `$PowerShell` but _before_ calling BeginInvoke()
Register-ObjectEvent -InputObject $PowerShell.Streams.Information -EventName DataAdded -SourceIdentifier 'WriteHostRecorded' -Action {
  $recordIndex = $EventArgs.Index
  $data = $PowerShell.Streams.Information[$recordIndex]
  Write-Host "async task wrote '$data'"
}