def getDesktopWindow(): console_id = win32ts.WTSGetActiveConsoleSessionId() if console_id == 0xffffffff: # User not logged in right now? logging.info("No console user") return None hwnd = None # Get processes running on this console svr = win32ts.WTSOpenServer(".") ps_list = win32ts.WTSEnumerateProcesses(svr, 1, 0) for ps in ps_list: logging.info("PS " + str(ps)) win32ts.WTSCloseServer(svr) # sessions = win32ts.WTSEnumerateSessions(None, 1, 0) # for session in win32ts.WTSEnumerateSessions(win32ts.WTS_CURRENT_SERVER_HANDLE, 1, 0): # print "SessionId: %s" % session['SessionId'] # print "\tWinStationName: %s" % session['WinStationName'] # print "\tState: %s" % session['State'] # print # if session["WinStationName"] == "Console": # cs = session #if cs is not None: # # Get process list for this session return hwnd
def kill(self, pid=None): import win32ts hand = win32ts.WTSOpenServer('localhost') process = win32ts.WTSEnumerateProcesses(hand, 1, 0) for i in process: # subprocess.Popen(self.nircmd + " closeprocess foobar2000.exe") if "foobar2000.exe" in i[2]: os.kill(i[1], i[1]) if "COMServer2Helper.exe" in i[2]: os.kill(i[1], i[1])
def EnumProcesses(): for server, server_h in EnumServers(): for session, pid, image, sid in Ts.WTSEnumerateProcesses(server_h, 1): yield { "Server": server, "hServer": server_h, "SessionId": session, "Pid": pid, "Image": image, "Sid": sid }
def find_process(**kw): mypid = os.getpid() mysession = Wts.ProcessIdToSessionId(mypid) srv_h = Wts.WTS_CURRENT_SERVER_HANDLE for session, pid, image, sid in Wts.WTSEnumerateProcesses(srv_h): if session != mysession: continue if "image" in kw and image.lower() != kw["image"].lower(): continue if "pid" in kw and pid != kw["pid"]: continue yield session, pid, image, sid
def get_all(self): if not self.processes: pids = win32process.EnumProcesses() try: proc_infos = win32ts.WTSEnumerateProcesses( wpc.conf.remote_server, 1, 0) except: proc_infos = [] pass for pid in pids: p = Process(pid) self.add(p) for proc_info in proc_infos: pid = proc_info[1] p = self.find_by_pid(pid) if p: # might fail to find process - race condition p.set_wts_session_id(proc_info[0]) p.set_wts_name(proc_info[2]) if proc_info[3]: # sometimes None p.set_wts_sid(Principal(proc_info[3])) TH32CS_SNAPPROCESS = 0x00000002 # See http://msdn2.microsoft.com/en-us/library/ms686701.aspx CreateToolhelp32Snapshot = ctypes.windll.kernel32.CreateToolhelp32Snapshot Process32First = ctypes.windll.kernel32.Process32First Process32Next = ctypes.windll.kernel32.Process32Next Thread32First = ctypes.windll.kernel32.Thread32First Thread32Next = ctypes.windll.kernel32.Thread32Next CloseHandle = ctypes.windll.kernel32.CloseHandle hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0) pe32 = PROCESSENTRY32() pe32.dwSize = ctypes.sizeof(PROCESSENTRY32) if Process32First(hProcessSnap, ctypes.byref(pe32)) == win32con.FALSE: pass #print >> sys.stderr, "Failed getting first process." #return else: while True: p = self.find_by_pid(pe32.th32ProcessID) if p: # might fail to find process - race condition p.set_short_name(pe32.szExeFile) if Process32Next(hProcessSnap, ctypes.byref(pe32)) == win32con.FALSE: break CloseHandle(hProcessSnap) return self.processes
def wts_proc_list(process: str = None) -> list: ''' Returns list of DictToObj objects with properties: .sessionid:int, .pid:int, .process:str (name of exe file) , .pysid:obj, .username:str, .cmdline:list process - filter by process name. ''' if process: process = process.lower() proc_tup = win32ts.WTSEnumerateProcesses() proc_li = [] for tup in proc_tup: if process: if tup[2].lower() != process: continue di = {} di['sessionid'], di['pid'], di['process'], _ = tup di['process'] = di['process'].lower() proc = psutil.Process(di['pid']) di['username'] = proc.username() if di['username']: di['username'] = di['username'].split('\\')[1].lower() di['cmdline'] = proc.cmdline() proc_li.append(DictToObj(di)) return proc_li
def _main(module, name, applockfilename, probe_ports=True): # Allow multiple instances only for curve viewer, profile info, # scripting client, synthetic profile creator and testchart editor multi_instance = ("curve-viewer", "profile-info", "scripting-client", "synthprofile", "testchart-editor") lock = AppLock(applockfilename, "a+", True, module in multi_instance) if not lock: # If a race condition occurs, do not start another instance safe_print("Not starting another instance.") return log("=" * 80) if verbose >= 1: version = VERSION_STRING if VERSION > VERSION_BASE: version += " Beta" safe_print(pyname + runtype, version, build) if sys.platform == "darwin": # Python's platform.platform output is useless under Mac OS X # (e.g. 'Darwin-15.0.0-x86_64-i386-64bit' for Mac OS X 10.11 El Capitan) safe_print("Mac OS X %s %s" % (mac_ver()[0], mac_ver()[-1])) elif sys.platform == "win32": machine = platform.machine() safe_print(*[v for v in win_ver() if v] + ({ "AMD64": "x86_64" }.get(machine, machine), )) else: # Linux safe_print(' '.join(platform.dist()), platform.machine()) safe_print("Python " + sys.version) cafile = os.getenv("SSL_CERT_FILE") if cafile: safe_print("CA file", cafile) # Enable faulthandler try: import faulthandler except Exception as exception: safe_print(exception) else: try: faulthandler.enable( open(os.path.join(logdir, pyname + "-fault.log"), "w")) except Exception as exception: safe_print(exception) else: safe_print("Faulthandler", getattr(faulthandler, "__version__", "")) from wxaddons import wx if "phoenix" in wx.PlatformInfo: # py2exe helper so wx.xml gets picked up from wx import xml safe_print("wxPython " + wx.version()) safe_print("Encoding: " + enc) safe_print("File system encoding: " + fs_enc) if sys.platform == "win32" and sys.getwindowsversion() >= (6, 2): # HighDPI support try: shcore = ctypes.windll.shcore except Exception as exception: safe_print("Warning - could not load shcore:", exception) else: if hasattr(shcore, "SetProcessDpiAwareness"): try: # 1 = System DPI aware (wxWpython currently does not # support per-monitor DPI) shcore.SetProcessDpiAwareness(1) except Exception as exception: safe_print("Warning - SetProcessDpiAwareness() failed:", exception) else: safe_print( "Warning - SetProcessDpiAwareness not found in shcore") initcfg(module) host = "127.0.0.1" defaultport = getcfg("app.port") lock2pids_ports = {} opid = os.getpid() if probe_ports: # Check for currently used ports lockfilenames = glob.glob(os.path.join(confighome, "*.lock")) for lockfilename in lockfilenames: safe_print("Lockfile", lockfilename) try: if lock and lockfilename == applockfilename: lockfile = lock lock.seek(0) else: lockfile = AppLock(lockfilename, "r", True, True) if lockfile: if not lockfilename in lock2pids_ports: lock2pids_ports[lockfilename] = [] for ln, line in enumerate(lockfile.read().splitlines(), 1): if ":" in line: # DisplayCAL >= 3.8.8.2 with localhost blocked pid, port = line.split(":", 1) if pid: try: pid = int(pid) except ValueError as exception: # This shouldn't happen safe_print("Warning - couldn't parse PID " "as int: %r (%s line %i)" % (pid, lockfilename, ln)) pid = None else: safe_print("Existing client using PID", pid) else: # DisplayCAL <= 3.8.8.1 or localhost ok pid = None port = line if port: try: port = int(port) except ValueError as exception: # This shouldn't happen safe_print( "Warning - couldn't parse port as int: %r " "(%s line %i)" % (port, lockfilename, ln)) port = None else: safe_print("Existing client using port", port) if pid or port: lock2pids_ports[lockfilename].append((pid, port)) if not lock or lockfilename != applockfilename: lockfile.unlock() except EnvironmentError as exception: # This shouldn't happen safe_print( "Warning - could not read lockfile %s:" % lockfilename, exception) if module not in multi_instance: # Check lockfile(s) and probe port(s) for lockfilename in [applockfilename]: incoming = None pids_ports = lock2pids_ports.get(lockfilename) if pids_ports: pid, port = pids_ports[0] appsocket = AppSocket() if appsocket and port: safe_print("Connecting to %s..." % port) if appsocket.connect(host, port): safe_print("Connected to", port) # Other instance already running? # Get appname to check if expected app is actually # running under that port safe_print("Getting instance name") if appsocket.send("getappname"): safe_print( "Sent scripting request, awaiting response..." ) incoming = appsocket.read().rstrip("\4") safe_print("Got response: %r" % incoming) if incoming: if incoming != pyname: incoming = None else: incoming = False while incoming: # Send args as UTF-8 if module == "apply-profiles": # Always try to close currently running instance safe_print("Closing existing instance") cmd = "exit" if incoming == pyname else "close" data = [cmd] lock.unlock() else: # Send module/appname to notify running app safe_print("Notifying existing instance") data = [module or appname] if module != "3DLUT-maker": for arg in sys.argv[1:]: data.append( safe_str(safe_unicode(arg), "UTF-8")) data = sp.list2cmdline(data) if appsocket.send(data): safe_print( "Sent scripting request, awaiting response..." ) incoming = appsocket.read().rstrip("\4") safe_print("Got response: %r" % incoming) if module == "apply-profiles": if incoming == "": # Successfully sent our close request. incoming = "ok" elif incoming == "invalid" and cmd == "exit": # < 3.8.8.1 didn't have exit command continue break appsocket.close() else: pid = None if not incoming: if sys.platform == "win32": import pywintypes import win32ts try: osid = win32ts.ProcessIdToSessionId(opid) except pywintypes.error as exception: safe_print("Enumerating processes failed:", exception) osid = None try: processes = win32ts.WTSEnumerateProcesses() except pywintypes.error as exception: safe_print("Enumerating processes failed:", exception) else: appname_lower = appname.lower() exename_lower = exename.lower() if module: pyexe_lower = appname_lower + "-" + module + exe_ext else: pyexe_lower = appname_lower + exe_ext incoming = None for (sid, pid2, basename, usid) in processes: basename_lower = basename.lower() if ((pid and pid2 == pid and basename_lower == exename_lower) or ((osid is None or sid == osid) and basename_lower == pyexe_lower)) and pid2 != opid: # Other instance running incoming = False if module == "apply-profiles": if not os.path.isfile(lockfilename): # Create dummy lockfile try: with open(lockfilename, "w"): pass except EnvironmentError as exception: safe_print( "Warning - could " "not create dummy " "lockfile %s: %r" % (lockfilename, exception)) else: safe_print( "Warning - had to " "create dummy " "lockfile", lockfilename) safe_print( "Closing existing instance " "with PID", pid2) startupinfo = sp.STARTUPINFO() startupinfo.dwFlags |= sp.STARTF_USESHOWWINDOW startupinfo.wShowWindow = sp.SW_HIDE lock.unlock() try: p = sp.Popen( [ "taskkill", "/PID", "%s" % pid2 ], stdin=sp.PIPE, stdout=sp.PIPE, stderr=sp.STDOUT, startupinfo=startupinfo) stdout, stderr = p.communicate() except Exception as exception: safe_print(exception) else: safe_print(stdout) if not p.returncode: # Successfully sent our close # request. incoming = "ok" if incoming == "ok": # Successfully sent our request if module == "apply-profiles": # Wait for lockfile to be removed, in which case # we know the running instance has successfully # closed. safe_print( "Waiting for existing instance to exit and " "delete lockfile", lockfilename) while os.path.isfile(lockfilename): sleep(.05) lock.lock() safe_print("Existing instance exited.") incoming = None if lockfilename in lock2pids_ports: del lock2pids_ports[lockfilename] break if incoming is not None: # Other instance running? import localization as lang lang.init() if incoming == "ok": # Successfully sent our request safe_print(lang.getstr("app.otherinstance.notified")) elif module == "apply-profiles": safe_print("Not starting another instance.") else: # Other instance busy? handle_error(lang.getstr("app.otherinstance", name)) # Exit return # Use exclusive lock during app startup with lock: # Create listening socket appsocket = AppSocket() if appsocket: if sys.platform != "win32": # https://docs.microsoft.com/de-de/windows/win32/winsock/using-so-reuseaddr-and-so-exclusiveaddruse#using-so_reuseaddr # From the above link: "The SO_REUSEADDR socket option allows # a socket to forcibly bind to a port in use by another socket". # Note that this is different from the behavior under Linux/BSD, # where a socket can only be (re-)bound if no active listening # socket is already bound to the address. # Consequently, we don't use SO_REUSEADDR under Windows. appsocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sys._appsocket = appsocket.socket if getcfg("app.allow_network_clients"): host = "" used_ports = [ pid_port[1] for pids_ports in list(lock2pids_ports.values()) for pid_port in pids_ports ] candidate_ports = [0] if not defaultport in used_ports: candidate_ports.insert(0, defaultport) for port in candidate_ports: try: sys._appsocket.bind((host, port)) except socket.error as exception: if port == 0: safe_print( "Warning - could not bind to %s:%s:" % (host, port), exception) del sys._appsocket break else: try: sys._appsocket.settimeout(.2) except socket.error as exception: safe_print( "Warning - could not set socket " "timeout:", exception) del sys._appsocket break try: sys._appsocket.listen(1) except socket.error as exception: safe_print("Warning - could not listen on " "socket:", exception) del sys._appsocket break try: port = sys._appsocket.getsockname()[1] except socket.error as exception: safe_print( "Warning - could not get socket " "address:", exception) del sys._appsocket break sys._appsocket_port = port break if not hasattr(sys, "_appsocket_port"): port = "" lock.seek(0) if module not in multi_instance: lock.truncate(0) if not port: lock.write("%s:%s" % (opid, port)) else: lock.write(port) atexit.register(lambda: safe_print("Ran application exit handlers")) from wxwindows import BaseApp BaseApp.register_exitfunc(_exit, applockfilename, port) # Check for required resource files mod2res = { "3DLUT-maker": ["xrc/3dlut.xrc"], "curve-viewer": [], "profile-info": [], "scripting-client": [], "synthprofile": ["xrc/synthicc.xrc"], "testchart-editor": [], "VRML-to-X3D-converter": [] } for filename in mod2res.get(module, resfiles): path = get_data_path(os.path.sep.join(filename.split("/"))) if not path or not os.path.isfile(path): import localization as lang lang.init() raise ResourceError( lang.getstr("resources.notfound.error") + "\n" + filename) # Create main data dir if it does not exist if not os.path.exists(datahome): try: os.makedirs(datahome) except Exception as exception: handle_error( UserWarning("Warning - could not create " "directory '%s'" % datahome)) elif sys.platform == "darwin": # Check & fix permissions if necessary import getpass user = getpass.getuser().decode(fs_enc) script = [] for directory in (confighome, datahome, logdir): if (os.path.isdir(directory) and not os.access(directory, os.W_OK)): script.append("chown -R '%s' '%s'" % (user, directory)) if script: sp.call([ 'osascript', '-e', 'do shell script "%s" with administrator privileges' % ";".join(script).encode(fs_enc) ]) # Initialize & run if module == "3DLUT-maker": from wxLUT3DFrame import main elif module == "curve-viewer": from wxLUTViewer import main elif module == "profile-info": from wxProfileInfo import main elif module == "scripting-client": from wxScriptingClient import main elif module == "synthprofile": from wxSynthICCFrame import main elif module == "testchart-editor": from wxTestchartEditor import main elif module == "VRML-to-X3D-converter": from wxVRML2X3D import main elif module == "apply-profiles": from profile_loader import main else: from DisplayCAL import main # Run main after releasing lock main()