Convert PowerShell object to use it on a condition - powershell

$version = Get-Module SharePointPnPPowerShellOnline -ListAvailable | Select-Object Version | Format-Table -HideTableHeaders | Out-String
Write-Output $version
With this I can get my PowerShell version, how can I convert it to use it in an if-else condition as an integer for example?

I think you can better use the version as type [Version]. That way you can compare easily enough and/or make use of its properties Major, Minor, etc indivudually
$version = [Version](Get-Module -Name SharePointPnPPowerShellOnline -ListAvailable).Version
if ($version -ge [Version]'3.23.2007.1') {
# do something
}
else {
# do something else
}
Edit
As JosefZ commented, the above does not check for a returned value of $null (not installed).
Nor does it check for the possibility that the cmdlet can return an array of versions in case there are more versions of the same module installed.
To overcome situations like that, you could do:
$module = 'SharePointPnPPowerShellOnline'
$version = [Version](Get-Module -Name $module -ListAvailable).Version |
Sort-Object | Select-Object -Last 1
if ($version) {
Write-Host "Module is installed. Current version $($version.ToString())"
if ($version -ge [Version]'3.23.2007.1') {
# do something (or not because the wanted version or higher is already installed)
}
else {
# do something else, like installing newer module
}
}
else {
Write-Warning "Module '$module' is not installed"
# do something, like installing the module
}

Related

How to compare an item property to a string value

