import os import subprocess import time import re import _winreg def execute_command(command, cwd=None): try: process = subprocess.Popen( command, cwd=cwd, shell=True ) return_code = process.wait() return return_code except Exception: return -1 def get_mdaemon_uninstall_entries(): uninstall_key = r"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" entries = [] # Registry views registry_views = [] if hasattr(_winreg, "KEY_WOW64_32KEY"): registry_views.append(_winreg.KEY_WOW64_32KEY) registry_views.append(_winreg.KEY_WOW64_64KEY) else: registry_views.append(0) # Check HKLM and HKCU root_keys = [ _winreg.HKEY_LOCAL_MACHINE, _winreg.HKEY_CURRENT_USER ] for root in root_keys: for view in registry_views: try: access = _winreg.KEY_READ | view reg = _winreg.OpenKey( root, uninstall_key, 0, access ) except: continue index = 0 while True: try: subkey_name = _winreg.EnumKey(reg, index) index += 1 except: break try: subkey_path = uninstall_key + "\\" + subkey_name app_key = _winreg.OpenKey( root, subkey_path, 0, access ) try: display_name = _winreg.QueryValueEx( app_key, "DisplayName" )[0] except: display_name = "" try: display_version = _winreg.QueryValueEx( app_key, "DisplayVersion" )[0] except: display_version = "" try: uninstall_string = _winreg.QueryValueEx( app_key, "UninstallString" )[0] except: uninstall_string = "" # Detect MDaemon Connector if display_name and \ "mdaemon connector" in display_name.lower(): entries.append({ "display_name": display_name, "display_version": display_version, "uninstall_string": uninstall_string, "root": root, "subkey_path": subkey_path, "view": view }) _winreg.CloseKey(app_key) except: pass try: _winreg.CloseKey(reg) except: pass return entries def build_uninstall_command(uninstall_string): if not uninstall_string: return None command = uninstall_string.strip() if "msiexec" in command.lower() or \ "msiexec.exe" in command.lower(): command = re.sub( r'(?i)(\s|^)/I(?=\s|{)', r'\1/X', command ) # If /I was not replaced command = re.sub( r'(?i)/I(?=\{)', '/X', command ) # Silent uninstall command = command + " /qn /norestart" return command else: # MDaemon Connector uninstallers normally support /S command = command + " /S" return command def uninstall_mdaemon_connector(): entries = get_mdaemon_uninstall_entries() if len(entries) == 0: return True uninstall_success = True for entry in entries: display_name = entry["display_name"] display_version = entry["display_version"] uninstall_string = entry["uninstall_string"] print "Found MDaemon Connector: " + \ display_name + " " + display_version if not uninstall_string: print "Uninstall string not found for " + display_name uninstall_success = False continue command = build_uninstall_command(uninstall_string) if not command: print "Unable to build uninstall command" uninstall_success = False continue print "Uninstall command: " + command return_code = execute_command(command) # MSI standard success/reboot-required codes if return_code in [0, 3010, 1641]: print display_name + \ " " + display_version + \ " was successfully uninstalled." else: print display_name + \ " " + display_version + \ " uninstall failed. Return code: " + \ str(return_code) uninstall_success = False return uninstall_success def verify_mdaemon_removed(): time.sleep(5) entries = get_mdaemon_uninstall_entries() if len(entries) == 0: return True for entry in entries: print "MDaemon Connector still detected: " + \ entry["display_name"] + " " + \ entry["display_version"] return False def spm_install(dir, args): try: os.chdir(dir) argslist = args.split() return_code = subprocess.call( argslist, cwd=dir ) if return_code in [0, 3010, 1641]: print 'retcode0retcode' else: print 'retcode' + str(return_code) + 'retcode' except Exception as e: print 'retcode1retcode' def spm_uninstall(dir, args): try: os.chdir(dir) # First try the package uninstall command argslist = args.split() return_code = subprocess.call( argslist, cwd=dir ) if return_code in [0, 3010, 1641]: print 'retcode0retcode' else: print 'retcode' + str(return_code) + 'retcode' except Exception as e: print 'retcode1retcode' def spm_update(dir, args): print "Starting MDaemon Connector update..." uninstall_result = uninstall_mdaemon_connector() if not uninstall_result: print "Existing MDaemon Connector could not be removed." print "Update operation stopped." print 'retcode1retcode' return removed = verify_mdaemon_removed() if not removed: print "MDaemon Connector is still installed." print "New version will not be installed." print 'retcode1retcode' return print "Old MDaemon Connector version removed successfully." time.sleep(5) try: os.chdir(dir) argslist = args.split() print "Installing new MDaemon Connector version..." return_code = subprocess.call( argslist, cwd=dir ) if return_code in [0, 3010, 1641]: print "New MDaemon Connector version installed successfully." print 'retcode0retcode' else: print "New MDaemon Connector installation failed." print "Return code: " + str(return_code) print 'retcode' + str(return_code) + 'retcode' except Exception as e: print "Exception during new version installation." print 'retcode1retcode'