Написать пост

Bginfo ломает обои? Напиши свой и сделай его лучше — конкурс пет-проектов

Аватар Дмитрий Беликов

Как я создал аналог программы bginfo, которая выводит информацию о системе и пользователе на рабочий стол, но не ломает смену обоев.

Обложка поста Bginfo ломает обои? Напиши свой и сделай его лучше — конкурс пет-проектов

Привет, уважаемый читатель! Меня зовут Дмитрий, я инженер техподдержки со стажем 10 лет. Самостоятельно изучаю Рython. Хочу сменить работу в техподдержке на разработку.

Сегодня я хочу рассказать о своем пет-проекте, который родился в голове, когда я устроился в одну крупную фирму инженером техподдержки.

Думаю, многим знакома такая программа, как BGinfo. Если не знаете, то эта программа выводит информацию о ПК на рабочий стол.

После начала работы в компании я понял, что данная программа довольно удобная: можно сразу узнать имя ПК, пользователя, домен, ip адрес и прочее, что помогает быстрее диагностировать проблемы, а также проводить инвентаризацию.

Спустя какое-то время я обнаружил у этой программки неприятный баг. Когда подключены два и более мониторов, после срабатывания BGinfo ломалось изображение, и приходилось руками менять положение с режима “Замостить” на “Заполнение”.

Но это еще полбеды. На просторах интернета я нашел программу Bing Wallpapper, которая запала мне в душу. Принцип простой: каждый день эта программа ставит на рабочий стол картинку дня, там и красивые пейзажи, и животные. Ну и какое-никакое разнообразие.

Так вот, BGinfo отключает автоматическую смену обоев. Так и родилась идея проекта.

Проект я назвал максимально “круто” — Corporate_Wallpaper_and_sys_info.

При начале разработки я подумал, что, в принципе, ничего сложного в этом проекте нет, и с места в карьер прыгнул в PyCharm.

Параметры ПК

Начал я с того, какие параметры выдает нам BGinfo, а именно: Host Name, Serial Number, IP Adress, Machine Domain, Logon Domain, Logon Server, User Name, OS Version, Build Number, OS Build, SCCM Client Version, Edge Version.

И тут понеслось гугление, была написана функция get_pc_info, в которой собиралась вся информация о ПК.

Часть информации получалась из командной строки, часть из реестра, часть из свойств файла .exe, как например, информация о версии MS edge.

Использовал библиотеки time, winreg, platform, socket, os, subprocess.

Приведу пример нескольких запросов, т.к. функция довольно длинная:

			'''Версия SCCM'''
    try:
        aSCCM_version = winreg.OpenKey(aReg, r'SOFTWARE\Microsoft\SMS\Mobile Client')
        SCCM_version = winreg.QueryValueEx(aSCCM_version, 'SmsClientVersion')[0]
    except:
        SCCM_version = 'None'
   
'''#Имя ПК'''
    Host_Name = platform.node()
'''#Сервис таг'''
    Mother_name = subprocess.check_output("wmic bios get serialnumber").decode().split()[1]
'''#Версия MS Edge '''
    try:
        Edge_version = ver_parser.GetFileVersion('C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe')
    except:
        Edge_version = 'None'
'''#Ip адрес'''
    try:
        IP_adress = socket.gethostbyname(Host_Name)
    except:
        IP_adress = 'None'
 '''#имя пользователя'''
    User_name = subprocess.check_output('whoami').decode('cp866').replace('\n', '')
    symb = User_name.find('\\')
    User_name = User_name[symb+1:]
		

А самое интересное, с чем столкнулся — это вычисление аптайма. Сперва делаем запрос через powershell времени последней загрузки. Далее удаляем лишние символы и приводим к стандарту библиотеки datetime. После этого получаем текущее время и вычитаем из текущего времени время загрузки.

			'''#Собираем список параметров полученных выше и передаем в функцию создания watermark'''
    param.extend([Host_Name, Mother_name, IP_adress, Machine_Domain,Logon_Domain, Logon_Server, User_name, OS_Version, Build_number, OS_Build, SCCM_version,Edge_version, Uptime])
    return param
		

Создание waterpark

После сбора параметров встал вопрос, как же все это дело отобразить на мониторе. И тут нашлась библиотека Pillow, которая умеет редактировать изображения.

Прочитал кучу статей и документации и смог создать Watermark с информацией о ПК.

			#print('Создаем изображение')
    monitor_width = GetSystemMetrics(0)
    general_watermark = Image.new('RGBA', (300, 370))
    draw_text = ImageDraw.Draw(general_watermark)
    name_param = ['Host Name', 'Serial number', 'IP Adress', 'Machine Domain', 'Logon Domain', 'Logon Server', 'User Name', 'OS Version', 'Build Number', 'OS Build', 'SCCM Client Version', 'Edge Version', 'Uptime']
    value_param = get_pc_info()
    font = ImageFont.truetype('arial.ttf', size=15)
		

В коде выше мы создаем изображение с прозрачным фоном и записываем все полученные параметры из функции выше. После вставляем в этот watermark логотип компании, а цельное изображение вставляем в картинку для рабочего стола.

