import os import subprocess import re import time import _winreg blacklist = ['ProjectLibre'] def _find_uninstall_entries(keywords): uninstallkey = 'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall' if 'PROGRAMFILES(X86)' in os.environ.keys(): reg_list = [ (_winreg.HKEY_LOCAL_MACHINE, uninstallkey, _winreg.KEY_WOW64_32KEY | _winreg.KEY_READ), (_winreg.HKEY_LOCAL_MACHINE, uninstallkey, _winreg.KEY_WOW64_64KEY | _winreg.KEY_READ), ] else: reg_list = [ (_winreg.HKEY_LOCAL_MACHINE, uninstallkey, _winreg.KEY_READ), ] matches = [] for reg_key, sub_key, access in reg_list: try: reg = _winreg.OpenKey(reg_key, sub_key, 0, access) except WindowsError: continue i = 0 while True: try: key_value = _winreg.EnumKey(reg, i) except WindowsError: break path = os.path.join(sub_key, key_value) try: hkey = _winreg.OpenKey(reg_key, path, 0, access) except WindowsError: i += 1 continue try: dis_name, _ = _winreg.QueryValueEx(hkey, 'DisplayName') except WindowsError: dis_name = None if dis_name: dis_name = dis_name.strip() for keyword in keywords: if keyword.lower() in dis_name.lower(): try: uninstr, _ = _winreg.QueryValueEx(hkey, 'UninstallString') except WindowsError: uninstr = None matches.append([dis_name, uninstr, path]) break i += 1 return matches def _run_uninstall_string(uninstr): if not uninstr: return 1 if 'msiexec' in uninstr.lower(): guid = re.findall(r'\{[0-9A-Fa-f\-]+\}', uninstr) if not guid: return 1 cmd = ['MsiExec.exe', '/X' + guid[0], '/qn', '/norestart'] else: exe_match = re.findall(r'"[^"]+"', uninstr) exe_path = exe_match[0].strip('"') if exe_match else uninstr.strip() cmd = [exe_path, '/VERYSILENT', '/SUPPRESSMSGBOXES', '/NORESTART'] try: subprocess.check_call(cmd) return 0 except subprocess.CalledProcessError as e: return e.returncode except OSError: return 1 def _uninstall_all_matches(): matches = _find_uninstall_entries(blacklist) if not matches: return 0 overall = 0 for dis_name, uninstr, path in matches: rc = _run_uninstall_string(uninstr) if rc != 0: overall = rc time.sleep(5) return overall def spm_install(dir, args): os.chdir(dir) argslist = args.split() try: subprocess.check_call(argslist) print 'retcode' + str(0) + 'retcode' except subprocess.CalledProcessError as e: print 'retcode' + str(e.returncode) + 'retcode' def spm_uninstall(dir, args): overall = _uninstall_all_matches() print 'retcode' + str(overall) + 'retcode' def spm_update(dir, args): # Uninstall whatever version(s) are currently registered first # (handles the double-entry: both the MSI GUID key and the Inno key) _uninstall_all_matches() time.sleep(20) # Then install the new version added in the ITSM package os.chdir(dir) argslist = args.split() try: subprocess.check_call(argslist) print 'retcode' + str(0) + 'retcode' except subprocess.CalledProcessError as e: print 'retcode' + str(e.returncode) + 'retcode'