我有一个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信息一起输出。
关于这是为什么的任何想法?
答案 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
}