Powershell CSV 输出问题

问题描述 投票:0回答:2

任何人都可以帮助我解释为什么我在 CSV 文件中将 System.String[] 作为我的网关输出,但它在 ISE 视图/窗口中工作正常。

$testcomputers = Get-Content -Path 'C:\Users2\101.txt'
$exportLocation = 'C:\Users2\PingResults.csv'

# Test connection to each computer before getting the inventory info
foreach ($computer in $testcomputers) {
  if (Test-Connection -ComputerName $computer -Quiet -count 1){
    Add-Content -value $computer -path C:\Users2\OnlineComputers.txt
  }else{
    Add-Content -value $computer -path C:\Users2\OfflineComputers.txt
  }
}

#Specify the list of PC names in the line below
$ArrComputers =  Get-Content -Path 'C:\Users2\OnlineComputers.txt'

Clear-Host
foreach ($Computer in $ArrComputers)
{
    $computerSystem = get-wmiobject Win32_ComputerSystem -Computer $Computer
    $computerBIOS = get-wmiobject Win32_BIOS -Computer $Computer
    $computerOS = get-wmiobject Win32_OperatingSystem -Computer $Computer
    $computerCPU = get-wmiobject Win32_Processor -Computer $Computer
    $computerHDD = Get-WmiObject Win32_LogicalDisk -ComputerName $Computer -Filter drivetype=3
    $computerGateway = Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Computer $Computer -Filter “IPEnabled=TRUE”
        write-host "System Information for: " $computerSystem.Name -BackgroundColor DarkCyan
        "-------------------------------------------------------"
        "Manufacturer: " + $computerSystem.Manufacturer
        "Model: " + $computerSystem.Model
        "Serial Number: " + $computerBIOS.SerialNumber
        "CPU: " + $computerCPU.Name
        "HDD Capacity: "  + "{0:N2}" -f ($computerHDD.Size/1GB) + "GB"
        "HDD Space: " + "{0:P2}" -f ($computerHDD.FreeSpace/$computerHDD.Size) + " Free (" + "{0:N2}" -f ($computerHDD.FreeSpace/1GB) + "GB)"
        "RAM: " + "{0:N2}" -f ($computerSystem.TotalPhysicalMemory/1GB) + "GB"
        "Operating System: " + $computerOS.caption + ", Service Pack: " + $computerOS.ServicePackMajorVersion
        "User logged In: " + $computerSystem.UserName
        "Last Reboot: " + $computerOS.ConvertToDateTime($computerOS.LastBootUpTime)
        "Gateway: " + $computerGateway.DefaultIPGateway
        ""
        "-------------------------------------------------------"

#Build the CSV file
$csvObject = New-Object PSObject -property @{
    'PCName' = $computerSystem.Name
    'Manufacturer' = $computerSystem.Manufacturer
    'Model' = $computerSystem.Model
    'Service Tag' = $computerBIOS.SerialNumber
    'RAM' = "{0:N2}" -f ($computerSystem.TotalPhysicalMemory/1GB)
    'HDDSize' = "{0:N2}" -f ($computerHDD.Size/1GB)
    'HDDFree' = "{0:P2}" -f ($computerHDD.FreeSpace/$computerHDD.Size)
    'CPU' = $computerCPU.Name
    'OS' = $computerOS.caption
    'SP' = $computerOS.ServicePackMajorVersion
    'User' = $computerSystem.UserName
    'Last_Reboot' = $computerOS.ConvertToDateTime($computerOS.LastBootUpTime)
    'Gateway' = $computerGateway.DefaultIPGateway
    } 

#Export the fields you want from above in the specified order
$csvObject | Select PCName, Manufacturer, Model, OS, SerialNumber, CPU, Ram, User, Last_Reboot, HDDSize, HDDFree, Gateway | Export-Csv 'C:\Users2\results.csv' -NoTypeInformation -Append
}

这是 ISE 输出

System Information for:  WS101161
-------------------------------------------------------
Manufacturer: Dell Inc.
Model: OptiPlex 5070
Serial Number: 7HF8T13
CPU: Intel(R) Core(TM) i5-9500 CPU @ 3.00GHz
HDD Capacity: 237.96GB
HDD Space: 67.87% Free (161.51GB)
RAM: 15.79GB
Operating System: Microsoft Windows 10 Pro, Service Pack: 0
User logged In: 
Last Reboot: 04/28/2022 17:40:52
Gateway: 10.170.1.250
-------------------------------------------------------

这是 CSV 输出(用户为空没关系,目前没有人登录到这台电脑)

"PCName","Manufacturer","Model","OS","SerialNumber","CPU","RAM","User","Last_Reboot","HDDSize","HDDFree","Gateway"
"WS101161","Dell Inc.","OptiPlex 5070","Microsoft Windows 10 Pro",,"Intel(R) Core(TM) i5-9500 CPU @ 3.00GHz","15.79",,"4/28/2022 5:40:52 PM","237.96","67.87%","System.String[]"

感谢您的协助!

asdasdasd

powershell csv wmi
2个回答
1
投票

回答您问题的主要问题是,

Win32_NetworkAdapterConfiguration 类
的属性DefaultIPGateway的类型为
string[]

默认IP网关
数据类型:字符串数组

您需要将其转换为

string
,以便
Export-Csv
可以处理它:

PS /> @{ Gateway = $computerGateway[0].DefaultIPGateway } | ConvertTo-Csv

"Gateway"
"System.String[]"

PS /> @{ Gateway = [string] $computerGateway[0].DefaultIPGateway } | ConvertTo-Csv

"Gateway"
"192.168.0.1"

还值得注意的是,

$computerGateway
可能会返回 IP 数组,在这种情况下您应该加入它们:

