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

PowerShell foreach循环存数组为空、无法生成HTML邮件正文的问题

问题根因排查

数组赋值为空的核心原因

  • 两种执行场景的输出流逻辑差异:直接在控制台执行脚本时,模块返回的有效用户对象会直接输出到控制台,错误不会影响已生成内容的展示;但当把foreach循环整体用@()包裹赋值给变量时,循环内部抛出的非终止错误会直接清空当前输出流的收集结果,最终得到空数组。
  • 跨租户调用Get-MsolUser时未添加错误屏蔽,遇到无合作权限、权限过期的客户租户时,MSOnline模块抛出的非终止错误会直接中断当前循环块的标准输出流,进一步加剧输出收集失效的问题。
  • 原代码中$_.isLicensed -eq "TRUE"的判断存在类型不匹配问题:isLicensed属性本身是布尔类型,部分版本的MSOnline模块会因为类型不匹配静默返回空结果。
  • 原代码直接将select UserPrincipalName输出的PSCustomObject对象存入数组,未提取纯属性值,在HTML渲染时会触发默认对象字符串化逻辑,导致内容挤成一行。

输出格式混乱挤在同一行的原因

PowerShell对非字符串类型的对象做隐式字符串转换时,会默认输出对象的类型全称,不会逐字段换行展示。控制台场景下有专属格式化引擎做表格化渲染,所以能看到正常的用户列表;但直接将这类对象数组拼入HTML邮件正文时,没有格式化引擎做适配,所有内容会被压缩成单个字符串块,无法按列表展示。

可直接复用的修正代码
Connect-MsolService -Credential $Credential
$customers = Get-MsolPartnerContract -All
$nonCompliantUsers = @()

foreach ($customer in $customers) {
  # 跳过指定匹配域名的租户
  if ($customer.defaultdomainname -like "*Domain1*" -or $customer.defaultdomainname -like "*DomainABC*") {
    continue
  }
  # 租户级用户查询,加错误屏蔽避免中断循环
  $tenantRiskUsers = Get-MsolUser -All -EnabledFilter EnabledOnly -TenantId $($customer.TenantId) `
    -ErrorAction SilentlyContinue |
    Where-Object {
      $_.StrongAuthenticationRequirements.State -eq $null -and 
      $_.isLicensed -eq $true
    }
  # 逐行提取纯字符串UPN存入数组,不保留对象
  foreach ($user in $tenantRiskUsers) {
    $nonCompliantUsers += $user.UserPrincipalName
  }
}

# 拼接HTML格式的邮件正文,适配邮件渲染规则
$htmlMailBody = @"
<h3>跨租户未配置MFA的已授权风险用户清单</h3>
<p>共排查到不符合合规要求的用户:$($nonCompliantUsers.Count) 个</p>
<ul>
<li>$($nonCompliantUsers -join "</li><li>")</li>
</ul>
"@
实操注意事项
  • 不要依赖@(foreach(...))的隐式数组收集逻辑处理带外部模块调用的循环:模块抛出的非终止错误会直接干扰输出流的收集结果,显式初始化数组、逐行追加值的方式稳定性更高。
  • 生成HTML邮件内容时,必须逐行拼接带标签的纯文本内容,不要直接将PowerShell对象数组隐式转为字符串传入正文。
  • 所有跨租户的MSOnline调用必须加-ErrorAction SilentlyContinue,适配CSP合作场景下必然存在的租户权限过期、合作关系解除的场景,避免单个租户的查询错误打断全量数据收集。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.27 12:36:06