При вставке логотипа компании столкнулся с тем, что когда я вставлял изображение .jpg в картинку с прозрачным фоном, то фон с прозрачного менялся на черный. Решилась эта задачка довольно просто:

			general_watermark.paste(watermark, (8, 80), mask=watermark.convert('RGBA'))
		

При вставке логотипа, логотип нужно конвертировать в RGBA.

В общем итоге мы получили картинку, какая и была у пользователя, но теперь с watermark. Осталось только установить на рабочий стол. Быстрый поиск выдал простую функцию:

			def changeBG():
    """Проверка разрядности системы"""
    bit64 = struct.calcsize('P') * 8 == 64
    SPI_SETDESKWALLPAPER = 20
    corp_wllp = os.path.abspath(cnew_wallp)
    if bit64 is True:
        ctypes.windll.user32.SystemParametersInfoW(SPI_SETDESKWALLPAPER, 0, corp_wllp, 3)
    else:
        ctypes.windll.user32.SystemParametersInfoA(SPI_SETDESKWALLPAPER, 0, corp_wllp, 3)
		

В зависимости от разрядности системы функции отличаются, и пришлось добавить проверку разрядности системы.

Но на этом я не остановился и решил добавить автосмену обоев: обои должны быть каждый день новые.

Как я выше писал, мне очень понравилась программа bing wallpaper. Пришлось спарсить страничку bing и сохранить изображение.

Настройки

А что, если пользователь не захочет менять обои? Я начал думать над созданием config файла. Сначала config сделал в формате .py. Удобно, можно его просто импортировать и работать с ним, но я отказался в пользу .ini и библиотеки ConfigParser.

В конфиг я добавил месторасположение сохранения картинки Bing и логотипа компании, добавил автосмену обоев.

Подключил все это через функцию read_config и библиотеки ConfigParser.

			def read_conf():
    config = configparser.ConfigParser()
    conf_file = f'{os.getcwd()}\config.ini'
    config.read(conf_file)
    clocal = config['DEFAULT']['local']
    cauto = config['DEFAULT']['auto']
    clogo = config['DEFAULT']['logo']
    cnew_wallp = config['DEFAULT']['new_wallp']
    cconfig = config['DEFAULT']['config']
    return clocal, cauto, clogo, cnew_wallp, cconfig
		

Тут же возникла проблема: а если не будет конфига, что делать? Написал функцию проверки конфига, и если его нет, то он будет создан.

			def new_config():
    with open(f'{os.getcwd()}\config.ini', 'w') as f:
        f.write('[DEFAULT]\n')
        f.write(f"local = {os.getcwd()}\local_wallp.jpg\n") #Директория хранения фото на ПК
        f.write('auto = True\n') #автосмена обоев вкл или выкл
        f.write("logo = OFS.JPG\n") # Диретория хранения логотипа
        f.write(f"new_wallp = {os.getcwd()}\corp_wallpaper.jpg\n") #Директория хранения нового файла рабочего стола
        f.write("config = config.ini")
		

Тут мне понадобилась функция getcwd() библиотеки os, которая возвращает путь до запущенного файла, чтобы в этой директории создать конфиг и, тем самым, сделать программу портативной.

Если у пользователя автосмена выключена, тогда нет смысла скачивать изображение, а достаточно получить путь до изображения, которое сейчас установлено у него на рабочем столе. Сделал функцию проверки автосмены:

			def check_auto_wallpaper():
    if cauto == 'True':
        download_wallpaper()
        if os.path.exists(clocal):
            create_image(clocal)
        else:
            check_logo_weather()
    else:
        check_logo_weather()
		

Получаем путь до обоев пользователя:

			def wallpaper():
    aReg = winreg.ConnectRegistry(None, winreg.HKEY_CURRENT_USER)
    aKey = winreg.OpenKey(aReg, r"Control Panel\Desktop")
    keyname = winreg.QueryValueEx(aKey, 'WallPaper')[0]
    return keyname
		

Используем путь до обоев, чтобы вставить на него наш логотип и установить на рабочий стол, как мы это делали в коде ранее.

Для постоянной работы создал цикл while, добавив туда запуск функций и time.sleep(3600) для ежечасного обновления информации. Ресурсов потребляет не много.

Во время создания программы я сменил место работы и предложил идею своей программы руководству на новом месте, ранее подобные программы компания не использовала.

Идея руководству понравилась, и программу пообещали внедрить в компании.

Спасибо, что дочитали до конца. Это моя первая статья, прошу сильно не пинать.

Да и программировать я только учусь, в окружении разработчиков у меня нет, все писалось, тестировалось и улучшалось самостоятельно.

Возможно, я что-то сделал неправильно или неэстетично, но этот проект позволил мне поработать с файловой системой Windows, изучить новые библиотеки и столкнуться с различными нюансами разработки. После разработки я разобрался в auto-py-to-exe, чтобы запуск совершался одной кнопкой, и покопался в реестре, дабы добавить программу в автозапуск.

Если вам понравился проект, и вы хотите посмотреть его полностью, то вот ссылка на GitHub:

Следите за новыми постами
Следите за новыми постами по любимым темам
820 открытий1К показов