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

如何在单个PowerShell runspace导入Exchange本地与在线模块并复用认证?

实现Exchange本地与Exchange Online模块在单个PowerShell Runspace池中共用且无需重复认证

可以实现将Exchange本地(OnPrem)和Exchange Online的已认证会话导入单个Runspace池,所有子Runspace无需重复认证即可调用两边的命令。以下是针对你现有脚本的修正方案:

原脚本核心问题

  1. 错误地尝试传递Import-PSSession生成的临时模块对象到子Runspace,这类模块依赖主Runspace的会话上下文,子Runspace无法直接复用
  2. 未正确将已认证的PSSession注入到Runspace池的初始会话状态(ISS),导致子Runspace无法获取Exchange Online的认证上下文

修正后的完整脚本

# --------------------------
# 1. 主Runspace中建立并认证Exchange Online会话
# --------------------------
if (-not $exoSession) {
    $exo_un = Get-Content "xxx"
    $exo_pw = Get-Content "xxx" | ConvertTo-SecureString
    $exo_creds = New-Object System.Management.Automation.PSCredential -ArgumentList $exo_un, $exo_pw
    
    # 连接Exchange Online并指定命令前缀,避免与本地命令冲突
    Connect-ExchangeOnline -Credential $exo_creds -Prefix "Ex" -ShowBanner:$false
    $exoSession = Get-PSSession | Where-Object { $_.ComputerName -like "outlook.office365*" -and $_.State -eq "Opened" } | Select-Object -First 1
}

# --------------------------
# 2. 主Runspace中建立并认证Exchange本地会话
# --------------------------
if (-not $exopSession) {
    $uri = "http://your-onprem-exchange-server/PowerShell/" # 替换为本地Exchange的PowerShell URI
    $exopSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri $uri -Authentication Negotiate
    # 在主Runspace中先导入本地命令,确保命令可用
    Import-PSSession $exopSession -AllowClobber -CommandName Get-Mailbox, Get-Recipient, Set-AdServerSettings | Out-Null
    Set-AdServerSettings -ViewEntireForest:$true
}

# --------------------------
# 3. 配置Runspace池的初始会话状态(ISS)
# --------------------------
$iss = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault()

# 将已认证的Exchange Online会话导入ISS
$iss.ImportPSSession($exoSession, @{
    AllowClobber = $true
    CommandName  = "Get-ExMailbox", "Get-ExMailboxStatistics", "Get-ExMailboxFolderStatistics"
    Prefix       = "Ex"
}) | Out-Null

# 将已认证的Exchange本地会话导入ISS
$iss.ImportPSSession($exopSession, @{
    AllowClobber = $true
    CommandName  = "Get-Mailbox", "Get-Recipient", "Set-AdServerSettings"
}) | Out-Null

# 添加Set-AdServerSettings到ISS,确保子Runspace能设置森林视图
$iss.Commands.Add(([System.Management.Automation.Runspaces.SessionStateFunctionEntry]::new("Set-AdServerSettings", (Get-Command Set-AdServerSettings).Definition)))

# --------------------------
# 4. 创建并启动Runspace池
# --------------------------
$maxThreads = 50
$runspacePool = [runspacefactory]::CreateRunspacePool(1, $maxThreads, $iss, $host)
$runspacePool.Open()

# --------------------------
# 5. 创建子Runspace任务
# --------------------------
$powershell = [powershell]::Create()
$powershell.RunspacePool = $runspacePool

$powershell.AddScript({       
    Param ($smtp)        
    
    # 确保子Runspace也能查看整个森林
    Set-AdServerSettings -ViewEntireForest:$true

    # 调用两边的命令
    $recipientExo = Get-ExMailbox -Identity $smtp -ErrorAction SilentlyContinue
    $recipientExop = Get-Recipient -Identity $smtp -ErrorAction SilentlyContinue
    
    # 返回结果对象
    [PSCustomObject]@{
        Smtp   = $smtp
        Online = $recipientExo
        Onprem = $recipientExop
    }
})

# 添加参数
$smtp = "name.name@domain.com"
$powershell.AddParameter('smtp', $smtp) | Out-Null

# 执行并获取结果
$returnVal = $powershell.BeginInvoke()
$result = $powershell.EndInvoke($returnVal)

# 输出结果
Write-Host "执行结果:"
$result

# 清理资源
$powershell.Dispose()
$runspacePool.Close()
$runspacePool.Dispose()
Get-PSSession | Remove-PSSession

关键修改说明

  1. 复用已认证会话:在主Runspace中完成Exchange Online和本地的认证,将已建立的PSSession直接导入到Runspace池的ISS中,子Runspace会自动继承会话的认证上下文,无需重复认证
  2. 避免命令冲突:使用-Prefix "Ex"给Exchange Online的命令添加前缀,防止与本地Exchange命令重名(比如Get-Mailbox和Get-ExMailbox)
  3. 初始会话状态配置:直接通过ImportPSSession将已认证会话导入ISS,而非传递临时模块路径,确保子Runspace能正确调用两边的命令
  4. 资源清理:添加了Runspace池和会话的清理代码,避免残留未关闭的会话

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 16:37:52