Editing a Custom Uninstall Package in SVM

Editing a Custom Uninstall Package in SVM

Summary

Information regarding editing an uninstall package in the Flexera Software Package System.

Synopsis

The script below is generated in instances where we do not have a built-in uninstaller available for the product in question. The example provided is for Adobe Air, but this method will work for any application that stores uninstaller information in the following registry locations on client machines: 

HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall 

or

 HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall

There will be a folder in one of these locations that is named after the product, ultimately that's what the script will be hunting for in order to get the uninstall information.

Discussion

The full uninstall script example is below, but the two variables you need to worry about adjusting are arrays named ProductRegExps and silentParams.

var ProductRegExps = ['product name here']; 

This array needs to contain the name from the registry folder mentioned above. The way the script is written you can also put multiple product names here (you'll need to separate them with commas). An example of that would look like this:

var ProductRegExps = ['product name here', 'other product name here' ];

As a matter of practice, you'll likely want to keep it to one product per uninstall the package, however, some products might have different versions available for uninstalling with different folders in the registry.

var silentParams = ['/S' ];

In the example here you'll see that I've used the '/S' flag which is fairly commonly used for uninstalling executables. This is used to set the mode for the uninstall to be silent, so if the product in question uses a different flag for this you'll need to adjust accordingly.

One thing that's incredibly important about this variable is that it must have the same number of arguments as the ProductRegExps array. The order is also critical as the for loop that extracts these values uses the same integer value for the index for both variables when matching them up. The actual script can be found by checking the 'edit package content' checkbox in the first step of the SPS wizard.

User-added image
User-added image
User-added image

 

Full Script Example

var Title = "Uninstall Adobe AIR 17.x, version 19.x";
var GUID = "3ecc9774-202b-4af2-9ca0-f0320b616f09";
var ProductRegExps = ['Adobe AIR'];
var silentParams = ['/S'];
var optionalParams = "";
 
// The following three variables have been embedded by the CSI at the
// start of this script
// var GUID = "";
// var Title = "";
// var ProductRegExps = [];
// var silentParams = [];
// var optionalParams = "";
 
// Define some of our constants for registry keys and paths we will need
var rootKeys = [
  0x80000001, // HKEY_CURRENT_USER
  0x80000002  // HKEY_LOCAL_MACHINE
];
var regPaths = [
  "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\",
  "Software\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\"
   // For 32bit programs installed on a 64bit machine
];
 
function main() {
  try {
    if ( !GUID ) {
      server.logMessage( "No GUID supplied for package " + Title );
      return 1;
    }
    server.logMessage( "Running package " + Title + " [Uninstall]" );
    server.logMessage( "NOTE: This package will uninstall all instances found on this machine for the specified package" );
 
    if ( ProductRegExps.length > silentParams.length ) {
      server.logMessage( "Insufficient silent params provided for products." );
      return 1;
    }
 
    // For each product call our uninstall function with its respective
    // silent parameters
    var productRegExp, params;
    for ( var i = 0; i < ProductRegExps.length; i++ ) {
      productRegExp = ProductRegExps;
      params = silentParams;
 
      server.logMessage( "Uninstalling product # " + (i+1) + ", regexp: \"" + productRegExp + "\"" );
      uninstallAllInstances( productRegExp, params );
    }
  } catch ( ex ) {
    server.logMessage( "Error: (" + ex.number + ") in main(), description: " + ex.description );
    return 1;
  }
  server.logMessage( "Finished running package " + Title );
  return 0;
}
 
// Function to uninstall a given product based on it regular expression
// and the passed in parameters
function uninstallAllInstances ( productRegExp, params ) {
  var rootKey, regPath;
  for ( var i = 0; i < rootKeys.length; i++ ) {
    rootKey = rootKeys;
    for ( var j = 0; j < regPaths.length; j++ ) {
      regPath = regPaths;
      server.logMessage( "Searching [ RootKey: " + rootKey.toString( 16 ) + " , Path: " + regPath + " ]" );
      uninstall( productRegExp, rootKey, regPath, params );
    }
  }
}
 
function uninstall ( productRegExp, rootKey, regPath, params ) {
  try {
    var productNames = findProductNames( productRegExp, rootKey, regPath );
    var command ="";
    var productName;
    if ( productNames.length > 0 ) {
      for ( var i = 0; i < productNames.length; i++ ) {
         productName = productNames;
         command = getUninstallCommand( productName, rootKey, regPath );
         if ( command !== "" ) {
           runUninstallCommand( command, params );
         } else {
           server.logMessage( " No uninstall command for [ RootKey: " + rootKey.toString( 16 ) + " , Path: " + regPath + ", ProductName:"+ productName + " ]" );
         }
      }
    }
  } catch ( ex ) {
    server.logMessage( "Error in uninstall(), description: " + ex.description );
  }
}
 
function runUninstallCommand ( command, params ) {
  try {
    if ( command && params ) {
      command += " " + params;
    }
 
    command += " " + optionalParams;
    server.logMessage( "Executing:            " + command );
 
    // Executing
    var shell = new ActiveXObject( "WScript.Shell" );
    var exec = shell.Exec( command );
    var maxTime = 1 * 3600 * 1000; // 1 hour
    var start = (new Date()).valueOf();
    // Check in every second until we return with success or an hour is up.
    while ( exec.Status == 0 && (new Date()).valueOf()-start < maxTime ) {
      server.sleep( 1000 );
    }
    if ( exec.Status == 0 ) {
      server.logMessage( "Executed:          " + command + ", Did not finish within 1 hour." );
    } else {
      server.logMessage( "Executed:          " + command + ", exit code: " + exec.ExitCode );
      shell.RegWrite( "HKLM\\Software\\Secunia\\Updates\\Installed\\" + GUID + "\\", Title );
    }
  } catch ( ex ) {
    server.logMessage( "Error: (" + ex.number + ") in runUninstallCommand(), command: \"" + command + "\", description: " + ex.description );
  }
}
 
function findProductNames( productRegExp, rootKey, regPath ) {
  var productList = getInstalledSoftware( rootKey, regPath );
  // return an array of all product names that match the regexp
  var res = [];
  if ( productList.length > 0 ) {
    for ( var i = 0; i < productList.length; i++ ) {
      if ( productList.match( productRegExp ) ) {
        server.logMessage( "Found Product Name:'"+ productList +"' " );
        if ( res !== "" ) {           res.push( productList );
        }
      }
    }
  } else {
    server.logMessage( "Did not find installed software using:[ RootKey: " + rootKey.toString( 16 ) + " , Path: " + regPath + " ]" );
  }
  return res;
}
 
function getInstalledSoftware ( rootKey, regPath ) {
  try{
                var oCtx = new ActiveXObject("WbemScripting.SWbemNamedValueSet");
    oCtx.Add("__ProviderArchitecture", 64);
    oCtx.Add("__RequiredArchitecture", true);
 
    var locator = new ActiveXObject("WbemScripting.SWbemLocator");
    var services = locator.ConnectServer(null, "root\\default",null,null,null,null,null,oCtx);
    var registry = services.Get("StdRegProv");
    var Method = registry.Methods_.Item("EnumKey");
    var params = Method.InParameters.SpawnInstance_();
    params.hDefKey = rootKey;
    params.sSubKeyName = regPath;
 
    var output = registry.ExecMethod_(Method.Name, params);
    try {
      return output.sNames.toArray();
    } catch ( ex ) {
      return [];
    }
  } catch( ex ) {
    server.logMessage( "Error: (" + ex.number + ") in getInstalledSoftware(), description: " + ex.description );
    return [];
  }
}
 
function getUninstallCommand ( software, rootKey, regPath ) {
  try{
                var oCtx = new ActiveXObject("WbemScripting.SWbemNamedValueSet");
    oCtx.Add("__ProviderArchitecture", 64);
    oCtx.Add("__RequiredArchitecture", true);
    server.logMessage( "Obtaining uninstall command for "+ software );
    var locator = new ActiveXObject("WbemScripting.SWbemLocator");
    var services = locator.ConnectServer(null, "root\\default",null,null,null,null,null,oCtx);
    var registry = services.Get("StdRegProv");
    var Method = registry.Methods_.Item("GetStringValue");
    var params = Method.InParameters.SpawnInstance_();
    params.hDefKey = rootKey;
    params.sSubKeyName = regPath + software;
    params.sValueName = "UninstallString";
    var output = registry.ExecMethod_(Method.Name, params);
    if ( output.sValue ) {
      server.logMessage( "Found uninstall command ["+ regPath + software + "] = '" + output.sValue + "'");
      return output.sValue;
    } else {
      server.logMessage( "Found empty uninstall command ["+ regPath + software + "]");
      return "";
    }
  } catch( ex ) {
    server.logMessage( "Error: (" + ex.number + ") in getUninstallCommand(), description: " + ex.description );
    return "";
  }
}
 
// Execute the script
server.setExitCode( main() );
server.logMessage( "Returning " + server.getExitCode() );




Labels (4)
Was this article helpful? Yes No
No ratings
Version history
Revision #:
4 of 4
Last update:
‎Sep 19, 2019 06:52 PM
Updated by:
 
Contributors