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

VMware虚拟机使用信息脚本执行缓慢且导出CSV失败求助

问题排查与解决方案

一、脚本运行缓慢的核心原因及优化

  1. 串行SMB访问无超时控制
    脚本逐个通过\\$($computer.Name)\d$\Users访问虚拟机D盘用户目录,每个请求依赖网络响应,若遇到离线/网络不通的虚拟机,会长时间卡在SMB连接上(默认超时极长)。串行处理大量虚拟机时,总耗时会急剧增加。

    • 优化方案:添加SMB访问超时控制,改用并行处理减少等待时间:
      # 带超时的用户目录查询函数
      function Get-LatestUserFolder {
          param([string]$ComputerName)
          $timeout = 5 # 设置5秒超时
          $job = Start-Job -ScriptBlock {
              Get-ChildItem "\\$using:ComputerName\d$\Users" -ErrorAction SilentlyContinue | 
              Sort-Object LastWriteTime -Descending | 
              Select-Object Name, LastWriteTime -First 1
          }
          $result = if (Wait-Job $job -Timeout $timeout) { Receive-Job $job }
          Remove-Job $job -Force
          return $result
      }
      
      循环中调用该函数替代直接的Get-ChildItem,避免长时间等待无响应的机器。
  2. 数组拼接的性能损耗
    使用$CSVArray += $Entry每次都会创建新数组,虚拟机数量较多时,内存复制开销会随数据量增大而急剧上升,拖慢运行速度。

    • 优化方案:改用泛型列表存储数据:
      # 替换原数组初始化
      $CSVArray = [System.Collections.Generic.List[PSCustomObject]]::new()
      # 替换数组拼接操作
      $CSVArray.Add($entry)
      
  3. 不必要的全量排序
    Get-ChildItem获取所有用户文件夹后再排序,可优化为直接取最新条目减少内存占用:

    # PowerShell 5.1+支持-Top参数,无需全量排序
    $Data = Get-ChildItem "\\$($computer.Name)\d$\Users" -ErrorAction SilentlyContinue | 
            Sort-Object LastWriteTime -Descending -Top 1 | 
            Select-Object Name, LastWriteTime
    

二、导出CSV为空/报错的原因及解决

  1. 初始$Filename报错原因
    原脚本通过保存对话框选择路径时,可能因目标目录无写入权限、路径含特殊字符,导致Export-CSV的-Path参数无效。

  2. 导出为空的核心原因

    • AD计算机列表为空:检查Get-ADComputer的-SearchBase路径是否匹配新域OU结构,单独运行以下命令验证是否返回预期虚拟机:
      Get-ADComputer -filter 'Enabled -eq $True' -SearchBase "OU=Virtual,OU=Computers-Internal,DC=Domain,DC=Com"
      
    • SMB访问全部失败:新域中可能存在虚拟机D盘共享未开启、权限变更等问题,导致所有\\$computer.Name\d$\Users访问失败。可在循环中添加日志输出,定位故障机器:
      Write-Host "Processing $($Computer.Name)..."
      
    • 对象序列化问题:自定义CsvRow类的[object]类型属性可能导致Export-CSV无法正确识别字段,改用PSCustomObject替代自定义类:
      foreach($Computer in $Computers){
          $entry = [PSCustomObject]@{
              ComputerName = $Computer.Name
              LastUser     = $null
              LastLogon    = $null
              Inactive     = "False"
          }
          Try{
              $Data = Get-LatestUserFolder -ComputerName $Computer.Name
              if($Data){
                  $entry.LastUser = $Data.Name
                  $entry.LastLogon = $Data.LastWriteTime
                  $entry.Inactive = if($Data.LastWriteTime.AddDays($InactiveDays) -lt $Today) { "True" } else { "False" }
              } else {
                  $entry.Inactive = "True"
              }
          } catch {
              $entry.LastUser = "Access Error"
              $entry.Inactive = "True"
          }
          $CSVArray.Add($entry)
      }
      
    • 权限与路径问题:确保运行脚本的账号对c:\temp有写入权限,手动创建c:\temp目录后再尝试导出。

三、调试建议

  • 在循环中添加日志,输出每台机器的处理状态,定位卡顿节点。
  • 手动测试访问单台虚拟机的\\computerName\d$\Users,确认SMB共享及权限正常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 03:42:06