Get current version number of specified program - powershell

I started with this, on a recommendation from a friend
Get-WmiObject win32_product | ft name, version
But then I found this, which gives me pause.
A little research led me to this
wmic product where "Name='Revit 2018'" get name,version
Which works as far as the data gathered. And yes, I am looking for a different program in this example. in any case, once I had good info using WMIC I tried to get the data into a variable so I could get just the version number, but the data formatting is something I have never seen before. I was hoping for a simple solution, like
$object = wmic product where "Name='Revit 2018'" get name,version
$object.version
But only the result is an array with 6 items, and only one seems to be the actual data line, and that's a single line, not two properties. And, I really wonder if an old command line utility is the right answer here. If it really is the best way to do this, is there a trick to converting the raw data to something more, PowerShelly? And if it's not the best way to get this info, what is? Is that scary link real, or is Get-WmiObject win32_product actually safe? And if so, is there a way to filter on a specific name, to speed things up? And indeed, Get-WmiObject doesn't work as I was expecting, as
$object = Get-WmiObject win32_product | ft name, version
foreach ($item in $object) {
Write-Host "$($item.version)"
}
Doesn't work as expected at all.
EDIT: This seems to be working as expected, which is progress.
$version = (Get-WmiObject win32_product -filter:"Name = 'Revit 2018'" | Select-Object -property:*).version
Write-Host "$version!"
I guess the question is really, is this a safe and consistent approach, or is there a better one?

Why not use the registry?
Set-Location HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall
$app = Get-ChildItem | Where-Object { $_.GetValue("DisplayName") -match 'YourSoftware' }
$app.GetValue("DisplayVersion")
Or
Set-Location HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall
$apps = Get-ChildItem
foreach ($app in $apps) {
$app.GetValue("DisplayName","DisplayVersion")
}
Note: You'll also need to check the SysWow64 registry location as well
HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\
Note: Not all items will have a display version in which case you always have the option of looking in the installation directory for the executable itself, which should have a version on it.

Related

How to find a file location by file name, and file name only, using get_ciminstance in powershell?

I'm trying to write a script that will retrieve a specific file's properties across multiple computers. I was using get-childitem to do this until I realized that only retrieves locally. I've read that get-ciminstance can be used to do this for remote machines, however, all the examples I've seen use full paths to find the files. My script assumes the location could be anywhere on the C drive, so it only looks for the location based on the file's name. So far I've tried several variations of code using get-ciminstance, but all either produce nothing or have the wrong query structure.
Here's what I have right now, and it's what I believe is the closest to being correct, but I'm not sure:
Get-CimInstance -ComputerName $PC -ClassName CIM_DataFile | select Name | Where-Object { $_.Name -like "install.properties"}
If anyone can point me in the right direction, it would be greatly appreciated. Thank you.
Here's a nice link. https://community.idera.com/database-tools/powershell/powertips/b/tips/posts/accessing-individual-files-and-folders-remotely-via-wmi Name is the full path, with double backslashes. The filter language is like sql. You can't use invoke-command?
Get-CimInstance CIM_DataFile -Filter 'name = "c:\\users\\admin\\foo\\file.json"'

Problem with declaration of variables in powershell

I have declared 2 PowerShell variables
$prm=Get-WmiObject Win32_Product -Computer . -Filter "vendor = 'Wolters Kluwer Financial Services'" | Select-Object Name, Vendor, Version
$rgteng=Get-WmiObject Win32_Product -Computer . -Filter "vendor = 'WKFS'" | Select-Object Name, Vendor, Version
I want the output of this variable to a text file o/p #{Name=Wolters Kluwer Financial Services Regulatory Reporting FRA Param 11.2.0; Vendor=Wolters Kluwer Financial Services; Version=11.2.0}, I want this o/p to a text file.
I have tried using Write-Output and Write-Host, but none of them gives right o/p
What happens there looks like this (just the big picture):
Get-WmiObject Win32_Product -Computer . -Filter "vendor = 'Wolters Kluwer Financial Services'" creates an WMI object and pipes it to the next command
Select-Object Name, Vendor, Version transforms that object into a new PSCustom type object (more like a table version of your WMI object wtih only the desired information)
Then it gets messy :
if you use write-host or display it on the screen , the output will be formatted according the the powershell's settings (those settings can be changed by altering xml files)
if you use export-csv you basically use a convertto-csv | out-file c:\sometheing.txt + some formatting rules that are applied. (I think the UTF-8 type of the file is changed but I am not sure...)
So if you want to know exactly how your variable / file will look like, without having powershell formatting interfering with your work, use convertto-csv | out-file.

Pulling duplicate items from print server

