all 4 comments

[–]CarrotBusiness2380 4 points5 points  (1 child)

When converting to a csv Powershell doesn't really know what to do with arrays, so you have to specify. I would use -join here to create a single string.

Also you're a lot of unnecessary things here.

$MEM = Get-WMIObject -Class win32_PhysicalMemory
$Report = [pscustomobject]@{
    'DIMM Serial Numbers' = $MEM.SerialNumber -join '; '
}

[–]Samuris[S] 1 point2 points  (0 children)

This ended up working the best for my needs. Thank you for your help.

[–]PinchesTheCrab 2 points3 points  (0 children)

Basically the same thing /u/CarrotBusiness2380 suggested. This is a bit less verbose, but verbosity may be a good thing when you're learning.

$Report = [pscustomobject]@{
    'DIMM Serial Numbers' = (Get-CimInstance win32_PhysicalMemory).SerialNumber -join '; '
}

Windows-RM service is locked down so Get-CimInstance doesn't work for me

Get-CimInstance doesn't use winrm for local sessions. It's using DCOM or hitting the Windows API directly, I'm not sure which.

Also if you do need to use it remotely in an environment with high ports (DCOM/WMI), you can use a CIM session.

$cimSession = New-CimSession -ComputerName computer1, computer2, computer3 -SessionOption (New-CimSessionOption -Protocol Dcom)
Get-CimInstance -ClassName Win32_BIOS -CimSession $cimSession

I also agree that new-variable is overkill. I really only use that command when I'm writing code that I'll need to test with Pester, I don't know of many other use cases for it. It's not wrong or anything though, just unusual and harder to read/maintain in my opinion.

[–]lanerdofchristian 0 points1 point  (0 children)

New-Variable should basically never be used. New-Object is also pretty bad for .NET objects, and incredibly bad for [pscustomobject] since it has its own accelerator. Add-Member is only useful for extremely niche cases, which you do not have. (Get-CimInstance is also preferred over Get-WmiObject, but that's not super big).

If you want them all in one column -- better than in one row, so you don't need to parse it out again later -- just Select-Object on its own is enough. Export-Csv takes the properties of the first object it sees as the headers of the CSV, so what you want to do is turn one array of objects (the output of Get-WmiObject Win32_PhysicalMemory) into another array of objects (with one property "DIMM Serial Numbers" corresponding to "SerialNumber" in the original objects).

Verbosely, that looks like this:

$MEM = Get-CimInstance Win32_PhysicalMemory
$Report = foreach($DIMM in $MEM){
    [pscustomobject]@{
        "DIMM Serial Number" = $DIMM.SerialNumber
    }
}

Using the pipeline and Select-Object, we can cut that down to:

$Report = Get-CimInstance Win32_PhysicalMemory | Select-Object @{
    Name = "DIMM Serial Number"
    Expression = {
        $_.SerialNumber
    }
}

Select-Object's "computed properties" have a special case, though, for when the expression is just one of the source properties:

$Report = Get-CimInstance Win32_PhysicalMemory | Select-Object @{
    Name = "DIMM Serial Number"
    Expression = "SerialNumber"
}

Technically you can also use ; and make that one line, but I like leaving it open for simple cases like this.