$computerGateway.DefaultIPGateway -join ', '

除此之外,您的代码还存在其他问题,例如

$computerHDD
上的所有除法运算:

$computerHDD.Size / 1GB

如果主机有多个物理磁盘,将会抛出此异常

InvalidOperation:方法调用失败,因为

[System.Object[]]
不包含名为“op_Division”的方法。

Test-NetConnection
无法可靠地告诉您是否可以连接到远程主机,可能有防火墙阻止 ICMP 数据包,并且您可能仍然能够连接它,因为代码中使用的协议是 WinRM ( WinRM HTTP 使用端口 5985,WinRM HTTPS 使用端口 5986)。

您的代码也可以并行调用,而不是一次调用一台主机,

Invoke-Command
是最好的选择,正如Lee_Dailey在他的有用评论中提到的那样。

向控制台发送信息 (

Write-Host
) 只会减慢你的脚本速度,我已经删除了控制台输出的所有实例。

在循环的每次迭代中使用

Export-Csv -Append
附加到文件也会减慢脚本速度,磁盘 I/O 越多,代码速度就越慢,最好先将所有输出收集到内存中,然后写入到文件一次。

最后,

Get-WmiObject
应替换为
Get-CimInstance
。所有 WMI Cmdlet 都不再在较新版本的 PowerShell (PowerShell Core) 中流通。自 PowerShell 3 起,CIM Cmdlet 就已可用。没有理由在 CIM 上使用 WMI。

话虽如此,这就是我处理你的脚本的方式:

$unavaibleHosts = [System.Collections.Generic.List[string]]::new()
$session = foreach($computer in Get-Content -Path 'C:\Users2\101.txt') {
    try {
        New-PSSession $computer -ErrorAction Stop
    }
    catch {
        $unavaibleHosts.Add($computer)
    }
}

Invoke-Command -Session $session -HideComputerName -ScriptBlock {
    $computerSystem = Get-CimInstance Win32_ComputerSystem
    $computerBIOS = Get-CimInstance Win32_BIOS
    $computerOS = Get-CimInstance Win32_OperatingSystem
    $computerCPU = Get-CimInstance Win32_Processor
    $computerHDD = Get-CimInstance Win32_LogicalDisk -Filter drivetype=3
    $computerGateway = Get-CimInstance -Class Win32_NetworkAdapterConfiguration -Filter IPEnabled=TRUE
    
    $hddSize = $computerHDD.ForEach{ "[{0} {1:N2}]" -f $_.DeviceID, ($_.Size / 1GB) } -join ' | '
    $hddFree = $computerHDD.ForEach{ "[{0} {1:P2}]" -f $_.DeviceID, ($_.FreeSpace / $_.Size) } -join ' | '
    # output from these 2 would look like this:
    # HDDSize      : [C: 236.76] | [D: 931.51]
    # HDDFree      : [C: 73.30%] | [D: 81.43%]
    
    [pscustomobject]@{
        'PCName' = $computerSystem.Name
        'Manufacturer' = $computerSystem.Manufacturer
        'Model' = $computerSystem.Model
        'Service Tag' = $computerBIOS.SerialNumber
        'RAM' = "{0:N2}" -f ($computerSystem.TotalPhysicalMemory / 1GB)
        'HDDSize' = $hddSize
        'HDDFree' = $hddFree
        'CPU' = $computerCPU.Name
        'OS' = $computerOS.caption
        'SP' = $computerOS.ServicePackMajorVersion
        'User' = $computerSystem.UserName
        'Last_Reboot' = $computerOS.LastBootUpTime
        'Gateway' = $computerGateway.DefaultIPGateway -join ','
    }
} | Select-Object * -ExcludeProperty RunspaceId | Export-Csv 'C:\Users2\results.csv' -NoTypeInformation

Remove-PSSession $session
$unavaibleHosts # => Is here for you to troubleshoot the failed connections.

-1
投票
# https://learn.microsoft.com/en-us/windows/win32/cimwin32prov/win32-networkadapterconfiguration
# DefaultIPGateway
# Data type: string array
# Access type: Read-only
# Qualifiers: MappingStrings ("Win32Registry|System\\CurrentControlSet\\Services|Parameters|DefaultGateway")
# Array of IP addresses of default gateways that the computer system uses.
# Example: "192.168.12.1 192.168.46.1"


# Your case
$computerGateway = Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Computer "DESKTOP-9EPNRSP" -Filter "IPEnabled=TRUE"
$csvObject = New-Object PSObject -property @{
    'Gateway' = $computerGateway.DefaultIPGateway
} 
$csvObject.Gateway.GetType().FullName

# Convert to String 
$computerGateway = Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Computer "DESKTOP-9EPNRSP" -Filter "IPEnabled=TRUE"
$csvObject = New-Object PSObject -property @{
    'Gateway' = "$($computerGateway.DefaultIPGateway)"
} 
$csvObject.Gateway.GetType().FullName

#Take first element
$computerGateway = Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Computer "DESKTOP-9EPNRSP" -Filter "IPEnabled=TRUE"
$csvObject = New-Object PSObject -property @{
    'Gateway' = $computerGateway.DefaultIPGateway[0]
} 
$csvObject.Gateway.GetType().FullName

#Generate with comma separated - █ Recommended █
$computerGateway = Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Computer "DESKTOP-9EPNRSP" -Filter "IPEnabled=TRUE"
$csvObject = New-Object PSObject -property @{
    'Gateway' = [string]::Join(",", $computerGateway.DefaultIPGateway)
} 
$csvObject.Gateway.GetType().FullName

输出

System.String[]
System.String
System.String
System.String
© www.soinside.com 2019 - 2024. All rights reserved.