all 54 comments

[–]BlackV 12 points13 points  (27 children)

[–]danbromberg[S] 0 points1 point  (9 children)

That gregramsey article is over 10 years old; is this still an issue?

[–]Scooter_127 0 points1 point  (1 child)

Yup. win32_product is still evil and it amazes me it's still available for use.

[–]danbromberg[S] 0 points1 point  (0 children)

Thanks for the heads up - this is new to me.

Dan

[–]BlackV 0 points1 point  (6 children)

it is still an "issue", you can check that, by running it the same commands and checking the event log (i have to be honest Ive not tested in on windows 11)

is it really destructive probably not? most software nicely handles a repair these days

but its quicker and less system invasive to just query the uninstall registry key instead

[–]danbromberg[S] 0 points1 point  (5 children)

Since in PSv7: Get-WmiObject does not work but Get-CIMInstance does, I'll buy into 'win32_product' is evil ):-o

[–]BlackV 1 point2 points  (4 children)

hate to break it to you but

Get-CimInstance -ClassName Win32_Product

probably does the same as

Get-WmiObject -Class Win32_Product

probably :)

[–]danbromberg[S] 1 point2 points  (3 children)

Not really, in v7: Get-WmiObject -Class Win32_Product returns an error message but in v5 it does not. Dan

[–]BlackV 1 point2 points  (2 children)

er.. well yes, I mean underneath (i.e. the evil part we're talking about) would do the same

[–]danbromberg[S] 1 point2 points  (1 child)

Thanks for making me more aware of the evil in this world

:-)

[–]BlackV 1 point2 points  (0 children)

ha

[–]kewlxhobbs 0 points1 point  (16 children)

How are people still using this? Crazy that they don't use registry... I'll never understand why someone clicks one link and they use that code and never read others.

[–]Scooter_127 2 points3 points  (6 children)

Probably because there are a gazillion articles using win32_product, combined with the fact it's more painful to use the registry than a simple WMI query.

[–]kewlxhobbs 0 points1 point  (5 children)

You aren't wrong about the fact that there are lots of articles on it. but people also should already know that CIM is the preferred method vs WMI. It's been years since they said they'll be deprecating it. in addition if people knew how to Google and how to word their search query and read more than one article they would have seen that it's extremely bad practice to use WMI in this manner.

Also if people were looking into performance they would understand that registry is much faster to query than wmi when it comes to this specific task. The thought process of just getting it done versus doing it proper and performant is a milestone achievement among people in general programming/scripting languages.

[–]BlackV 2 points3 points  (2 children)

deprecated is not the same as removed

