Scan list of PCs to uninstall software with a report

This topic contains 6 replies, has 5 voices, and was last updated by Profile photo of Nigel Tatschner Nigel Tatschner 6 months ago.

  • Author
    Posts
  • #38490
    Profile photo of nthnu
    nthnu
    Participant

    I'm new to Powershell and like what it can do, but I'm having issues trying to get it to do what I want lol.
    I'm trying to come up with a Powershell script to scan our domain for PCs that have any version of Quicktime installed. If it's found then uninstall, either way I'm looking to have it export to a log file with the computer name and if it was uninstalled or can't connect. The below script works, but it shows the GENUS info and there's nothing to identify it with the PC it was run on. If the software isn't on there, the script give me "You cannot call a method on a null-valued expression." on the second line. Any ideas? Thanks

    $app = Get-WmiObject -Class Win32_Product -ComputerName (Get-Content "C:\Users\name\Desktop\pstest\test2list.txt") | Where-Object {$_.Name -like “*Quicktime*”}
    $app.Uninstall() | Out-File C:\Users\name\Desktop\pstest\test2listout.txt
  • #38496
    Profile photo of Rob Simmers
    Rob Simmers
    Participant

    First, you should do a search, try "win32_product" and you will see results that start with evil, bad, alternatives, etc., because there are hidden issues using Win32_Product. Unfortunately, the alternatives without a management suite like SCCM, KACE, Altiris, Automation Manager, etc., are not going to be a couple lines of code. You can get installed software from registry and use WMI to create a process to uninstall the software. Take a look at this example:

    As for why you are getting the null error, there are numerous issues. The .Uninstall() method exists in the context of a single WMI object. When you run your WMI call against multiple computers, you are creating a collection of results. Additionally, you are returning ALL software and then filtering with WHERE, which would most likely convert these from WMI objects into Powershell objects, which do not have an UnInstall() method. Again, you should really avoid the Win32_Product class, but I want you to understand some basic concepts of how you would implement this:

    # Get a list of computers
    $computers = Get-Content "C:\Computers.txt"
    
    # Although you can pass a list of computers to Get-WMIObject, to call the method, WMI need to be connected to the
    # computer when calling it. So, we need to loop through each computer and connect
    foreach ( $computer in $computers ) {
        # Now here, I would normally ping the computer prior to connecting, but we're doing a high-level example.
        # We connect to the computer with WMI and our Filter is being done in WMI, so it will only return a result if
        # a product name contains quicktime. You want to filter as soon as possible and only return what you need.
        $quicktime = Get-WMIObject -Class Win32_Product -Filter "Name Like '%quicktime%'" -ComputerName $computer
        # Here, if you search a computer and quicktime is not installed, $quicktime will be null.  So, we need to 
        # check if the object is null before we attempt to call the method
        if ($quicktime) {
            "Found {0} on {1}" -f $quicktime.Name, $computer
            # if you look at the documentation for Win32_Product, the UnInstall() method returns 0 for success and
            # any other code would be a failure (except may 3010 which is reboot required), so we check the return
            $result = $quicktime.Uninstall()
            if ($result -eq 0) {
                "Uninstall successful on {0}" -f $computer
            }
            else {
                "Uninstall failed on {0}" -f $computer
            }
        }
        else {
            "Quicktime is not found on {0}" -f $computer
        }
    }
    
  • #41896
    Profile photo of nthnu
    nthnu
    Participant

    Thanks Rob! This will help me out.

  • #41968
    Profile photo of Andrew
    Andrew
    Participant

    nthnu,

    what infrastructure do you use to maintain your desktops? I love Powershell, and we had to get Quicktime Player out of the Domain ASAP due to the security bulletin.

    We used a one line SCCM Task sequence to remove it across 1500 desktops / laptops using the good old MsiExec /X switch. This comes with all the built in reporting.

    As some of the more experienced guys on this forum might say – pick your tool, sometimes Powershell, although awesome isn't the right tool for the job, if like me you needed Quicktime gone, and couldn't script this quickly – SCCM was sitting there all along for this specific task where I work.

  • #42005
    Profile photo of Nigel Tatschner
    Nigel Tatschner
    Participant

    Just Adding my 2 pence.

    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.

    If the users has a lot of applications installed this might take a while and could impact the users performance.

    Taken from https://msdn.microsoft.com/en-us/library/aa394378(v=vs.85).aspx

    Also, here is my take on it: http://tatux.co.uk/2015/03/20/get-ntsoftware/

  • #42029
    Profile photo of Jack Neff
    Jack Neff
    Participant

    After all that you still use Win32_Product in your script? Lol

    • #42219
      Profile photo of Nigel Tatschner
      Nigel Tatschner
      Participant

      I never once said I wouldn't use it, I just added more information. Why is that funny?

You must be logged in to reply to this topic.