在PowerShell中,ForEach循环的某些部分被跳过了吗?

时间:2018-08-14 16:26:48

标签: powershell foreach powershell-v3.0

我有一个Powershell脚本,除了我的输出的一部分被跳过且无法弄清楚原因外,似乎运行正常。这是正在运行的脚本:

#Server list provided for the script.
$ServerList = Get-Content $env:USERPROFILE\Documents\Servers.txt
#Counter for first If loop.
$Counter = 0
#Counter for second If loop.
$Counter2 = 0

#ForEach loop going through the server list, picking out OS, Drives, and CPU info and dumping it into an array.
ForEach($Server in ($ServerList))
    {
        "Collecting server information on $Server, please wait..."
        "Collecting Operating System..."
        $OS = gwmi Win32_OperatingSystem -ComputerName $Server | select Caption
        "Collecting Storage..."
        $Drives = gwmi Win32_LogicalDisk -ComputerName $Server | Format-Table DeviceId, @{n="Size in GB";e={[math]::Round($_.Size/1GB,2)}},@{n="Free Space in GB";e={[math]::Round($_.FreeSpace/1GB,2)}}
        "Collecting CPU..."
        $CPU = gwmi Win32_Processor -ComputerName $Server | select Name, Manufacturer
        $ServerInfo = @($OS,$Drives,$CPU)
        #$ServerInfo
        #Do loop that posts the info stored in the array and ups the first counter. Runs while counter is equal to 0.
        Do
            {
                "All done. Here's all the info we got on $($Server):"
                 $ServerInfo
                 $Counter++
            }While ($Counter -eq 0)
        #If loop that checks if the Counter has been bumped by the Do loop. Sets Counter to 0 and increases Counter2 by 1.
        If ($Counter -eq 1)
            {
                $Counter = 0
                $Counter2++
            }
        #If loop that checks if Coutner2 is equal to a certain number. This is the hard stop to the loop.
        If ($Counter2 -eq 2)
            {
                "Max number of runs met. Stopping."
                break
            }
    }

我知道脚本很杂乱,需要大量工作,但是由于某些原因,在ForEach循环的第二遍之后,OS变量被完全跳过,并且不会显示在控制台中。第一次运行后,它将完全保留,仅发布驱动器和CPU信息。我以为Do和If循环可能有点奇怪,所以我将它们注释掉进行测试,但结果相同。

我已经尝试在循环运行时发布变量OS,驱动器和CPU,以确保它确实将某些内容保存到了变量中,而且确实如此,而且我还在循环中断后调用变量本身以查看如果循环/脚本中发生了一些奇怪的事情。我发现在循环结束后调用OS变量和ServerInfo数组会使它与OS信息一起输出。

关于这是为什么的任何想法?

1 个答案:

答案 0 :(得分:0)

我认为输出奇怪的原因在于您使用计数器的方式。

如果我正确理解了这个问题,则希望(控制台)为Servers.txt文件中的每个服务器输出,但BUT会最大化到一定数量。文本文件中可能有一百多台服务器,但是您希望将输出限制为仅一定数量的服务器,然后脱离主ForEach循环。

不仅如此,您还想捕获并以后结合使用各种Get-WmiObject调用获得的不同信息,而PowerShell会使用这些信息来格式化它们。

使用| Out-String的诀窍。

下面是我的脚本版本。

$ServerList = Get-Content $env:USERPROFILE\Documents\Servers.txt
$Counter  = 0  # the running counter; gets incremented for each server
$MaxCount = 2  # the maximum number of servers you want to process

#ForEach loop going through the server list, picking out OS, Drives, and CPU info and dumping it into an array.
ForEach($Server in $ServerList) {
    Write-Host "Collecting server information on $Server, please wait..."
    Write-Host  "Collecting Operating System..." -ForegroundColor Yellow

    $OS = (Get-WmiObject Win32_OperatingSystem -ComputerName $Server | 
           Select-Object Caption |
           Out-String).Trim()

    Write-Host "Collecting Storage..." -ForegroundColor Yellow
    $Drives = (Get-WmiObject Win32_LogicalDisk -ComputerName $Server | 
               Select-Object DeviceId, 
                             @{n="Size in GB";e={[math]::Round($_.Size/1GB,2)}},
                             @{n="Free Space in GB";e={[math]::Round($_.FreeSpace/1GB,2)}} |
                             Out-String).Trim()

    Write-Host "Collecting CPU..." -ForegroundColor Yellow
    $CPU = (Get-WmiObject Win32_Processor -ComputerName $Server | 
            Select-Object Name, Manufacturer |
            Out-String).Trim()

    Write-Host
    # join these strings together with newlines so the output will be readable
    $ServerInfo = @($OS,$Drives,$CPU) -join "`r`n`r`n"
    # output the serverInfo for this server. 
    $ServerInfo
    Write-Host

    # instead of the -join above which looks more like the original code you gave,
    # you could also do:
    #  $ServerInfo = "{0}`r`n`r`n{1}`r`n`r`n{2}`r`n" -f $OS, $Drives, $CPU
    # or even:
    #  Write-Host $OS
    #  Write-Host
    #  Write-Host $Drives
    #  Write-Host
    #  Write-Host $CPU
    #  Write-Host

    # if $Counter has reached the maximum number of servers to process, break out of the ForEach loop
    If (++$Counter -ge $MaxCount) {
        Write-Host "Max number of runs ($MaxCount) met. Stopping." -ForegroundColor Green
        return
    }
    Write-Host
}