Статья Способы получения информации об ОС и железе с помощью Python. Часть 03: ОС Windows и WMI

Эта статья является продолжением двух предыдущих статей: раз, два о способах получения информации об операционной системе и железе компьютера с помощью стандартных модулей 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()

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

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

Вложения

  • wmi_win_merge.zip
    3,2 КБ · Просмотры: 175
Последнее редактирование:
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!