noz3r0
noz3r0

Reputation: 345

Adding objects to array to create multiple columns

I'm trying to get the DisplayName of all Software listed in AddRemovePrograms for each computer, add it to an array under the name of the computer, then export. Here's what I have:

$Computers = gc "C:\Get Software.txt"
$CSV = "C:\Get Software.csv"
$Results = @()

If (Test-Path $CSV) {
    Remove-Item $CSV
    }

Foreach($Computer in $Computers){

    #Get DisplayName of Software Installed on Asset
    $Software = Get-WmiObject Win32Reg_AddRemovePrograms -ComputerName $Computer | Select-Object -ExpandProperty DisplayName
    $counter = 0

    While ($counter -lt $Software.count){

    #Create a PSObject. Loops through all software and adds to $Results.
    $Obj = New-Object PSOBJECT
    Add-member –inputobject $Obj –membertype Noteproperty  -Name $Computer -Value $Software[$counter]
    $counter++
    $Results+=$Obj
    }




}


$Results | Export-Csv $CSV -NoTypeInformation

Unfortunately, the output only lists the first Computer in the CSV. I've tried stepping through this to understand it, I just don't understand why I can't add the $Obj variable to $Results with a different Name Property (In this case I'm looping and making a new name based on the computer name in my .txt file). It seems to only take the first input and won't put a new column header then spit out the software. Below is an example of what I'm getting and what I'd like to get instead.

OUTPUT

A01234
Program1
Program2
Program3

EXPECTED OUTPUT

A01234     B05678      C09123
Program1   Program97   Program30
Program2   Program98   Program31
Program3   Program99   Program32

Hopefully this makes some sense. Any assistance would be appreciated, I'm clearly doing something wrong with the objects and I'm not seeing it. Thanks!

Upvotes: 1

Views: 13513

Answers (1)

TheMadTechnician
TheMadTechnician

Reputation: 36297

This is do-able, it just isn't quite as simple as you would think. What I would suggest is setting things up as a hashtable where the keys are your computer names and your values are an array of software titles for each computer. Then you find out how many titles the computer with the most software has (that's how many rows you'll have, so it's how many times you'll have to loop), and create a loop to make that many objects. Each object will have no properties to start, and then we add a property for each computer in the hashtable, and the value for that property will be the Nth item listed in the hashtable for that computer. Here's the code, it might make this all make more sense:

$Computers = 'A01234','B05678','C09123'

$SftwrPerCmp = [ordered]@{}

ForEach($Computer in $Computers){
    $SftwrPerCmp.add($Computer,@())

    #Randomly generate 7-15 strings as 'Programs' for current computer
    $Software = 1..$(get-random -Maximum 15 -Minimum 7)|%{(Get-Random -inputobject $("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" -split ''|?{$_}) -count 6) -join ''}

    ForEach($Title in $Software){
        $SftwrPerCmp["$Computer"] += $Title
    }
}

$MaxTitleCount = $SftwrPerCmp.Values|%{$_.count}|sort|select -last 1

$Results = @()
For($i=0;$i -lt $MaxTitleCount;$i++){
    $Record = New-Object PSObject
    $SftwrPerCmp.Keys | ForEach{Add-Member -InputObject $Record -NotePropertyName $_ -NotePropertyValue $SftwrPerCmp["$_"][$i]}
    $Results += $Record
    Clear-Variable Record
}

$Results|Format-Table -AutoSize

Now obviously you will not randomly generate software titles, you'll use your existing $Software = Get-WmiObject line that's in your existing code instead since that part was at least working for you. This should result in the listings that you were looking for. My code resulted in this:

A01234 B05678 C09123
------ ------ ------
CU7K5E 6GJWOB 97H1TY
7VCZ5T CIPWVK 760NKU
CHKPY0 J4B7D0 1QOSD3
2YEFR4 2VY6DM O68SKU
VI7ZQG WLJQN9 Q5VJAZ
ZQOKNV R9KZG1 H2XZK4
S8IZC4 GRSMPU BIZXKA
LAVNI0 TKBOUC K9DEFU
3U7KVO        JZ3X4H
A6GVUK        18AC5H
NMI32Q        H14GPJ
50KSZ6        XU0FWC
PAN5TC        9WXR5U
531M04              

Upvotes: 3

Related Questions