I am relatively new to PowerShell and cannot understand why my original attempts failed. I am attempting to validate the bit version of MS Office and perform actions off that. For whatever reason the strings were not comparing properly until I found a solution in the actual question here. Help understanding the difference between the two examples below would be much appreciated.
First attempt:
$getMSBitVersion= Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Office\ClickToRun\Configuration" | Select-Object -Property Platform
if( $getMSBitVersion -eq "x64" ){
Write-Host "true"
} else {
Write-Host "false"
}
Working solution:
$getMSBitVersion= (Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Office\ClickToRun\Configuration" -Name Platform).Platform
if( $getMSBitVersion -eq "x64" ){
Write-Host "true"
} else {
Write-Host "false"
}
My assumption is the first is outputting an object instead of string and thus the comparison cannot be done. If this is the case, is the working solution the only way/best way to do this?
Thank you Mathias and Abraham.
From what I gather, the following are confirmed methods on how to make the desired comparison.
1: This will scope into the object property of "Platform" by using dot notation and return the string value instead of the whole object.
$getMSBitVersion= (Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Office\ClickToRun\Configuration" -Name Platform).Platform
if( $getMSBitVersion -eq "x64" ){
Write-Host "true"
} else {
Write-Host "false"
}
2: This will take all the properties of the Path and pass through to Select-Object. Select-Object will take and expand the "Property" object and return it as a string.
$getMSBitVersion= Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Office\ClickToRun\Configuration" | Select-Object -ExpandProperty Platform
if( $getMSBitVersion -eq "x64" ){
Write-Host "true"
} else {
Write-Host "false"
}
I was unable to get this solution to function correctly, but should, in theory, work.
3: This, in theory, should work, but the two objects are recognized differently and do not compare as intended.
$getMSBitVersion= Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Office\ClickToRun\Configuration" | Select-Object -Property Platform
$test= #{Platform="x64"}
if( Compare-Object $getMSBitVersion $test ){
Write-Host "true"
} else {
Write-Host "false"
}

How to compare .net FW version number with number stored in variable

Super new here and to #Powershell. I'm making a script to check whether the .Net Framework version that is installed is greater than or equal to a version number stored in a variable.
The issue I have is when setting up the variable that filters down to the version number.
$installed = (Get-ChildItem 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\' | Get-ItemPropertyValue -Name Version | Where { $_.Version -ge $software }) -ne $null
I want to compare the .Net Framework Version found in
HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full
to whichever version is installed on a Windows 10 computer to see if it is greater than or equal. I've tried comparing the release number in the registry, but the Version is more relevant for what I'm doing.
I want to write a message to the console and to a text file
$software = '4.7.02053'
$installed = (Get-ChildItem 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\' | Get-ItemPropertyValue -Name Version | Where { $_.Version -ge $software }) -ne $null
If(-not $installed) {
"$software is NOT installed."| Out-File -FilePath C:\Pre-Req_Log.txt -append
Write-Host "'$software' is NOT installed.";
pause
} else {
"$software is installed."| Out-File -FilePath C:\Pre-Req_Log.txt -append
Write-Host ".Net FW '$software' is installed."
}
My expected result is to see '4.7.02053' is (or not) Installed in the text file and it be correct. It doesn't matter if it's equal, as long as it's that version or greater I will be happy.
To compare version numbers, don't compare them as strings, cast them to [version] (System.Version) and then compare them:
$refVersion = [version] '4.7.02053'
$installedVersion = [version] (Get-ItemPropertyValue -LiteralPath 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full' -Name Version)
if ($installedVersion -ge $refVersion) {
# installed
# ...
}
else {
# not installed
# ...
}
If you use these [version] instances inside an expandable string ("..."), you'll get the expected string representation, but note that outputting them as-is to the console or via Out-File / > will show a tabular display with the version-number components shown individually. To force the usual string representation, use enclosing "..." - e.g., "$refVersion", or call .ToString(), e.g., $refVersion.ToString()

Check if program is installed if so go to next powershell

I've googled and not found anything useful to me.
I have 4 msi files I want to install but would like to check if some of it is installed on the computer.
Example:
check if program 1 is installed, if not install it and go to and install program 2.
However if it's not installed, install it and go to program 2 and do the same test there.
Execute-MSI -Action Install -Path "$dirFiles\Program1"
Execute-MSI -Action Install -Path "$dirFiles\Program2"
Execute-MSI -Action Install -Path "$dirFiles\Program3"
Execute-MSI -Action Install -Path "$dirFiles\Program4"
If you know the GUID, you could test path the uninstall key. Also don't forget that if your OS is 64 bit, there will be the same key in WOW6432Node for 32 bit apps.
$uninstallkey = "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\"
$uninstall32key = "HKLM:\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\"
#Example 64-bit app
$app1guid = "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}"
if (!(Test-Path "$uninstallkey\$app1guid)) {Execute-MSI -Action Install -Path "$dirFiles\Program1"}
#Example 32-bit app
$app2guid = "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}"
if (!(Test-Path "$uninstall32key\$app2guid)) {Execute-MSI -Action Install -Path "$dirFiles\Program1"}
Without knowing anything about your applications, there are two easy options I can think of.
1) Read a log file, looking for a pattern / string - check 6 times (configure as needed) and fail if it doesn't complete. If it does, move on to the next install and do the same check
$LOGFILE = 'C:\Somewhere.log'
$Complete = 'no'
$Counter = 1
$max = 6
Start-Sleep 10
DO {
$Check = SELECT-STRING -pattern 'status: 0.' -path $logfile -quiet
write-host $Check
If (($Check) -eq $True) {
Set-Variable -name Complete -Value "yes"
}
Else {Set-Variable -name Complete -Value 'no'}
Write-host $Counter
Start-Sleep 20
$Counter++
}
while ($Complete -eq 'no')
If (($Counter) -eq $max) {
Throw 'Installation failed, check the error log'
}
Option 2)
If you know what directories it creates or even a file count, can do something like the above with count instead of a file read
$PRDIR = "D:\Folder"
If (($PRDIR.Count) -gt 2)
{
Do something
}
Else
{
Do something else
{
Hope that helps!
R
You can use WMI to check if your MSIs are installed or not. Example:
$products = Get-WmiObject -Class win32_product | Where-Object { $_.Name -like "*someName*" } | Select-Object *
You might extend the Where-Object clause with additional patterns to query for (e.g. via $_.Name -like "*Sw1*" -or $_.Name -like "*Sw2*" ). $products should be an array including the findings, which you can use to check if the requested SW is installed or not. Example:
PS> $found = $results.Where({ $_.Name -like "*sw1*"})
PS> if ($found) { Write-Host "Found" }
Hope that helps

Read registry settings recursively with Powershell

I'm trying to read recursively some registry settings with Powershell.
This is what I tried:
$registry = Get-ChildItem "HKLM:\Software\Wow6432Node\EODDashBoard\moveFilesOverflow" -Recurse
Foreach($a in $registry) {
Write-Output $a.PSChildName
$subkeys = (Get-ItemProperty $a.pspath)
Write-Output $subkeys.LastDateTime_EndScript
}
I would like to be able to list all the registry keys with their value, without knowning the registry keys.
With my script I have a variable $subkeys that contains objects I can access. (For example here I can access $subkeys.LastDateTime_EndScript)
However what I would like is to list all the registry keys with their value without knowing the registry keys in my script, ie something like this:
Foreach ($subkey in $subkeys) {
Write-Output $subkey.keyname
Write-Output $subkey.value
}
Is it possible?
Thanks,
You can loop through the properties. Using your idea that would be:
foreach ($a in $registry) {
$a.Property | ForEach-Object {
Write-Output $_
Write-Output $a.GetValue($_)
}
}
Output:
InstallDir
C:\Program Files\Common Files\Apple\Apple Application Support\
UserVisibleVersion
4.1.1
Version
4.1.1
....
That's pretty messy though. The usual way to output data like this in powershell is to create an object with properties for Name and Value so you have one object per registry-value. This is easier to process (if you're going to use it for something in the script) and easier to look at in console.
foreach ($a in $registry) {
$a.Property | Select-Object #{name="Value";expression={$_}}, #{name="Data";expression={$a.GetValue($_)}}
}
or
foreach ($a in $registry) {
($a | Get-ItemProperty).Psobject.Properties |
#Exclude powershell-properties in the object
Where-Object { $_.Name -cnotlike 'PS*' } |
Select-Object Name, Value
}
Output:
Value Data
----- ----
InstallDir C:\Program Files\Common Files\Apple\Apple Application Support\
UserVisibleVersion 4.1.1
Version 4.1.1
....

Powershell Check versions number of installed program

i'm trying to get this code to work, but i cant get the version to match - can you help?
$Version = Get-ChildItem hklm:\software\microsoft\windows\currentversion\uninstall | ForEach-Object {Get-ItemProperty $_.pspath} | Where-Object {
$_.PSChildName -Eq '{BFAE8D5B-F918-486F-B74E-90762DF11C5C}'} | Select-Object Version
Write-Host $Version
if ($Version -eq 67436760)
{
Write-Host "Version match"
}
else
{
Write-Host "Not Matched"
}
The problem is that you are trying to compare an object to an integer. Since it's the wrong data type you will always get False returned.
To fix this you simply need add .Version, like this:
if ($Version.Version -eq 67436760)
{
Write-Host "Version match"
}
else
{
Write-Host "Not Matched"
}
That will retrieve the integer inside the object instead of the object itself.
Best regards
you need to capture that version variable better and convert it to an interger. Use:
Write-Host $Version
[int]$Version=$Version.version