You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将函数传入PowerShell的ForEach-Object -Parallel循环

解决PowerShell 7 ForEach-Object -Parallel无法访问外部函数的问题

核心原因

ForEach-Object -Parallel会创建独立的线程级运行空间,默认无法直接访问主运行空间中定义的函数、变量,这就是Convert-LDAPProperty被识别为不存在的原因。

可行解决方案

方案1:通过$using:传递函数定义到并行块

先将外部函数的定义存入变量,再在并行块内重新定义该函数:

# 保存外部函数的定义文本
$convertLdapFunc = ${function:Convert-LDAPProperty}.ToString()

$Results | Where-Object {$_} | ForEach-Object -Parallel {
    # 在并行块内重新注册函数
    $function:Convert-LDAPProperty = $using:convertLdapFunc

    $Computer = $_
    $Up = $True
    if ($using:PSBoundParameters['Ping']) {
        $Up = Test-Connection -Count 1 -Quiet -ComputerName $_.properties.dnshostname
    }
    if ($Up) {
        if ($using:PSBoundParameters['Raw']) {
            $Computer = $_
            $Computer.PSObject.TypeNames.Insert(0, 'func.Computer.Raw')
        }
        else {
            $Computer = Convert-LDAPProperty -Properties $_.Properties
            $Computer.PSObject.TypeNames.Insert(0, 'func.Computer')
        }
        $Computer
    }
}

注意:主运行空间的PSBoundParameters也需要用$using:前缀引用,并行块无法直接访问。

方案2:直接在并行块内定义函数

如果函数代码较短,可直接将Convert-LDAPProperty的定义嵌入并行块:

$Results | Where-Object {$_} | ForEach-Object -Parallel {
    # 并行块内定义目标函数
    function Convert-LDAPProperty {
        param(
            [Parameter(Mandatory=$true)]
            $Properties
        )
        # 这里写入你的函数逻辑
        # ...
    }

    $Computer = $_
    $Up = $True
    if ($using:PSBoundParameters['Ping']) {
        $Up = Test-Connection -Count 1 -Quiet -ComputerName $_.properties.dnshostname
    }
    if ($Up) {
        if ($using:PSBoundParameters['Raw']) {
            $Computer = $_
            $Computer.PSObject.TypeNames.Insert(0, 'func.Computer.Raw')
        }
        else {
            $Computer = Convert-LDAPProperty -Properties $_.Properties
            $Computer.PSObject.TypeNames.Insert(0, 'func.Computer')
        }
        $Computer
    }
}

方案3:将函数打包为模块复用

如果有大量复用函数,建议将其封装到PowerShell模块(.psm1文件)中,在并行块内导入模块即可:

# 假设函数已封装到MyLDAPTools.psm1模块
$Results | Where-Object {$_} | ForEach-Object -Parallel {
    # 导入模块(可使用完整路径确保能找到)
    Import-Module MyLDAPTools

    $Computer = $_
    $Up = $True
    if ($using:PSBoundParameters['Ping']) {
        $Up = Test-Connection -Count 1 -Quiet -ComputerName $_.properties.dnshostname
    }
    if ($Up) {
        if ($using:PSBoundParameters['Raw']) {
            $Computer = $_
            $Computer.PSObject.TypeNames.Insert(0, 'func.Computer.Raw')
        }
        else {
            $Computer = Convert-LDAPProperty -Properties $_.Properties
            $Computer.PSObject.TypeNames.Insert(0, 'func.Computer')
        }
        $Computer
    }
}

额外注意事项

  • 主运行空间的变量、参数都需要通过$using:前缀才能在并行块中访问。
  • 并行块的运行空间是临时初始化的,导入模块或定义函数的操作会在每个线程执行一次,但PowerShell会做缓存优化,不会重复加载模块。
  • 如果Convert-LDAPProperty依赖其他外部函数或模块,需确保这些依赖也能在并行块中被访问(同样用$using:传递或导入模块)。

内容的提问来源于stack exchange,提问作者Quentin_otd

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 11:37:01