Reputation: 166
I've several problems with the output and export of my current project. I'm using the cmdlet Get-RemoteProgram
to get the installed Software via Network and registry entries.
This is my code for now:
function Get-RemoteProgram ....
$computername = Import-Csv "C:\data\test\test.csv" |
select -ExpandProperty PCName
$regex = @("Program1|Program2|Program3")
$items = @()
foreach ($computer in $computername) {
if (Test-Connection $computer -ErrorAction SilentlyContinue -Count 1) {
$query = Get-RemoteProgram -ComputerName $computer -Property DisplayVersion |
where {$_.ProgramName -match $regex}
$obj = New-Object -Type PSObject
$obj | Add-Member -Name ("Computername") -Value $computer -MemberType NoteProperty -Force
$maxcount = $query.ProgramName.Count
if ($maxcount -gt 1) {
for ($i=0; $i -lt $maxcount; $i++) {
$progandversion = $query.ProgramName[$i] + $query.DisplayVersion[$i]
$obj | Add-Member -Name ($progandversion) -Value "Available" -MemberType NoteProperty -Force
}
} elseif ($maxcount -eq 1) {
$progandversion = $query.ProgramName + $query.DisplayVersion
$obj | Add-Member -Name ($progandversion) -Value "Available" -MemberType NoteProperty -Force
}
$obj | Add-Member -Name ("ProgrammVersion$i") -Value $query.DisplayVersion[$i] -MemberType NoteProperty -Force
$items += $obj
}
$items | Export-Csv c:\daten\inventur\output_final.csv -Append -Force
Write-Host "$computer has been checked.."
}
The problem I now have is that my script does not list all different programs that I am looking for. It should export the computername and afterwards - in the same line - put out an available if the software is installed or keep it clean if the program was not found.
That's the output I get right now:
#TYPE System.Management.Automation.PSCustomObject Computername,"Program1","Program2" Computer1,"Available","Available" Computer1,"Available","Available" Computer2,, Computer1,"Available","Available" Computer3,, Computer2,, Computer1,"Available","Available"
I don't know why the computers are multiple times in the output.
I would like to have it like this:
Computername,Program1,Program2,Program3,Program4 Computer1,Available,,Available,, Computer2,Available,,,, Computer3,,,Available, Computer4,,,,
Can you help me somehow?
Upvotes: 3
Views: 1668
Reputation: 986
The encoded version in c# installed programs via windows registry
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace SoftwareInventory
{
class Program
{
static void Main(string[] args)
{
//!!!!! Must be launched with a domain administrator user!!!!!
Console.ForegroundColor = ConsoleColor.Green;
StringBuilder sbOutFile = new StringBuilder();
Console.WriteLine("DisplayName;IdentifyingNumber");
sbOutFile.AppendLine("Machine;DisplayName;Version");
//Retrieve machine name from the file :File_In/collectionMachines.txt
//string[] lines = new string[] { "NameMachine" };
string[] lines = File.ReadAllLines(@"File_In/collectionMachines.txt");
foreach (var machine in lines)
{
//Retrieve the list of installed programs for each extrapolated machine name
var registry_key = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall";
using (Microsoft.Win32.RegistryKey key = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, machine).OpenSubKey(registry_key))
{
foreach (string subkey_name in key.GetSubKeyNames())
{
using (RegistryKey subkey = key.OpenSubKey(subkey_name))
{
//Console.WriteLine(subkey.GetValue("DisplayName"));
//Console.WriteLine(subkey.GetValue("IdentifyingNumber"));
if (subkey.GetValue("DisplayName") != null)
{
Console.WriteLine(string.Format("{0};{1};{2}", machine, subkey.GetValue("DisplayName"), subkey.GetValue("Version")));
sbOutFile.AppendLine(string.Format("{0};{1};{2}", machine, subkey.GetValue("DisplayName"), subkey.GetValue("Version")));
}
}
}
}
}
//CSV file creation
var fileOutName = string.Format(@"File_Out\{0}_{1}.csv", "Software_Inventory", DateTime.Now.ToString("yyyy_MM_dd_HH_mmssfff"));
using (var file = new System.IO.StreamWriter(fileOutName))
{
file.WriteLine(sbOutFile.ToString());
}
//Press enter to continue
Console.WriteLine("Press enter to continue !");
Console.ReadLine();
}
}
}
Upvotes: 0
Reputation: 18747
Your problem is two-fold. First, you want to update existing data in a CSV, but instead you use -Append
when you run Export-CSV
. This explains while more than one row with a given ComputerName
exists. And second, you are not setting default values for a given ProgramName
, and thus no properties for programs that are not found anywhere exists in the output CSV. To resolve your first problem, you need to run Export-CSV
without appending to save your entire data set into your CSV file. And to resolve your second problem, you should pre-fill your new PSObject
s with properties. Preparation should be done like this:
$programs=get-content "programs.txt" # one name one line, or an array of names in @()
$regex='('+($programs -join ',')+')' # regex out of array
Then in your main cycle you add this line after call to New-Object
:
$programs | % { $obj | Add-Member -Name $_ -Value "Not found" -MemberType NoteProperty } # create default values
Should do. Swap "Not found" for an empty string if you desire.
Upvotes: 2