$array = #()
$path="C:\Reports\Software.txt"
$programs = Get-Content -Path $Path;
foreach ($program in $programs)
{
$system64=Get-ItemProperty
HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* |
Select DisplayName, DisplayVersion | where {$_.DisplayName -like
"*$program*"};
$system32=Get-ItemProperty
HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* | Select
DisplayName, DisplayVersion| where {$_.DisplayName -like "*$program*"};
if ($system64)
{
Write-Host "npp query = "$system64""
Write-Host "npp query = "$system32""
Write-Host -ForegroundColor green "$program already installed!"
$array += $system64
}
elseif ($system32)
{
Write-Host "npp query = "$system64""
Write-Host "npp query = "$system32""
Write-Host -ForegroundColor green "$program already installed!"
$array += $system32
}
else
{
$array += $program
}
}
$array |Export-Csv C:\Reports\Software.csv -NoType
I am trying to create a table with specific software I have on my computer and their Version.
I would like if the Software doesn't exit to put software name under the header DisplayName and under the header DisplayVersion to put Not Installed.
It works fine if the software exists but if it doesn't it doesn't put the name under the header and put a blank line on the excel file.
example what I am taking now is :
DisplayVersion DisplayName
Gimp 2.8.22
7-Zip 18.01
Notepad++ 7.5.8
What i Want
DisplayVersion DisplayName
Gimp 2.8.22
7-Zip 18.01
Adobe Acrobat Not Installed
Notepad++ 7.5.8
any suggestions ?
Give this one a try in your else statement:
$array += #(1 | Select-Object #{Name="DisplayName";Expression={$program}},#{Name="DisplayVersion";Expression={'not installed'}})
With this, you create a custom object and add it to your array.
Hope it helps.
Related
Firstly, I have a csv file with a list of programs that should be included with the default installation of Windows. The CSV looks like this.
Name;Version;Vendor;InstallDate
64 Bit HP CIO Components Installer;18.2.4;Hewlett-Packard;20210902
7-Zip 18.05 (x64 edition);18.05.00.0;Igor Pavlov;20210812
Adobe Acrobat Reader DC;20.006.20034;Adobe Systems Incorporated;20210903
Secondly, I have a powershell script that tries to compare the list of programs on a remote computer with the list of programs in the CSV file (by Name, Version and Vendor). It is supposed to output only the non matching programs.
The comparing part works perfectly, but now I would like to color the lines of output which match by Name and Vendor, but not by Version. How would I go about doing that?
This is my powershell script.
$programs =#()
$programs = Get-WmiObject –computername <ComputerName> -Class Win32_Product
foreach($program in $programs) {
foreach($defprogram in Import-Csv -Path "...\defprograms.csv" -Delimiter ';') {
if ($program.Name -eq $defprogram.Name -And $program.Version -eq $defprogram.Version -And $program.Vendor -eq $defprogram.Vendor) {
$programs = $programs -ne $program }
}}
$programs | sort-object Name | format-table -AutoSize Name,Version,Vendor,InstallDate
And this is the output of fore mentioned script.
In the example in the output, I would like to make the '64 Bit HP CIO Components Installer' colored red.
64 Bit HP CIO Components Installer 15.2.1 Hewlett-Packard 20210909
Canon Laser Printer/Scanner/Fax Extended Survey Program 2.1.2 CANON INC. 20210216
Not a nice solution, but do the job :
$a = #"
Name;Version;Vendor;InstallDate
64 Bit HP CIO Components Installer;18.2.4;Hewlett-Packard;20210902
7-Zip 18.05 (x64 edition);18.05.00.0;Igor Pavlov;20210812
Adobe Acrobat Reader DC;20.006.20034;Adobe Systems Incorporated;20210903
"#
$b = $a | Convertfrom-Csv -Delimiter ';'
$b | % {Write-Host "$($_.name);" -ForegroundColor Red -NoNewline; Write-Host "$($_.Vendor);" -NoNewline; Write-Host $($_.Installdate) ;}
You can do this by reading the CSV with default programs you need to colorize.
Then create a regex string of their .Name property. Use Format-Table as usual, but append Out-String -Stream so you can capture the resulting lines in a variable
# your code here:
$programs = #(Get-WmiObject –computername <ComputerName> -Class Win32_Product)
foreach($program in $programs) {
foreach($defprogram in Import-Csv -Path "...\defprograms.csv" -Delimiter ';') {
if ($program.Name -eq $defprogram.Name -And $program.Version -eq $defprogram.Version -And $program.Vendor -eq $defprogram.Vendor) {
$programs = $programs -ne $program }
}
}
# read the default programs and create a regex string of their Name fields
$defprograms = Import-Csv -Path "...\defprograms.csv" -Delimiter ';'
$redprograms = '({0})' -f (($defprograms.Name | ForEach-Object { [regex]::Escape($_) }) -join '|')
# Format-Table the array of objects and capture the resulting lines in variable `$table`
$table = $programs | Sort-Object Name | Format-Table -AutoSize Name,Version,Vendor,InstallDate | Out-String -Stream
# next loop through these lines and find lines that match any of the default program names
switch -Regex ($table) {
"^$redprograms\s*" {
Write-Host $_.Substring(0, $matches[1].Length) -NoNewline -ForegroundColor Red
Write-Host $_.Substring($matches[1].Length)
}
default { $_ }
}
Output would then look something like
I am having an issue with the output from one property as a comma separated value instead of a list in the out-gridview. Is there a way to have a value be added to the output as a list instead of a single line?
.'C:\Program Files\Microsoft\Exchange Server\V14\bin\RemoteExchange.ps1'
Connect-ExchangeServer -Auto -AllowClobber
do {
Write-Host
Write-Host
Write-Host
$name = Read-Host "What is the user's first name or letter?"
Write-Host
Write-Host
Write-Host
$list = Get-ADUser -Filter * | ? {$_.SamAccountName -match $name} |
select #{N="Highlight a User & Press Ctrl+C then Ctrl+V"; E={$_.SamAccountName}} |
sort SamAccountName |
Out-String
Write-Host -ForegroundColor Green $list
$box = Read-Host "Copy and paste the mailbox you want to see?"
$user = $box
$mailbox= Get-Mailbox -Identity $user | Get-MailboxStatistics |
Sort totalitemsize -desc |
select #{Name="User"; Expression={$_.DisplayName}},
#{Expression={"{0:N2}" -f($_.TotalItemSize.Value.ToMb()/1024)};label=”Mailbox Size in GB”},
#{Expression={"{0:N0}" -f($_.TotalItemSize.Value.ToMb())};label=”Mailbox Size in MB”},
#{Name="Message Count"; Expression={"{0:N0}" -f($_.itemcount)}},
#{Name="Database"; Expression={$_.DatabaseName}}
$folders= Get-MailboxFolderStatistics $user |
? {$_.ItemsInFolder -gt 0} |
Sort ItemsInFolder -Descending |
Select Name,
#{N="Items in Folder"; E={"{0:N0}" -f($_.ItemsInFolder)}},
#{N=”Folder Size in MB”;E={"{0:N0}" -f($_.FolderSize.ToMb())}}
$object= [PSCustomObject]#{
User = $mailbox.'User'
'Mailbox Size in MB'= $mailbox.'Mailbox Size in MB'
'Message Count' = $mailbox.'Message Count'
Database = $mailbox.Database
Name = $folders.Name
}
$object | Out-GridView
Write-Host
Write-Host
Write-Host
$runagain = Read-Host "Would you like to get another user's folder size?" | Out-String
Write-Host
Write-Host
}
while($runagain -like "y*")
Any help to get the $folders.Name to show as a list within the same out-Gridview would be great.
Thank you
You're probably looking for:
Name = $($folders.Name -join [Environment]::Newline)
This way you are not using an object anymore but are manually creating a list by joining the elements with a new line.
This question already has answers here:
Unable to Pause or Sleep after Select-Object
(2 answers)
Closed 3 years ago.
I tried to find the solution by myself but now I'm out of ideas. I wrote a script that I want to use to check if Erlang is installed on a machine:
# Check if a Software ins installed
function Check_Program_Installed($programName) {
$x86_check = ((Get-ChildItem "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall") |
Get-ItemProperty |
Where-Object {$_.DisplayName -like "*$programName*" } |
Select-Object -Property DisplayName, UninstallString)
if(Test-Path 'HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall')
{
$x64_check = ((Get-ChildItem "HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall") |
Get-ItemProperty |
Where-Object {$_.DisplayName -like "*$programName*" } |
Select-Object -Property DisplayName, UninstallString)
}
if ($x86_check -and $x64_check -eq $null){
write-host "$programName is not installed on this computer" -ForegroundColor Green
#continue
}
elseif ($x86_check -or $x64_check -ne $null){
write-host "On this computer is installed " -ForegroundColor Red
$x86_check
$x64_check
}
}
# Erlang check
Write-Host "Checking if Erlang exist " -NoNewline
Check_Program_Installed("Erlang")
Write-Host "The End: the script ends here" -ForegroundColor Yellow
But if I execute it as result the very last line is executed before Check_Program_Installed("Erlang"). Why PowerShell is not respecting the step priority?
Checking if Erlang exist On this computer is installed
The End: the script ends here
DisplayName UninstallString
----------- ---------------
Erlang OTP 21 (10.2) C:\Program Files\erl10.2\Uninstall.exe
Just add Format-Table to $x86_check and $64_check at the end. Link to answer.
# Check if a Software ins installed
function Check_Program_Installed($programName) {
$x86_check = ((Get-ChildItem "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall") |
Get-ItemProperty |
Where-Object {$_.DisplayName -like "*$programName*" } |
Select-Object -Property DisplayName, UninstallString) | Format-Table
if(Test-Path 'HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall')
{
$x64_check = ((Get-ChildItem "HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall") |
Get-ItemProperty |
Where-Object {$_.DisplayName -like "*$programName*" } |
Select-Object -Property DisplayName, UninstallString) | Format-Table
}
if ($x86_check -and $x64_check -eq $null){
write-host "$programName is not installed on this computer" -ForegroundColor Green
#continue
}
elseif ($x86_check -or $x64_check -ne $null){
write-host "On this computer is installed " -ForegroundColor Red
$x86_check
$x64_check
}
}
# Erlang check
Write-Host "Checking if Erlang exist " -NoNewline
Check_Program_Installed("Erlang")
Write-Host "The End: the script ends here" -ForegroundColor Yellow
I have tried copying your code and testing it, however I cannot make the actual Check_Program_Installed function work, so it is hard for me to validate.
However, for PowerShell it is important to understand the pipeline.
Normally with everything you do, it is send to the pipeline and will appear in your console in the order that the pipeline got it.
However Write-Host does not send your text to the pipeline, it sends it directly to the console, so it could be a simple race condition where the text gets to the console faster than the pipeline object.
If you try to test using Write-Output instead of Write-Host I would guess you get it in the correct order, since Write-Output sends an object to the console through the pipeline.
Could you guys please help me with the following scenario . Here is what i am trying to accomplish .
I generate a report of computers that need that need to be disabled in AD = file1.txt
I have a pre-made list of Computers to exclude
from getting disabled = file2.txt
I have a script to disable a list
of computers from a text file but i would like to exclude whatever
computer that exist in the file2.txt .
Here is what i have so far
$toBeDisabled = Import-CSV \\SERVER\file1.csv
$toBeExcluded = Import-CSV \SERVER\file2.csv
$toBeDisabled = $toBeExcluded | Where-Object {($toBeExcluded | Select-Object -ExpandProperty Name) -NotContains $_.Name}
ForEach ($Computer in $toBeDisabled.DeviceName)
{
$Computer = $Computer.Trim()
$ADComputer = Get-ADComputer $Computer -Properties Description
If ($ADComputer)
{
Add-Content c:\temp\computers.log -Value "The following PC $Computer has been found and disabled"
Set-ADComputer $ADComputer -Description "$($ADComputer.Description)- Disable due to inactivity - $(Get-Date) - by $env:UserName " -Enabled $False
}
Else
{ Add-Content c:\temp\computers.log -Value "$Computer not Found in Active Directory or Was disabled before"
}
}
Im getting the following error (Select-Object : Property "Name" cannot be found)
Thanks
The best approach here would be to just compare these two files first:
$toBeExcluded = Import-Csv C:\temp\file2.csv
$toBeDisabled = $toBeExcluded | Where-Object {($toBeExcluded | Select-Object -ExpandProperty Name) -NotContains $_.Name}
The above assumes that file2.csv has the same format (so it has property Name).
Then, instead of $Computers you just have to use $toBeDisabled in foreach.
I figured that out .
Compare-Object $file1 $file2 -Property "DeviceName" |
Where SideIndicator -eq "<=" |
Select DeviceName |
Export-Csv "\Server\DisableList.csv" -NoType
Thanks everyone for help
I'm trying to export some group memberships all to one CSV file so I can find users who are not in our domain. Everything works great, but when all the outputs get appended I can't see what group each entry is in. Here's what I have now.
$Groups = import-csv "C:\users\USER\desktop\secgroupinput2.csv"
foreach($item in $Groups)
{
Get-ADGroupMember -Server "SERVERDC" -Identity $item.directoryname | export-csv "C:\users\USER\desktop\realexport.csv" -Append
}
How can I add a row between appends with the group name, likely from the import?
Thanks!
I did something similar in the past. Hope this code helps :
Function ADGroupMembers
{
$group = get-content C:\Pshell\PM\group.txt
$i =25
do{
if (get-QADgroup $group[$i] -Empty 0)
{write-output ''; Write-Output -inputobject "The $($group[$i]) group members :"; write-output '';
get-QADGroupMember $group[$i] -IncludeAllProperties | Format-Table -AutoSize DisplayName, Type, Office, Company, Department, Title, WhenCreated | Out-String -Width 4096;
write-output ''}
else {Write-Output -inputobject "*** Member not found in the $($group[$i]) group!"; write-output ''}
$i +=1}
while ($i -ne $group.length)
}
ADGroupMembers | out-File 'c:\Pshell\PM\groupmemberdetails.txt'