0

been trying to get this to output to a csv. Works fine in of itself, but can't figure out how to do it. I guess because I'm using write-host it never actually goes in the pipeline which gives me a null pipeline input error. I've tried playing aroung with a few other ways to no avail. Here is the "stock code" i'd like to manage to export into a csv:

$InstalledSoftware = Get-ChildItem "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall"

foreach($obj in $InstalledSoftware)
    {write-host $obj.GetValue('DisplayName') -NoNewline; 
     write-host " - " -NoNewline; 
     write-host $obj.GetValue('DisplayVersion')}

As I said, it seems like it the pipeline remains empty so adding | export-csv doesn't work. I don't even need it to write output it on screen, although it's a nice plus, so for now I'll try to reformulate it with something other than write-host.

TylerH
  • 20,799
  • 66
  • 75
  • 101
Hex
  • 23
  • 6

2 Answers2

2

You need to create first an object with the information about the specific program and the add this information to an array. Then you can export the array as an CSV. You could also export one entry at a time and append it to the csv. But if find this approach cleaner:

$InstalledSoftware = Get-ChildItem "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall"
$allSoftware = [System.Collections.ArrayList]@()
foreach($obj in $InstalledSoftware) {
    $software = New-Object -TypeName PSObject
    $software | Add-Member -MemberType NoteProperty -Name DisplayName -Value $obj.GetValue("DisplayName")
    $software | Add-Member -MemberType NoteProperty -Name Version -Value $obj.GetValue("DisplayVersion")
    $null = $allSoftware.Add($software)
}

$allSoftware | Export-Csv -Path "SomePath"
guiwhatsthat
  • 2,349
  • 1
  • 12
  • 24
  • Thanks a lot that did the trick. To understand, you created an array with $allSoftware = [System.Collections.ArrayList]@() which creates an array and fills it with an empty set, correct? Then in the foreach loop: 1 create a new object and assign it as a PSObject Type, named $software 2 then for each $software object you used add-member to add a property and named that property "DisplayName" with Noteproperty -Name 3 same as step 2 but for version 4 used $null = $allSoftware.add($software) to in a sense "append" the single $software objects to the $allSoftware array Correct, somewhat? – Hex Apr 27 '22 at 11:10
  • bit of a noob so trying to get a better understanding. and thank you for your time once again – Hex Apr 27 '22 at 11:10
  • 1
    `$allSoftware = [System.Collections.ArrayList]@()` with this line of code you create an empty arraylist. Which is needed later needed to add the objects (which are PSObject). You can not use the Add() function on an object which does not exists. And you create it outside of the loop to not overwrite it everytime – guiwhatsthat Apr 27 '22 at 12:20
0

I reworked your code to produce something that can be fed to Export-csv.

The following code at least produces a CSV file. It does produce several records with no data in them. It may also have other errors. But at least it will give you a handle on how to manipulate the objects.

$InstalledSoftware = Get-ChildItem "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall"


$installedSoftware | %{
    [pscustomobject]@{
        'DisplayName'     = $_.GetValue('DisplayName')
        'DisplayVersion'  = $_.GetValue('DisplayVersion')
        }} |Export-csv myfile.csv 

You may have to learn a little about pipelines, typecasting, hashtables, and Export-csv. I hope it's worth the effort.

halfer
  • 19,824
  • 17
  • 99
  • 186
Walter Mitty
  • 18,205
  • 2
  • 28
  • 58
  • Hmm it'll be interesting to understand the differences in your approach and the approach used by the first responder (@guiwhatsthat). Definitely gonna try and play around with both just to see what changes. Know a bit about pipelining but clearly not enough, don't know jack about typecasting and hashtables, so will definitely look those up, many thanks friend – Hex Apr 27 '22 at 12:04
  • Hashtables are a big subject, and I'm only ankle deep into them myself. The simple explanation is that they are an easy way to create a collection of name, value pairs that can be accessed in a variety of ways. – Walter Mitty Apr 27 '22 at 13:16
  • Typecasting is just a way of forcing a conversion to a given type. PSCustomObject is, for present purposes, a container that works like an old fashioned record did. Export-csv can work with a pipeline that's delivering a stream of PSCustomObjects. – Walter Mitty Apr 27 '22 at 13:18
  • So each of the steps in my approach is adding value by delivering something the next step can use. – Walter Mitty Apr 27 '22 at 13:19