I have a script that has two comboboxes. The first selects a location, the second populates depending on the first combobox selecteditem and displays available printer names for that location.
What I see happen more often than not is the list has duplicates of all of its items. Code below;
$Hospital = Get-Printer -ComputerName \\PrintServer | where {$_.Name -like “*Name*”}
$ComboBox_Location.Add_SelectedIndexChanged{
switch ($ComboBox_Location.SelectedItem){
"Hospital"{
$ComboBox_Printer.Items.Clear();
foreach($Name in $Hospital){
$ComboBox_Printer.Items.Add("$($Name.name)");
}
}
I can provide more code if it is needed. I believe the problem is in this particular code, but you can tell me otherwise. I also took out the ("$($Name.name)") and replaced it with "$Name.name", the following are results of the test;
MSFT_Printer(Name="PrinterName")
MSFT_3DPrinter(Name="PrinterName")
They were the same name. It was the duplicate. Is something needing a change in my print server?
Thanks in advance!
I found what was wrong. The devicetype was not defined. It needed to be;
$Hospital = Get-Printer -ComputerName \\PrintServer | where {($_.Name -like “*Name*”) -and ($_.DeviceType -eq "Print")}
This excluded any other types of devices (like the 3DPrinter) from populating in the list.

Powershell pipeline objects from import-csv headaches

We have a big audit coming up, and we want to be sure that all termed employees' AD computer accounts have been deactivated. I have a .csv that has a unique identifier that we use - our schema includes that ID in the middle of the ADcomputer Name property. I am having enormous trouble correctly piping the imported csv objects and their property to the filter. I think. I'm not entirely sure. This is something like what I've been trying.
Import-Csv termname.csv | ForEach-Object
{ Get-ADComputer -Filter { Name -Contains "$($_.id)" } } |
Export-Csv termcomp.csv -NoTypeInformation
This "script" pulled a total of no content, while I KNOW that when I test
Get-ADComputer -Filter { Name -Contains $id }
where $id is that unique ID, I get hits on AD Computer objects. Likewise, testing this block
Import-Csv termname.csv | ForEach-Object { Get-ADComputer { Name -Contains $_.id }
PowerShell's error is:
..."Property 'id' not found in object of type: 'System.Management.Automation.PSCustomObject'.
I think that I am misapprehending what precisely is an "object" in this case. Is the whole imported array an object, with a property of .id? Or is each row its own object, with a .id property? And, either way, why has PowerShell such strong objections to a pipeline object, which is, after all, its primary job?
Is there an entirely better way to go about this whole process? Am I somehow overthinking the whole mess?
UPDATE
As requested, sample contents of the csv file. Taking the suggestion to use wildcards instead, I've put the wildcards into the .csv itself, which, again, may not be the most elegant solution. But as long as it works! Here's the sample, copied from Notepad++
id
*rstarr56*
*jlennon58*
*pmcartney74*
*gharrison68*
So it looks like your CSV file does not have an "ID" heading in it, causing that not to be an available property, easy fix there is to confirm the contents of the CSV file, if everything looks correct try running Import-Csv termname.csv | ForEach-Object { Write-Host $_.id } to confirm that the property is coming across correctly. However you will also have trouble using -Contains here as that operator is meant to check if an array contains a particular value, you'll need to use Name -Like "*$($_.id)*"
After hours of digging, I found an answer here:
Import-CSV and Foreach to use Get-ADUser
Thanks especially to Mike for some great thinking about -Like and how to test the success of the code.
The line that ended up working was:
Import-Csv termname.csv | ForEach-Object {
Get-ADComputer -Filter "Name -Like '*$($_.id)*'"
} | Export-Csv termout.csv
Apparently, Powershell hates {{}}.
Thanks again, all!

Which is the most comprehensive way to check applied KBs to a Windows machine?

I am using Powershell to run a status of a list of KBs and see if they are applied or not.
I have found a few ways and I have seen inconsistencies with the numbers they are reporting. Which is right?
You can check SYSTEMINFO and get a list of hotfixes. You can also use the Get-Hotfix cmdlet, which is an alias for gwmi Win32_QuickFixEngineering or you can use wmic qfe list (WMI-CLI QuickFixEngineering List).
So, why am I getting different numbers when I do a quick count?
i.e. (Get-HotFix).Count and (wmic qfe list).Count
Using those two returns 153 and 310, respectively.
What gives? Why does it return different values? Are all of the applied KBs not listed in the Get-Hotfix cmdlet?
Before anyone asks, yes, I have restarted the machine and I haven't applied any since it was restarted and updated. That is Day 1 stuff...
WMIC has obscure blank lines which might be muddying the waters a bit. Here's simple, not very good, parser for wmic qfe (Windows 10 so who knows if it'll transpose).
The hope is that you can compare the lists.
$qfe = wmic qfe list brief | Select-Object -Skip 1 | Where-Object { $_.Trim().Length -gt 0 } | ForEach-Object {
[PSCustomObject]#{
Description = $_.Substring(0, 17).Trim()
HotFixId = $_.Substring(30, 10).Trim()
}
}
Compare-Object (Get-HotFix) $qfe -Property HotFixID -IncludeEqual
So is that enough? No, not really. QFE is great but indicative only. I'm trying to remember the circumstance that invalidates it. I'll come back to this.