2

Probably a dumb question but, I'm just curious.

Is there a difference between Get-CIMInstance and Get-WMIObject when Invoking an Uninstall for an application under the Win32_Product class? Only reason I ask is because:

  • Using Get-CIMInstance to uninstall an application, will reboot my computer with certain programs.
  • Using Get-WMIObject to uninstall an application just runs without rebooting.

Also, piping a Get-Member to any Get-CIMInstance product, doesn't give me a method to uninstall but, it does using Get-WMIObject. Is this just how the developers wrote it? Although, Invoke-CIMMethod -Name Uninstall still works.

Get-CIMInstance / Uninstall

Heres what I was doing to uninstall multiple apps using Get-CIMInstance/Invoke-CIMMethod -Name Uninstall:

Get-CimInstance -ClassName win32_product | Where-Object Name -Match "Visual" | 
    ForEach-Object -Process { 
        Invoke-CimMethod -InputObject $_ -Name Uninstall 
                            }
#Methods Returned
<#
Get-CimInstance -ClassName win32_product | Where-Object Name -Match "Visual" | Get-Member -MemberType Method


   TypeName: Microsoft.Management.Infrastructure.CimInstance#root/cimv2/Win32_Product

Name                      MemberType Definition
----                      ---------- ----------
Clone                     Method     System.Object ICloneable.Clone()
Dispose                   Method     void Dispose(), void IDisposable.Dispose()
Equals                    Method     bool Equals(System.Object obj)
GetCimSessionComputerName Method     string GetCimSessionComputerName()
GetCimSessionInstanceId   Method     guid GetCimSessionInstanceId()
GetHashCode               Method     int GetHashCode()
GetObjectData             Method     void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Ser...
GetType                   Method     type GetType()
ToString                  Method     string ToString()
#>

Get-WMIObject / Uninstall

Get-WMIObject -ClassName win32_product | Where-Object Name -Match "Visual" | 
    ForEach-Object -Process { 
        Invoke-WMIMethod -InputObject $_ -Name Uninstall 
                            }
#Methods Returned
<#
Get-WMIObject -Class win32_product | Where-Object Name -Match "Visual" | Get-Member -MemberType Method


   TypeName: System.Management.ManagementObject#root\cimv2\Win32_Product

Name      MemberType Definition
----      ---------- ----------
Configure Method     System.Management.ManagementBaseObject Configure(System.UInt16 InstallState, System.UInt16 InstallLevel, S...
Reinstall Method     System.Management.ManagementBaseObject Reinstall(System.UInt16 ReinstallMode)
Uninstall Method     System.Management.ManagementBaseObject Uninstall()
Upgrade   Method     System.Management.ManagementBaseObject Upgrade(System.String PackageLocation, System.String Options)
#>

Pardon the long post, just a curious mind.

Please delete/close if not allowed.

Steven
  • 6,817
  • 1
  • 14
  • 14
Abraham Zinala
  • 4,267
  • 3
  • 9
  • 24

2 Answers2

6

There are lots of differences between using the WMI cmdlets and the newer CIM cmdlets. Get-WMIObject is deprecated in windows PowerShell and has been removed from PowerShell Core, so the general recommendation is to go with CIM. The methods shouldn't behave differently though, so I can't explain the reboot behavior you mentioned.

The objects returned by Get-CimInstance don't have the methods, but you can pass them to Invoke-CimMethod`.

$instance = Get-CimInstance win32_process -Filter "Name = 'powershell_ise.exe'"
$instance | Invoke-CimMethod -MethodName 'Terminate'

You can discover methods using Get-CimClass

(Get-CimClass win32_process ).CimClassMethods

If you need arguments for a given method they can be passed via the -Arguments parameter using a hash table as the argument. You can find examples in the help file or here

You can use Invoke-WMIMethod directly too:

Invoke-CimMethod -Query "SELECT * FROM Win32_Process WHERE Name = 'powershell_ise.exe'" -MethodName Terminate

I usually don't do it that way because it's a little less verbose to use -Filter with -CLassName, and -Filter is missing isn't available with Invoke-CimMethod However, these are just personal preferences.

I recommend you read Introduction to CIM Cmdlets as well

Also, Win32_Product has a bad reputation. If you google it you can get more information but here's an article I quickly found through SO questions: Why Win32_Product is Bad News

As a general rule you should move filtering left in the command. Use the -Query or -Filter parameters rather than getting all instances and using a Where{} afterward. Especially considering the known performance issues with Win32_Product.

Steven
  • 6,817
  • 1
  • 14
  • 14
  • Hello Steven!! Thanks for the answer. I am aware that `Get-Ciminstance` is the successor and I was trying to make it a little more legible without using WQL filtering(: I completely forgot about win32_products reconfiguration as it was my biggest take away from the article besides it being *"dog slow"* lol So in your opinion, do you think that its better to query the uninstall string from the registry to uninstall programs using Posh? I also was hoping someone knew why it would reboot with `Get-Ciminstance` and not with `Get-WMIObject`. – Abraham Zinala Apr 07 '21 at 01:36
  • Saw in the comments someone reference this link: http://csi-windows.com/toolkit/win32product-replacement. Seems that an alternative was found for win32_product uninstallation but, since its VBScript, I was having a hard time trying to understand what its really doing. Thank you for the links as well. Already halfway down "Introduction to CIM cmdlets". Really good read. – Abraham Zinala Apr 07 '21 at 01:37
  • Was completely unfamiliar with `Invoke-WMIMethod` being able to do what I needed from the get go without having to query for the applications using `Get-Ciminstance`. – Abraham Zinala Apr 07 '21 at 01:39
  • 1
    Withstanding the WMI/CIM specifics, if it were me I'd probably look up the uninstall string from the uninstall registry key, and run it separately, perhaps with some control and monitor functions around it. – Steven Apr 07 '21 at 03:51
  • https://blog.ipswitch.com/get-ciminstance-vs-get-wmiobject-whats-the-difference Good article on CIM vs WMI – DGM Sep 10 '21 at 17:53
2

Or using get-package, assuming it's an msi install:

get-package *visual* | uninstall-package

The win32_product class is notoriously slow as well, since it verifies all msi's when it's used.

js2010
  • 23,033
  • 6
  • 64
  • 66
  • Funny you mentioned that cause, I attempted `Uninstall-Package` with no luck. Was expecting for at least and error but, it does display anything and status still states installed. Even tried a reboot to see if it would uninstall but, had no luck either; still there. Uninstall strings in the registry didn't help either. – Abraham Zinala Apr 07 '21 at 03:48
  • 1
    For the particular issue of uninstalling I like this idea. but you would have to wrap it with PoSh remoting if you wanted to operate non-locally. – Steven Apr 07 '21 at 03:50