Home > Software design >  Powershell CSV Output Issue
Powershell CSV Output Issue

Time:04-29

Can anyone assist my with explanation as to why I get System.String[] as my Gateway output in the CSV file but it works fine in the ISE view/window.

$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
}

Here is the ISE output

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
-------------------------------------------------------

And here is the CSV output (User being empty is okay, nobody is signed into this PC at the moment)

"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[]"

Thank you for the assistance!

asdasdasd

CodePudding user response:

The main issue that answers your question, the property DefaultIPGateway of the Win32_NetworkAdapterConfiguration class is of the type string[]:

DefaultIPGateway
Data type: string array

You need to convert it to string so that Export-Csv can handle it:

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

"Gateway"
"System.String[]"

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

"Gateway"
"192.168.0.1"

It is also worth noting that $computerGateway may return an array of IPs in which case you should join them:

$computerGateway.DefaultIPGateway -join ', '

Aside from that, there are other issues with your code, for example all Division operations on $computerHDD:

$computerHDD.Size / 1GB

Will throw this exception if the host has more than one Physical Disk:

InvalidOperation: Method invocation failed because [System.Object[]] does not contain a method named 'op_Division'.

Test-NetConnection is not reliable to tell you if you can or cannot connect to a remote host, there may be a firewall blocking ICMP packets and you may have been able to still connect it since the protocol being used in your code is WinRM (WinRM HTTP uses port 5985 and WinRM HTTPS uses port 5986).

Your code can also be invoked in parallel instead of going one host at a time, Invoke-Command is the best alternative as Lee_Dailey mentions in his helpful comment.

Sending information to the console (Write-Host) will only slow your script down, I've removed all instances of console output.

Appending to a file with Export-Csv -Append on each iteration of your loop will also slow your script down, the more Disk I/O the slower the code will be, it is better to collect all output first in memory and then writing to a file once.

Lastly, Get-WmiObject should be replaced by Get-CimInstance. All the WMI Cmdlets are no longer in circulation in newer versions of PowerShell (PowerShell Core). And the CIM Cmdlets have been available since PowerShell 3. No reason to use WMI over CIM.

With all that being said, this is how I would approach your script:

$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.

CodePudding user response:

# https://docs.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 sepparated - █ 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

Output

System.String[]
System.String
System.String
System.String
  • Related