import os import subprocess import ctypes import ssl import time from urllib2 import Request, urlopen BC_INSTALLER_URL = "https://cdn-patchportal-one.comodo.com/portal/packages/spm/Beyond%20Compare/x64/BCompare-5.2.2.32209.exe" class disable_file_system_redirection: _disable = ctypes.windll.kernel32.Wow64DisableWow64FsRedirection _revert = ctypes.windll.kernel32.Wow64RevertWow64FsRedirection def __enter__(self): self.old_value = ctypes.c_long() self.success = self._disable(ctypes.byref(self.old_value)) def __exit__(self, type, value, traceback): if self.success: self._revert(self.old_value) def ecmd(command): with disable_file_system_redirection(): process = subprocess.Popen( command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) out, err = process.communicate() return out.strip() + err.strip() def get_bc_uninstall_strings(): uninstall_list = [] reg_paths = [ r'HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall', r'HKLM\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall' ] for reg_path in reg_paths: cmd = 'reg query "%s" /s /f "Beyond Compare" ' % reg_path result = ecmd(cmd) lines = result.splitlines() current_key = "" for line in lines: line = line.strip() # Registry Key if line.startswith("HKEY_"): current_key = line # Display Name Check if "DisplayName" in line and "Beyond Compare" in line: uninstall_query = 'reg query "%s" /v "QuietUninstallString"' % current_key uninstall_result = ecmd(uninstall_query) uninstall_lines = uninstall_result.splitlines() for uline in uninstall_lines: if "QuietUninstallString" in uline: parts = uline.split("REG_SZ") if len(parts) > 1: uninstall_string = parts[1].strip() uninstall_list.append(uninstall_string) return uninstall_list def spm_uninstall(dir, args): uninstall_strings = get_bc_uninstall_strings() if not uninstall_strings: return for uninstall_cmd in uninstall_strings: try: # Add silent switches if not present if "/VERYSILENT" not in uninstall_cmd.upper(): uninstall_cmd += " /VERYSILENT" if "/SUPPRESSMSGBOXES" not in uninstall_cmd.upper(): uninstall_cmd += " /SUPPRESSMSGBOXES" if "/NORESTART" not in uninstall_cmd.upper(): uninstall_cmd += " /NORESTART" print("Running Uninstall:", uninstall_cmd) ecmd(uninstall_cmd) time.sleep(15) except: pass def download_installer(file_path, url): headers = {'User-Agent': 'Mozilla/5.0'} request = Request(url, headers=headers) try: context = ssl._create_unverified_context() response = urlopen(request, context=context) with open(file_path, 'wb') as f: while True: chunk = response.read(1024 * 100) if not chunk: break f.write(chunk) return True except: return False def spm_install(dir, args): temp_path = os.environ.get("TEMP", "C:\\Windows\\Temp") file_name = BC_INSTALLER_URL.split("/")[-1] local_path = os.path.join(temp_path, file_name) if not download_installer(local_path, BC_INSTALLER_URL): return install_cmd = '"%s" /SP- /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /ALLUSERS' % local_path print("Running Install:", install_cmd) ecmd(install_cmd) time.sleep(25) try: os.remove(local_path) except: pass def cleanup_old_registry(): reg_paths = [ r'HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall', r'HKLM\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall' ] for reg_path in reg_paths: cmd = 'reg query "%s"' % reg_path result = ecmd(cmd) lines = result.splitlines() for line in lines: line = line.strip() if "BeyondCompare4_is1" in line: delete_cmd = 'reg delete "%s" /f' % line ecmd(delete_cmd) def spm_update(dir, args): # Remove all old versions spm_uninstall(None, None) time.sleep(20) cleanup_old_registry() time.sleep(5) spm_install(None, None)