import win32gui import win32process from psutil import Process import schedule import time def add_ibname_to_1C_window(hwnd, more) -> None: ''' Если окно является окном 1С, то добавляет слева к его названию имя открытой базы. :param hwnd: Открытое окно Windows ''' # Берем только окна, связанные с 1С. class_name = win32gui.GetClassName(hwnd) if 'V8TopLevelFrame' not in class_name: return window_text = win32gui.GetWindowText(hwnd) # Находим процесс, и по этому процессу ищем командную строку. process_id = win32process.GetWindowThreadProcessId(hwnd)[1] process = Process(process_id) commandline = process.cmdline() # Ищем имя базы. ib_name = ib_name_in_commandline(commandline) if ib_name is None: return # Устанавливаем новое имя. if not window_text.startswith(ib_name + ' - '): win32gui.SetWindowText(hwnd, f'{ib_name} - {window_text}') def ib_name_in_commandline(commandline: list) -> str | None: ''' Ищет имя информационной базы из командной строки 1С. :param commandline: Список строк, из которых состоит строка параметров процесса. :return: ''' # Поиск по параметру "/IBName". # Вид строки: "/IBNameMYBASE". iter = (x for x in commandline if x.startswith('/IBName')) par = next(iter, '') if par: ib_name = par.replace('/IBName', '') ib_name = ib_name.strip(' "\'') return ib_name # Поиск по параметру "/S". # Вид строки: '/S"server-1C:1641\ZUP"' iter = (x for x in commandline if x.startswith('/S') and '\\' in x) par = next(iter, '') if par: ib_name = par.split('\\')[-1] ib_name = ib_name.strip(' "\'') return ib_name # Поиск по параметру "/F" # Вид строки: '/F"D:\1C_base\ZUPRAZR"' iter = (x for x in commandline if x.startswith('/F') and '\\' in x) par = next(iter, '') if par: ib_name = par.split('\\')[-1] ib_name = ib_name.strip(' "\'') return ib_name # Поиск по параметру "/IBConnectionString". # Вид строки: "Srvr=MYSERVER;Ref=MYBASE;". iter = (x.lower() for x in commandline if 'ref=' in x.lower()) par = next(iter, '') if par: par = par.partition(';ref=')[2] # убираем всё до ";ref=" par = par.partition(';')[0] # убираем всё после ";" ib_name = par.strip(' "\'') return ib_name def windows_passage() -> None: ''' Проходит по открытым окнам с указанной функцией. ''' win32gui.EnumWindows(add_ibname_to_1C_window, None) if __name__ == '__main__': istest = False if istest: windows_passage() raise SystemExit('Тестовый прогон закончен.') schedule.every(2).seconds.do(windows_passage) while True: schedule.run_pending() time.sleep(2)
Public
Type hints help humans and linters (like mypy
) to understand what to expect "in" and "out" for a function. Not only it serves as a documentation for others (and you after some time, when the code is wiped from your "brain cache"), but also allows using automated tools to find type errors.
"Early quit" is a common pattern which reduces branching and indents in python code. Instead of writing if a: <1000 lines of code> else: <return / raise exception>
, revert the condition: if not a: <return / raise exception>
. This way the "else" clause is not needed, and program logic is straightforward: if something is wrong, quit or raise, otherwise go on.
Never overwrite built-in names, like list
, sum
or max
- if later someone wants to use built-in function, he will find it replaced with your variable. If you really need to use one of those names, append underscore: sum_ = 15
.
Whatever you want to code, usually someone has already done that. And usually there are some tools to cover your case. And usually you can find them using Google.
Nice code. Just fyi, there is more_itertools.first
Whatever you want to code, usually someone has already done that. And usually there are some tools to cover your case. And usually you can find them using Google.
par.removeprefix('/IBName')
Create new review request