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
Share a link to this review

4.00% issue ratio

R1 Missing type hints

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.

Nice!
You did a great job avoiding this case. Many developers don't.
R14 Not using "early quit"

"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.

R40 Overwriting builtins

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.

L50 Reinventing a wheel

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

L50 Reinventing a wheel

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.

Suggested change:
par.removeprefix('/IBName')

Create new review request