none
Having trouble finding specific software in registry RRS feed

  • Question

  • Hi,

    I am having some problems finding installed instances of 7-Zip from the registry but the script is being designed so it could apply to any software titles.

    I have a task to remove all instances of 7-Zip lower than version 19.00 and then install version 19.00. I have found several devices that have more than version installed at once (usually two) so the script needs to look for all installed instances in the registry and remove them if lower than version 19.00. They might be installed using an MSI or EXE installer.

    I am building functions that are not too specific so I can reuse the code for other software remediation tasks. The code as written has some minor bugs but I would like to focus on the Get-SoftwareInstance function and the Detection/Uninstall scriptblocks.

    In the function I use $found to collect an array of objects and then return that result to the main script. If you inspect $found within the function, you will get a list of any 7-Zip instances found in the registry. Line 174 is where the call is made to the function and I'm attempting to return the results of the function to an array variable called $instances.

    I use foreach to inspect $instances to make a determination if any of the versions found need to be uninstalled (lower than 19.00). When I inspect $instance after Line 174, I am seeing every software in the registry path, not just 7-Zip. I don't really understand how the array contains only 7-Zip when within the function but outside of the function, there are dozens of software titles in the array. I have been looking for other examples but most of them only look for one instance of a software title.

    #######################
    ## Declare Functions ##
    #######################
    
    Function Append-ToLogFile([string]$messageForLog,[string]$pathToLog) {
    #Output to log file
        if($messageForLog -ne "") {
            Write-Output "$(Get-Date -Format G) - $messageForLog" | Out-File $pathToLog -Append
        } else {
            Write-Output " " | Out-File $logFile -Append
        }
    
    }
    
    Function Get-SoftwareInstances ([string] $title) {
    #Collect all installed instances of $title
    
    	#Declare variables
        $Keys = @("HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall",
                  "HKLM:SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall")
        
        $Found = @() #Array of 7-Zip objects
        
        #Iterate through the uninstall keys
        foreach($key in $Keys){
            
            #Iterate through each key under the uninstall key
            foreach($Child in (Get-ChildItem -Path $key)){
        
                #Collect the properties for the current key
                $Values = Get-ItemProperty -Path $Child.PSPath
        
                #Evaluate if the current key is 7-Zip
                if ($Values.DisplayName -match $title) {
        
                    #7-Zip was found
                    #Create an object with specific properties
                    $Object = [PSCustomObject]@{
                        DisplayName = $Values.DisplayName
                        DisplayVersion = $Values.DisplayVersion
                        UninstallString = $Values.UninstallString
                    }
        
                    #Add the 7-Zip object to array of objects
                    $Found += $object
        
                }
                
            }
        }
        
        return $found
    }
    
    Function Uninstall-Software([string]$removalString) {
    #Remove software (untested)
    
        #Test which which installer was used
        if($removalString.Substring(0,1) -eq "M") {
            #MSI installer was used to install software
            #Remove /I in the removal string; replace with /X
            Append-ToLogFile "Software installed with MSI." $logFile
            Append-ToLogFile "Rebuilding removal string with correct parameters." $logFile
            $removalString = $removalString -replace "/I", "/X "
            
            #Append silent switches to removal string
            $removalString = $removalString + " /qb"
            
            #Output new command line to log
            Append-ToLogFile "New string: $removalString" $logFile
            
            #Execute removal of software
            #NOTE: If File Explorer is running, MSI cannot uninstall
            
            
        } else {
            #EXE installer was used to install software
            #Append silent switch to removal string
            Append-ToLogFile "Software installed with EXE." $logFile
            Append-ToLogFile "Rebuilding removal string with correct parameters." $logFile
            $removalString = $removalString + " /S"
            
            #Output new command line to log
            Append-ToLogFile "New string: $removalString" $logFile
            
            #Execute removal of software
            Append-ToLogFile "Removing 7-Zip." $logFile
            & $removalString
        }
    
    }
    
    Function QuitNow([int]$retCode) {
    #Quit program with feedback
    
    	#Output blank line to log
    	Append-ToLogFile " " $logFile
    	
    	if ($retCode -eq 1) {
    		#A problem was encountered during execution
    		Append-ToLogFile "An error was detected." $logFile
    		Append-ToLogFile "The script is complete." $logFile
    		Exit 1
    	} else {
    		#No problems were encountered during execution
    		Append-ToLogFile "No errors were detected." $logFile
    		Append-ToLogFile "" $logFile
    		Append-ToLogFile "Script execution complete." $logFile
    		Exit 0
    	}
    }
    
    ###################
    ## End Functions ##
    ###################
    
    #==============================================================
    
    #################################
    ## Change Script Functionality ##
    #################################
    
    #Name of log file to be used
    $logFileName = "Upgrade_7-Zip.log"
    
    #Log intro appearing at the beginning of the log
    $logIntro = " - Begin 7-Zip Upgrade Process."
    
    #Use variable to make this script remove software only
    $uninstallOnly = $false
    
    #==============================================================
    
    #######################
    ## Declare Variables ##
    #######################
    $logFilePath = "$ENV:TEMP" + "\7-Zip"
    $logFile = "$logFilePath" + "\$logFileName"
    $software = "7-Zip"
    $instances = @()
    $installed = $false
    
    
    ####################
    ## Initialize Log ##
    ####################
    
    #Create log folder if it doesn't exist
    if (!(Test-Path $logFilePath)) {
        New-Item $logFilePath -type directory | Out-Null
    }
    
    #Initialize log file
    if (Test-Path $logFile) {
    	#File exists. Preparing for append.
    	Append-ToLogFile "" $logFile
    	Append-ToLogFile "====================================================================" $logFile
    	Append-ToLogFile "====================================================================" $logFile
    	Append-ToLogFile "" $logFile
    } Else {
    	#File doesn't exist; initializing.
    	Append-ToLogFile $logIntro $logFile
    	Append-ToLogFile "" $logFile
    }
    
    ###############
    ## DETECTION ##
    ###############
    
    #Get all instances of 7-Zip installed
    Append-ToLogFile "Searching for all instances of 7-Zip." $logFile
    $instances = Get-SoftwareInstances $software
    Append-ToLogFile "Version(s) installed:" $logFile #debug
    Append-ToLogFile $instances.DisplayVersion $logFile #debug
    
    #Evaluate results of installation detection
    Append-ToLogFile "Evaluating the results of software search." $logFile
    if($instances -ne $null) {
        #7-Zip was found to be installed
        Append-ToLogFile "7-Zip is installed." $logFile
    } else {
        #7-Zip is not installed
        Append-ToLogFile "7-Zip was not found. Terminating script." $logFile
        QuitNow 0
    }
    
    ###############
    ## UNINSTALL ##
    ###############
    
    #Determine if any software needs to be uninstalled
    Append-ToLogFile "Determine if any software needs to be removed." $logFile
    foreach($instance in $instances) {
    
        #Checking version installed
        if(($instance.DisplayVersion -notlike "19.00") -and ($instance.DisplayVersion -notlike "19.00.00.0")) {
            #The version detected is already the latest
            Append-ToLogFile "This instance is the latest version. No remediation required." $logFile
        } else {
            #This instance needs to be uninstalled
            Append-ToLogFile "Removing: $instance.DisplayName" $logFile
            Uninstall-Software $instance.UninstallString
        }
    }

    Thank you for your help!

    Rob

    Tuesday, August 6, 2019 5:29 PM

