| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229 |
- import os
- import sys
- import time
- import uuid
- import winreg
- from ctypes.wintypes import RECT
- import psutil
- import win32gui
- import winshell
- import ctypes
- import pythoncom
- import win32com.client
- import win32api
- from comtypes.typeinfo import LoadTypeLibEx
- from ctypes import OleDLL, c_void_p, byref, WINFUNCTYPE
- from uuid import UUID
- from tools.log import logger
- class Utils:
- @staticmethod
- def extract_between_strings(content, start_tag, end_tag):
- """
- 提取content中从start_tag到end_tag之间的字符串。
- 参数:
- content (str): 包含要提取内容的字符串。
- start_tag (str): 起始标记字符串。
- end_tag (str): 结束标记字符串。
- 返回:
- str: start_tag和end_tag之间的内容。如果未找到匹配内容,则返回空字符串。
- """
- try:
- # 查找起始标记的位置
- start_index = content.find(start_tag)
- if start_index == -1:
- return ""
- # 计算实际内容的起始位置
- start_index += len(start_tag)
- # 查找结束标记的位置
- end_index = content.find(end_tag, start_index)
- if end_index == -1:
- return ""
- # 提取中间的内容
- return content[start_index:end_index]
- except Exception as e:
- # 错误处理,返回空字符串或抛出异常
- return ""
- @staticmethod
- def get_registry_value(key_path, value_name,key=winreg.HKEY_CURRENT_USER):
- try:
- with winreg.OpenKey(key, key_path) as key:
- value, _ = winreg.QueryValueEx(key, value_name)
- return value
- except FileNotFoundError:
- return None
- @staticmethod
- def get_install_dir_from_shortcut(shortcut: str):
- try:
- with winreg.OpenKey(winreg.HKEY_CURRENT_USER,
- r"Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders") as key:
- value, _ = winreg.QueryValueEx(key, "Desktop")
- shortcut = winshell.shortcut(os.path.join(value, shortcut))
- return shortcut.path
- except Exception as e:
- print(f"Error parsing shortcut {value + shortcut}: {e}")
- return None
- @staticmethod
- def makelong(low, high):
- return low | (high << 16)
- @staticmethod
- def set_window_position_and_size(hwnd, x, y, width, height):
- """
- 设置指定窗口句柄的窗口的位置和大小。
- :param hwnd: 窗口句柄
- :param y: 窗口的新 y 坐标
- :param x: 窗口的新 x 坐标
- :param width: 窗口的新宽度
- :param height: 窗口的新高度
- """
- if hwnd:
- win32gui.MoveWindow(hwnd, x, y, width, height, True)
- else:
- logger.error("无效的窗口句柄")
- print("无效的窗口句柄")
- @staticmethod
- def get_window_position_and_size(hwnd):
- """
- 获取指定窗口句柄的窗口的位置和大小。
- :param hwnd: 窗口句柄
- :return: 窗口的位置和大小
- """
- if hwnd:
- rect = win32gui.GetWindowRect(hwnd)
- x, y, width, height = rect
- return x, y, width-x, height-y
- else:
- raise Exception("无效的窗口句柄")
- @staticmethod
- def get_mac_address():
- mac_address = ':'.join(hex(uuid.getnode())[2:].zfill(12)[i:i + 2] for i in range(0, 12, 2))
- return mac_address
- @staticmethod
- def is_admin():
- try:
- return ctypes.windll.shell32.IsUserAnAdmin()
- except Exception:
- return False
- @staticmethod
- def run_as_admin():
- # 以管理员权限重新运行当前脚本
- script = sys.argv[0]
- params = ' '.join([f'"{param}"' for param in sys.argv[1:]])
- try:
- ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, f'"{script}" {params}', None, 1)
- except Exception as e:
- print(f"Failed to elevate privileges: {e}")
- sys.exit(1)
- class TimedLock:
- def __init__(self, lock, timeout):
- self.lock = lock
- self.timeout = timeout
- def __enter__(self):
- """尝试获取锁,如果在超时内无法获取,抛出 TimeoutError"""
- if not self.lock.acquire(timeout=self.timeout):
- raise TimeoutError(f"Could not acquire lock within {self.timeout} seconds.")
- return self
- def __exit__(self, exc_type, exc_val, exc_tb):
- """确保锁被释放"""
- self.lock.release()
- @staticmethod
- class Timer:
- def __init__(self):
- self._time_signs = {}
- def time_sign(self, sign):
- self._time_signs[sign] = time.time()
- def timer(self, sign, t):
- if sign not in self._time_signs:
- self._time_signs[sign] = time.time()
- return True
- if time.time() - self._time_signs[sign] > t:
- self._time_signs[sign] = time.time()
- return True
- return False
- @staticmethod
- def create_instance_from_com_dll(dll_path):
- """从 DLL 中创建 COM 对象实例"""
- com_classfactory = c_void_p(0)
- try:
- # 加载 DLL 和类型库
- dll = OleDLL(dll_path)
- typelib = LoadTypeLibEx(dll_path)
- # 获取 COM 对象的 CLSID
- co_class_info = typelib.GetTypeInfo(1)
- co_class_attr = co_class_info.GetTypeAttr()
- clsid = UUID(str(co_class_attr.guid)).bytes_le
- # 获取 IClassFactory 接口
- iclassfactory = UUID(str(pythoncom.IID_IClassFactory)).bytes_le
- dll.DllGetClassObject(clsid, iclassfactory, byref(com_classfactory))
- # 从 IClassFactory 接口创建 COM 对象实例
- class_factory = pythoncom.ObjectFromAddress(com_classfactory.value, pythoncom.IID_IClassFactory)
- iptr = class_factory.CreateInstance(None, pythoncom.IID_IDispatch)
- return win32com.client.Dispatch(iptr, resultCLSID=None)
- except Exception as e:
- raise RuntimeError(f"Failed to create COM object from DLL: {e}")
- finally:
- # 释放 IClassFactory 接口
- if com_classfactory:
- IUnknown_Release = WINFUNCTYPE(c_void_p)(2, 'Release', (), pythoncom.IID_IUnknown)
- IUnknown_Release(com_classfactory)
- @staticmethod
- def draw_text_on_window(hwnd, text):
- print(text)
- # 获取窗口的设备上下文
- hdc = win32gui.GetDC(hwnd)
- # 设置文本颜色
- color = win32api.RGB(255, 0, 0) # 红色
- ctypes.windll.gdi32.SetTextColor(hdc, color)
- ctypes.windll.gdi32.SetBkMode(hdc, 1) # 透明背景
- # 在指定位置绘制文本
- x, y = 50, 50 # 文本的起始坐标
- ctypes.windll.gdi32.ExtTextOutW(hdc, x, y, 0, None, text, len(text), None)
- # 释放设备上下文
- win32gui.ReleaseDC(hwnd, hdc)
- @staticmethod
- def kill_process(pid):
- try:
- p = psutil.Process(pid)
- p.kill() # 强制终止进程
- # 可选:等待进程结束,设置超时
- p.wait(timeout=3) # 等待最多3秒
- except psutil.NoSuchProcess:
- logger.warning(f"Process {pid} does not exist.")
- except psutil.AccessDenied:
- logger.warning(f"Access denied to terminate process {pid}.")
- except psutil.TimeoutExpired:
- logger.warning(f"Process {pid} could not be terminated in time.")
- except Exception as e:
- logger.exception(f"Error: {e}")
|