Check if a program (Slack) is installed on a system? - windows

I would like to check whether Slack is installed on a system or not.
Even though it was installed both of the below two commands giving me blank, why is this?
System details are: Windows 10 64 bit.
$slack32 = Get-ItemProperty 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*' |
Select-Object DisplayName |
Select-String "Slack" |
Out-String
$slack64 = Get-ItemProperty 'HKLM:\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*' |
Select-Object DisplayName |
Select-String "Slack" |
Out-String

Slack by default installs under the User's directory, not Program Files, probably does the same in the registry hives.
Try HKCU:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*

Related

I'm a novice at Powershell and im trying to complete a task

I'm starting to work with Powershell and I've been doing some courses online. At this moment I'm stuck in a Challenge, I hope some good soul can help me with the instructions from the course.
Instructions are:
1-Find out what Windows features are installed on the server machine. (I'm remoting command to a computer named "Server")
2-Select only the data stored in the Name and InstallState columns.
3-Sort the data by the Name property in ascending (alphabetical) order.
4-Make sure the output format is set to table
5-Save the final output into a file called C:\features.txt on your desktop machine.
What I have come up with is this:
Invoke-Command -ComputerName Server -ScriptBlock{
>> Get-WindowsFeature | Select-Object -Property Name, InstallState | Sort-Object -Property Name | Format-Table
>> } | Out-File C:\features.txt
I have tried both with and without the select-object command since I know the format-table command works almost the same in this case. Thank u!
When ever I invoke a scriptblock on a remote computer i assign it to a variable and then handle the results this:
$myResults= Invoke-Command -ComputerName Server -ScriptBlock{…}
Foreach ($item in $myResults){
Write-host” $item.name /
$item.nstallState”
}
You use the pipeline rather excessively which is not wrong but for me personally still a beginner my self it is not easy to totally comprehend what each of them is exactly returning and forwarding to the next. Dont try to write a perfect line with several pips in the first attempt. Start with the smallest fastest fraction of the task. In this case yust get them all out without filter and pipelines. Then work your way from there, make little changes, use write-host to display the results and trail and error yourself to a deeper understanding of each of them. And then in the end u can chain them up.
As per my comment for example.
# 1-Find out what Windows features are installed on the server machine.
Get-WindowsFeature
# Results
<#
#>
# 2-Select only the data stored in the Name and InstallState columns.
Get-WindowsFeature |
Select-Object -Property Name, InstallState
# Results
<#
#>
# 3 - Sort the data by the Name property in ascending (alphabetical) order.
Get-WindowsFeature |
Select-Object -Property Name, InstallState |
Sort-Object -Property Name
# Results
<#
#>
# 4-Make sure the output format is set to table
Get-WindowsFeature |
Select-Object -Property Name, InstallState |
Sort-Object -Property Name |
Format-Table # though this is not needed, since table is the default for less than 5 properties.
# Results
<#
#>
<#
# 5-Save the final output into a file called C:\features.txt on your desktop
machine.
#>
Get-WindowsFeature |
Select-Object -Property Name, InstallState |
Sort-Object -Property Name |
Export-Csv -Path 'SomePathName' -NoTypeInformation -Append
# (I'm remoting command to a computer named "Server")
$Computers |
ForEach-Object {
Invoke-Command -ComputerName $PSItem.ComputerName -ScriptBlock{
Get-WindowsFeature |
Select-Object -Property Name, InstallState |
Sort-Object -Property Name |
Export-Csv -Path 'SomePathName' -NoTypeInformation -Append
}
}

Powershell - Get-Process's ProcessName is truncated on macOS

I'm using Powershell 7.2.5 on macOS 12.5.
I had Google Chrome open and ran Get-Process google*, and got truncated ProcessName:
gps google*
NPM(K) PM(M) WS(M) CPU(s) Id SI ProcessName
------ ----- ----- ------ -- -- -----------
0 0.00 626.36 5,529.29 33973 1 Google Chrome
0 0.00 124.94 2,870.73 33993 1 Google Chrome H
Google Chrome H should be Google Chrome Helper or something longer.
gps | sort-object {$_.ProcessName.length} showed that all processnames are truncated to 15 chars.
How do I make Get-Process output without truncation?
I read the help for Get-Process and tried to pipe the output to Format-Custom and Format-List ProcessName -Force, and none of these tricks worked.
Unfortunately, this is not a formatting problem:
At least up to the .NET version underlying PowerShell Core 7.3.0-preview.6, .NET , .NET 7.0.0-preview.6.22324.4, the .ProcessName property value is limited to 15 chars.
This is a known problem, and there is a known fix, but no one has stepped up to implement it yet - see GitHub issue #52860
A - computationally expensive - workaround is to use a call to the native ps utility, via a calculated property:
Get-Process google* |
Select-Object Id,
#{ n='ProcessName'; e={ Split-Path -Leaf (ps -p $_.Id -o comm=) }
Note: The above reports just the process ID and the (full) process name.
More work is needed if you want the same display columns as you would get by default, only with the full process names:
Get-Process google* | ForEach-Object {
$copy = $_ | Select-Object *
$copy.ProcessName = Split-Path -Leaf (ps -p $_.Id -o comm=)
$copy.pstypenames.Insert(0, 'System.Diagnostics.Process')
$copy
}

the installed date queried by power shell is null, which is a valid date listed by control panel [duplicate]

Is there an option to find installed software with the PowerShell? Mainly software is installed on a MSI basis. I tried it with the following code but I am not sure if it works reliable and for every software product. For example, 32- and 64-bit?
Get-ItemProperty HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* | `
Select DisplayName, DisplayVersion, Publisher, InstallDate | sort {[string]$PSItem}
Is there a reliable way to find every installed software?
You can find all information about installed software, updates and hotfixes with the following PowerShell commands:
try{
$InstalledSoftware = Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*
$InstalledSoftware += Get-ItemProperty HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*
} catch {
Write-warning "Error while trying to retreive installed software from inventory: $($_.Exception.Message)"
}
If I you want to find the installed MSI's, you could use the following:
$InstalledMSIs = #()
foreach ($App in $InstalledSoftware){
if($App.PSChildname -match "\A\{[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}\}\z"){
$InstalledMSIs += New-Object PSObject -Property #{
DisplayName = $App.DisplayName;
DisplayVersion = $App.DisplayVersion;
Publisher = $App.Publisher;
InstallDate = $App.InstallDate;
GUID = $App.PSChildName;
}
}
}
Also, you can check the installed Features on a Windows Server 2008 or higher OS with the following command:
Get-WindowsFeature -ErrorAction Stop | Where-Object {$_.Installed} | Sort-Object DisplayName
Surprisingly few people know about get-package. You can limit the output by programs or msi provider types. Uninstall-package works with msi installs. Otherwise you'll have to do something with $_.metadata['uninstallstring']. This stopped working in powershell 7.
get-package
Below command will give you all the details about all the installed softwares (I believe this is more reliable).
Get-WmiObject -Class Win32_Product

Check if program with specific version is installed

I'm trying to create a very simple script which would check if the a specific program is installed and if so return the version number for that program.
I've been able to get to the point where I'm running the script and able to return a binary value if a program is installed or not but not sure how to return the version number for that installed program.
What I will post will be just what I'm doing to return if program is installed, and need help in then attaining the version number.
function Check_Program_Installed {
$my_check = Get-ItemProperty HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* |
Select-Object DisplayName, DisplayVersion, InstallDate |
Format-Table -AutoSize |
Out-String
# Check if Google Chrome is installed
$my_check -Match "Google Chrome"
}
Check_Program_Installed
If you want that function to look for a specific installed program instead of returning a (table) formatted string, then you could simply do:
function Check_Program_Installed {
[CmdletBinding()]
Param(
[Parameter(Position = 0, Mandatory=$true, ValueFromPipeline = $true)]
$Name
)
$app = Get-ItemProperty -Path "HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*" |
Where-Object { $_.DisplayName -match $Name } |
Select-Object DisplayName, DisplayVersion, InstallDate, Version
if ($app) {
return $app.DisplayVersion
}
}
Check_Program_Installed "Google Chrome"
This will return $null when not found, or the version as string like 70.0.3538.67
Instead of doing the match after formatting the table, you could add a where to select the result you need beforehand and then obtain the DisplayVersion directly from that object. You could clean this up more to do exactly what you need, but here is your code modified to retrieve and display the number if the application is found. Try switching to a bad name to see the else result:
function Get-ApplicationVersion {
$applicationName = "Google Chrome"
$my_check = Get-ItemProperty HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* | Select-Object DisplayName, DisplayVersion, InstallDate | Where -Property DisplayName -Match $applicationName
$versionNumber = $my_check.DisplayVersion
if ($my_check) {
$versionNumber
}
else {
write-warning "Application not found"
}
}
Get-ApplicationVersion
EDITED: Renamed function name from Check_Program_Installed to use PS common verb Get, per suggestion.
function Get-InstalledProgram {
Param (
$ProgramName
)
$UninstallKeys = Get-ItemProperty HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*
if ( $ProgramName )
{
$UninstallKeys | Where-Object -Property DisplayName -Match -Value $ProgramName | Select-Object DisplayName, DisplayVersion, InstallDate
}
else
{
$UninstallKeys | Select-Object DisplayName, DisplayVersion, InstallDate
}
}
If you wanted to see all the programs, then you don't have to add a parameter. Just pipe its output to Format-Table. Format-Table does some weird just where the items are no longer the objects you're expecting, but table objects. Here is how I would handle that:
Get-InstalledProgram | Format-Table -Autosize
If you want to search for a program, add a parameter. You'll see above I added a parameter for ProgramName. It will match this term to the registry key's DisplayName.
PS C:\> Get-InstalledProgram -ProgramName Java
DisplayName DisplayVersion InstallDate
----------- -------------- -----------
Java 8 Update 181 8.0.1810.25 20180725
Java Auto Updater 2.8.181.13 20180925
If you wanted to just get the version, I would recommend just piping your output to Select-Object -ExpandProperty DisplayVersion
PS C:\> Get-InstalledProgram -ProgramName 'Java 8' | Select-Object -ExpandProperty DisplayVersion
8.0.1810.25
tl;dr
In Windows PowerShell[1] v5.1+, use the following (searches among both 32-bit and 64-bit installed programs, as shown in Control Panel):
Get-Package -ProviderName Programs -IncludeWindowsInstaller '*Google Chrome*' |
ForEach-Object Version
Note: The 32-bit-only HKEY_LOCAL_MACHINE:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall registry key may have more specific entries than what Control Panel shows - I'm unclear on why, but perhaps the composite view in Control Panel is sufficient.
Applied to your example:
PS> (Get-Package -ProviderName Programs -IncludeWindowsInstaller '*Google Chrome*').Version
70.0.3538.67
As for what you tried:
Since you're checking the Wow6432Node registry key branch specifically, you're checking installed 32-bit programs only.
As such, a better name for your function would be Check_32BitProgram_Installed or, more in line with with the function's intent, using an approved PowerShell verb, Get-32BitProgramVersion.
Alternatively, name, the function Get-ProgramVersion and look in both the 32-bit and 64-bit locations and process the results as shown in Theo's and Kevin M. Lapio's and Shawn Esterman's helpful answers:
Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*,
HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*
In line with the generic title of your question, the above is a solution that essentially searches the list of installed applications you would see in Control Panel > Programs > Programs and Features (appwiz.cpl), which covers both 32-bit and 64-bit applications:
Windows PowerShell v5.1 comes with the PackageManagement module and a Programs package provider[1] that allows inspecting installed programs via the Get-Package cmdlet; in PSv3 and PSv4, it is possible to manually install it.
To list installed programs (shown with abridged sample output):
PS> Get-Package -ProviderName Programs -IncludeWindowsInstaller
Name Version Source ProviderName
---- ------- ------ ------------
Git version 2.18.0 2.18.0 Programs
Microsoft Azure Compute Emu... 2.9.8699.20 Programs
Microsoft Azure Authoring T... 2.9.8699.20 Programs
# ...
The output objects are of type [Microsoft.PackageManagement.Packaging.SoftwareIdentity], which have .Name and .Version properties, which enables the solutions above.
The Programs package provider supports two dynamic options (options specific to that provider):
-IncludeWindowsInstaller is needed to make the list of programs reported match what Control Panel shows.
-IncludeSystemComponent, by contrast, reports components that do not show in Control Panel.
[1] Unfortunately, the underlying Programs package provider is not available in PowerShell Core on Windows as of v7.0 - and I'm unclear on whether that is a not-yet situation or whether it will never be - see GitHub issue #13225.

Grab the latest volume using PowerShell

I'm struggling trying to grab the latest volume/Drive using PowerShell
I have a result of a PowerShell look like this
PS C:\Users\me> Get-WMIObject Win32_Volume | select Name
Name
----
C:\
D:\
E:\
\\?\Volume{021a6bbd-0b97-4973-824a-7c635e362f09}\
\\?\Volume{bae1c1d6-59c3-44b1-9360-b7d3101c0e92}\
PS C:\Users\me>
If I want to access just this
E:
How can I filter out to :\ with the highest alphabetical order ?
I've been trying so many options using Select-String, but seems to get worse result.
The ones you want don't start with "\\". The drive letters may be returned in any order, so you need to sort them and take the last one:
Get-WMIObject Win32_Volume | Where-Object {$_.Name -NotLike '\\*'} | select Name | Sort-Object -Property Name | Select-Object -Last 1
Or, if the drive letter is known to be in the range A to Z, then it would be more sensible to use -Like '[A-Z]*' instead of -NotLike '\\*'.
Try something like this
Get-WMIObject Win32_Volume | where {$_.Name -eq "E:\"}
this should give you a list of objects wich you can access like an array. Also there is a lot of useful information here https://technet.microsoft.com/en-gb/library/2007.04.powershell.aspx

Resources