Answers

  • My recommendation is to load the script into the ISE, set breakpoints, and perform debugging.

    (It's outside the forum's scope to ask others to debug long scripts for you.)


    -- Bill Stewart [Bill_Stewart]

    • Marked as answer by robwm1 Tuesday, August 6, 2019 6:20 PM
    Tuesday, August 6, 2019 5:35 PM
    Moderator

All replies

  • My recommendation is to load the script into the ISE, set breakpoints, and perform debugging.

    (It's outside the forum's scope to ask others to debug long scripts for you.)


    -- Bill Stewart [Bill_Stewart]

    • Marked as answer by robwm1 Tuesday, August 6, 2019 6:20 PM
    Tuesday, August 6, 2019 5:35 PM
    Moderator
  • I have been doing that but I can't understand why the array looks correct within the function but entirely different outside of the function.

    I guess my main question is whether my Get-SoftwareInstances function is the correct approach or am I way off-base? Also, why does the function appear differently in two places?

    I'm not trying to ask anyone to do my job, I just need some advice so I can continue working on this. I can't find any good examples so far and now I'm a bit stuck at this point.

    Tuesday, August 6, 2019 5:45 PM
  • Break the script into pieces and proceed slowly. Watch the values of variables. See where values are coming from. If you think your problem is with a specific function, put that function into a separate script file and debug it independently of the rest of the script.


    -- Bill Stewart [Bill_Stewart]

    Tuesday, August 6, 2019 5:49 PM
    Moderator
  • Most of your issue was addressed in your original question but you ignored the answer and failed to provide any information:

    https://social.technet.microsoft.com/Forums/scriptcenter/en-US/1aff9d5b-3dff-4179-922a-3dcd4dd737c6/how-to-find-installed-software-and-collect-some-properties?forum=ITCG#b96566b1-3020-443e-8596-4b70c70b5242

    This is really just a duplicate of what you posted originally.

    Why write hundreds of lines of code to accomplish a simple task.  Just get the values and remove the components.

    As Bill has noted you will need to take this a small piece at  time.  I suggest starting by eliminate all code that is not completely necessary.  If you want to get fancy then add the fancy stuff after you can get the code working.


    \_(ツ)_/

    Tuesday, August 6, 2019 6:11 PM
  • I didn't ignore the answer. In that discussion, we were talking about finding one instance installed but I found out that there are multiple instances in the registry. The code our discussion was around doesn't support finding multiple instances.

    Sorry to waste your time.  :(

    Tuesday, August 6, 2019 6:20 PM
  • I didn't ignore the answer. In that discussion, we were talking about finding one instance installed but I found out that there are multiple instances in the registry. The code our discussion was around doesn't support finding multiple instances.

    Sorry to waste your time.  :(

    I directly addressed the issue of multiple copies. With 7Zip there can be two copies 32 and 64 bit. Why is that an issue.

    Again - start small and get the base code working before trying to get fancy.  If you have a snippet that is at issue post the snippet and a specific question.  Don't ask other to debug 100+ lines for you.  It will be much easier that way.


    \_(ツ)_/

    Tuesday, August 6, 2019 6:30 PM