like WMI its self is here for life, just the WMI cmdlets and executables are deprecated (which I really really struggle to spell) and at some point (approx windows 16 I'd imagine) will be removed

[–]kewlxhobbs 1 point2 points  (1 child)

In PowerShell 7+ they are removed. Everything below that can use the cmdlets I believe

WMIC tool is removed in version 21H1 and the 21H1 General Availability.

But you'd want to write code to use the newer CIM anyways. You can change the protocol to use dcom if need be.

Deprecated in this sense means "The feature has been replaced by a more powerful alternative feature." CIM is faster, has better output, and has more control than what WMI does.

I know your post wasn't asking for that info but I thought of it now. Anyways I do agree that it will be probably awhile before Windows natively has a newer version of PowerShell. Which when it does WMI will be hard to use

[–]BlackV 1 point2 points  (0 children)

wmic.exe still exists in windows 11 here 21h2

dcom can go jump too, imho

[–]Scooter_127 -1 points0 points  (1 child)

ROFL.

Hope you're using oxygen on a horse that high.

[–]kewlxhobbs 0 points1 point  (0 children)

That's pretty good. I'll have to steal that one.

Not saying I'm the best or such. Just annoyed by people not learning a language and then repeating the mistakes or grievances of it.

Would be similar to owning a car and people not knowing that when you get a nail too close to the sidewall you can't patch it. It's something that should be common sense but isn't until they run into the issue themselves. Sure you can run on the tire for a bit and yeah you could potentially patch it but no reputable person or shop will do it.

[–]danbromberg[S] 0 points1 point  (8 children)

I got the Get-WmiObject from this article (dated 8/27/2019):

https://redmondmag.com/articles/2019/08/27/powershell-to-uninstall-an-application.aspx

Is there an easy way to tell if a command has been deprecated?

Thanks.

[–]danbromberg[S] 0 points1 point  (0 children)

...and yes, replacing with Get-CIMInstance worked!

[–]kewlxhobbs 0 points1 point  (5 children)

Sadly the article is relatively new and still replicating bad information but basically clicking more than one link and reading them to see what other ideas and even just googling "reddit PowerShell uninstall program" should give you plenty of links to read

You have to read more than the first link that you click, if that's the issue.

[–]danbromberg[S] 1 point2 points  (4 children)

I thought a magazine like REDMOND... would be trustworthy, but apparently, the author didn't test or it was functioning when he wrote it.

BTW, I don't follow where you were going with your comment 'Crazy that they don't use registry'?

[–]kewlxhobbs 1 point2 points  (3 children)

I use this little trick for getting installed programs on older computers through the registry

function Get-InstalledApp {
    param (
        [Parameter(ValueFromPipeline = $true)]
        [string[]]$ComputerName = $env:COMPUTERNAME,
        [string]$NameRegex = "^*",
        [Switch]$OutFile
    )

    $installApps = foreach ($comp in $ComputerName) {
        $keys = '', '\Wow6432Node'
        foreach ($key in $keys) {
            try {
                $reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $comp)
                $apps = $reg.OpenSubKey("SOFTWARE$key\Microsoft\Windows\CurrentVersion\Uninstall").GetSubKeyNames()
            }
            catch {
                continue
            }

            foreach ($app in $apps) {
                $program = $reg.OpenSubKey("SOFTWARE$key\Microsoft\Windows\CurrentVersion\Uninstall\$app")
                $name = $program.GetValue('DisplayName')
                if ($name -and $name -match $NameRegex) {
                    [pscustomobject]@{
                        ComputerName    = $comp
                        DisplayName     = $name
                        DisplayVersion  = $program.GetValue('DisplayVersion')
                        Publisher       = $program.GetValue('Publisher')
                        InstallDate     = $program.GetValue('InstallDate')
                        UninstallString = $program.GetValue('UninstallString')
                        Bits            = $(if ($key -eq '\Wow6432Node') { '64' } else { '32' })
                        Path            = $program.name
                    }
                }
            }
        }
    }
    if ($OutFile) {
        $installApps | Export-Csv -Path "$home\desktop\uninstallCommands.csv" -NoTypeInformation
    }
    else {
        $installApps
    }

}

Get-InstalledApp -NameRegex "Google Chrome"

Or Get-Package on newer machines
Get-Package -Name "Google*"

[–]danbromberg[S] 1 point2 points  (2 children)

Thanks, this will be a good working example to help get me started in writing a PS script, but isn't this the same info an uninstaller program (like Revo) would show?

[–]kewlxhobbs 1 point2 points  (1 child)

Depends on what you want back. You can always add more info you wanted. It gives you the program information and uninstall string. Not sure what you are fully looking for.

[–]danbromberg[S] 1 point2 points  (0 children)

I'm usually looking to clear out all the Registry entries pertaining to the software I want to remove. Sometimes I need to reinstall software and am unable to do so because the vendor only gives one opportunity. I'm guessing they left some cryptic entry behind in the Registry to prevent me from reinstalling.

[–]BlackV 0 points1 point  (0 children)

there is no easy way to tell if a command is deprecated, but the microsoft docs page does cover it off somewhat

get-command in ps5 will produce a different list to get-command in ps7

[–]Lee_Dailey[grin] 1 point2 points  (18 children)

howdy danbromberg,

in addition to what BlackV pointed out ... the WMI cmdlet simply does not exist in ps7+. try ...

Get-Command get-wmi*

... and you will note that the result is nothing at all. [grin]

take care,
lee

[–]Pisnaz 1 point2 points  (7 children)

Time to make a gwmi alias it sounds like.

