import os import ctypes import subprocess import time import _winreg as reg 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) UNINSTALLERS = [ r"C:\Program Files (x86)\Bitvise SSH Client\uninst.exe", r"C:\Program Files\Bitvise SSH Client\uninst.exe" ] KEY_PATH = r"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" WOW_PATH = r"SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall" def find_uninstaller(): for u in UNINSTALLERS: if os.path.exists(u): return u return None def bitvise_registered(): # True if "Bitvise SSH Client ..." entry still exists in Uninstall keys for path, flag in ((KEY_PATH, reg.KEY_WOW64_64KEY), (WOW_PATH, reg.KEY_WOW64_32KEY)): try: main = reg.OpenKey(reg.HKEY_LOCAL_MACHINE, path, 0, reg.KEY_READ | flag) except Exception: continue try: for i in range(reg.QueryInfoKey(main)[0]): try: sub = reg.OpenKey(main, reg.EnumKey(main, i), 0, reg.KEY_READ | flag) try: name = reg.QueryValueEx(sub, "DisplayName")[0] if name.startswith("Bitvise SSH Client"): return True finally: reg.CloseKey(sub) except Exception: continue finally: reg.CloseKey(main) return False def uninst_running(): try: p = subprocess.Popen('tasklist /FI "IMAGENAME eq uninst.exe" /NH', shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) out = p.communicate()[0] return 'uninst.exe' in out.lower() except Exception: return False def kill_bitvise(): for proc in ("BvSsh.exe", "BvSshClient.exe"): os.system('taskkill /f /im "%s" >nul 2>&1' % proc) def spm_uninstall(dir, args): with disable_file_system_redirection(): uninst = find_uninstaller() # Already removed -> success if uninst is None and not bitvise_registered(): print 'retcode' + str(0) + 'retcode' return if uninst is None: # registry entry exists but no uninstaller file print 'retcode' + str(1) + 'retcode' return kill_bitvise() try: # Exit code is ignored: parent uninst.exe returns 1 while the child keeps working subprocess.call('"%s" "BvSshClient" -unat' % uninst, shell=True) except Exception: pass # Wait up to ~3 minutes for the child uninst.exe to finish and the registry entry to go for _ in range(60): time.sleep(3) if not uninst_running() and not bitvise_registered(): break time.sleep(3) if bitvise_registered(): print 'retcode' + str(1) + 'retcode' else: print 'retcode' + str(0) + 'retcode' 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_update(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'