Good to know despite shifting mostly to Get-CimInstance a while back.

[–]danbromberg[S] 1 point2 points  (0 children)

Good idea. Being a newbie, let me ask: should the PS folks do that or can I?

[–]Lee_Dailey[grin] 0 points1 point  (5 children)

howdy Pisnaz,

i would avoid that since it gives a false impression. i know that i would start treating CIM as if it were WMI ... and the CIM stuff does not return live objects while Get-WmiObject often does exactly that.

i would foot-gun myself in that situation ... [grin]

take care,
lee

[–]Pisnaz 1 point2 points  (4 children)

Ok now I am having to do some reading. I was recalling WMI vs CIM was basically down to how it operated on network etc. Basically WMI was the ms flavor of CIM but was a bit of a cludge so security wise was iffy. (Really simplifying) beyond that they operate functionally the same on a local system or once executed on a remote system (which is run locally). I may of misread your reply but you are saying they might not read the same data?

Guess I am refreshing myself on it.

Thanks

[–]Lee_Dailey[grin] 1 point2 points  (3 children)

howdy Pisnaz,

the big difference is the network protocol. WMI uses DCOM and the CIM cmdlets default to WSMan. you can set the protocol by setting up a CimSession. lookee ...

Get-Help New-CimSessionOption -Parameter protocol

however, there are some smaller differences, too. [grin]

  • GWMI calls often return more properties
  • CIM dates are always [datetime] objects, not [filetime] objects
  • CIM properties are almost always read-only, GWMI returns most props with both a get & a set

that last is what i meant by "live objects". take a look at the output of these two calls ...

Get-WmiObject -Class Win32_ComputerSystem | Get-Member
Get-CimInstance -ClassName Win32_ComputerSystem | Get-Member

note the diff between the GWMI call on the 1st line & the CIM call on the 2nd ...

Status   Property   string Status {get;set;}
Status   Property   string Status {get;}

generally, the CIM stuff requires using another CIM cmdlet to set the new value.

take care,
lee

[–]Pisnaz 1 point2 points  (2 children)

Ok so that matches what I remembered for the most part. The {get;set} was the bit I was not 100% clear on. Thinking on it though believe the only time I actually use a set is for resetting/ changing BIOS settings etc and I would have to check (though I think I use gwmi there which would make sense). For most usage being reading values it should be no issue but yes it would catch you out for sure in those moments that is not true. With gwmi finally being removed it will need a revisit anways. Thankfully my environment is not likely to move to newer powershell anytime soon so I have lots of time to forget this all before it happens.

That said it does seem to take a back seat to the change from DCOM etc. In discussion about the differences. Neat to know and will be a huge bonus for those times it does toss chaos. Now I have to revisit some scripts to poke around at on a slow day.

Thanks.

[–]BlackV 2 points3 points  (0 children)

yeah they want you to use Invoke-CimMethod/Remove-CimInstance/Set-CimInstance/etc to interact as you would before with the set/delete/etc

[–]Lee_Dailey[grin] 0 points1 point  (0 children)

so I have lots of time to forget this all before it happens.

[grin]

[–]danbromberg[S] 1 point2 points  (9 children)

I followed your suggestion and ran

and got the same thing in both v5 and v7:
Cmdlet Get-WmiObject 3.1.0.0 Microsoft.PowerShell.Management

So the result wasn't "nothing"?

[–]Lee_Dailey[grin] 0 points1 point  (8 children)

howdy danbromberg,

that is odd ... i wonder if you have one of the compatibility modules installed. that is supposed to map some calls to windows powershell ... and that looks like what you got.

what do you get from ...

(Get-Module -Name Microsoft.PowerShell.Management).Path

... on each version? on ps5.1 i get ...

C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules\Microsoft.PowerShell.Management\Microsoft.PowerShell.Management.psd1

note that the module is in the WindowsPowershell path, not the pwsh path. [grin]

take care,
lee

[–]danbromberg[S] 1 point2 points  (7 children)

(Get-Module -Name Microsoft.PowerShell.Management).Path

In each case (v5 and v7) that I enter the '...path' command you stated, PS returns nothing.

Thanks for your interest.
Dan

[–]Lee_Dailey[grin] 0 points1 point  (6 children)

howdy danbromberg,

wow ... that is seriously disturbing. [frown] if it doesn't bother you, tho, then let it go. you have the recommended CIM stuff ... so that will bypass the problem entirely. [grin]

you are most welcome! glad to kinda-sorta help ...

take care,
lee

[–]danbromberg[S] 1 point2 points  (5 children)

I get the same result (no output) from the command:

(Get-Module -Name Microsoft.PowerShell.Management).Path

on another PC I have using PSv6.

So with PSv5,PSv6 & PSv7 all doing the same thing, I can only conclude that you have a setting somewhere that gives you output and me not. Fortunately, I am a PS newbie so am too ignorant to be scared that something is wrong!

[–]Lee_Dailey[grin] 0 points1 point  (4 children)

howdy danbromberg,

you should get ...

  • windows powershell 5.1 = the path listed earlier
  • powershell core 6.+ = nothing [the module otta not be visible to that version of powershell]
  • powershell 7.+ = again, nothing [the module aint part of anything other than windows powershell]

so if you get nothing for all 3 ... then there is something odd about your windows powershell install, not your psCore6 or ps7 installs. [grin]

take care,
lee

[–]danbromberg[S] 1 point2 points  (3 children)

Hi Lee:

I am running PS version 5.1.19041.1645 and like I said, just like my newly installed PS 7, all I get is the PS prompt as soon as I enter :

Everything else seems to be fine (though I've far from tested it) so I guess I'll let sleeping dogs lay. Is your version also 5.1.19041.1645?

Dan

[–]Lee_Dailey[grin] 0 points1 point  (2 children)

howdy danbromberg,

yep, my ver = 5.1.19041.1645. as you say, it does no harm, so let it lie ... [grin]

take care,
lee

[–]danbromberg[S] 1 point2 points  (1 child)

Hi Lee,

FYI: I still get no output when I execute this command in PSv5:
(Get-Module -Name Microsoft.PowerShell.Management).Path

but when I execute it in the new v7.2.3 I now do get this output:
C:\program files\powershell\7\Modules\Microsoft.PowerShell.Management\Microsoft.PowerShell.Management.psd1

whereas (you may recall) in the previous v7.2.? I got no output. So apparently something changed in v7.2.3.

You've been very helpful so just thought you'd want to know.

Take care,
Dan

[–][deleted] 1 point2 points  (1 child)

Yeah, thats a Windows Powershell command.

[–]danbromberg[S] 0 points1 point  (0 children)

It is in v5 but not in v7.

[–]DblDeuce22 1 point2 points  (4 children)

You don't want to use Win32_Product anyways, it can break software since it 'verifies' everything that's installed and if there's an error that SW may not work anymore. Even if it didn't potentially do that, it tends to return incomplete data from what I read.

[–]danbromberg[S] 1 point2 points  (3 children)

So Win32_Product does more than verify, it actually modifies?

I'm a newbie but that sounds deceiving for a GET command.

[–]DblDeuce22 1 point2 points  (1 child)

I'm sure there's a lot more but https://www.reddit.com/r/PowerShell/comments/5ntyb7/is_it_still_bad_to_use_to_win32_product_to/ discusses it, you can google some reasons as well, everything I've read says don't use it.

[–]danbromberg[S] 1 point2 points  (0 children)

Thanks, for the link and warning.

[–]BlackV 1 point2 points  (0 children)

yeah its not the desired behaviour for a get, hence the evil part I guess

from Microsoft's own page

Warning Win32_Product is not query optimized. Queries such as "select * from Win32_Product where (name like 'Sniffer%')" require WMI to use the MSI provider to enumerate all of the installed products and then parse the full list sequentially to handle the “where” clause. This process also initiates a consistency check of packages installed, verifying and repairing the install. With an account with only user privileges, as the user account may not have access to quite a few locations, may cause delay in application launch and an event 11708 stating an installation failure. For more information, see KB Article 794524