Что ж, если в трех предыдущих статьях (раз, два, три) мы узнавали информацию об операционной системе с помощью python и библиотек, которые не требуют установки, это: winreg – работа с реестром Windows; subprocess.check_out – запускали утилиту командной строки wmic и парсили ее вывод; wmi – работа с инструментарием управления Windows, то сегодня давайте попробуем использовать сторонние библиотеки для этих целей. Также, как и в предыдущих статьях сравним скорость работы. И, думаю, что подведем некий итог по сбору информации об операционной системе и железе компьютера. Попробуем скомбинировать способы получения информации. Возьмем из каждого способа тот параметр, который недоступен в других и объединим это все в один. После чего, посмотрим на скорость работы объединенного способа.
Что потребуется?
Так как данный скрипт подразумевает в своей работе установку сторонних библиотек, то потребуется установить их довольно много. Ну как много, давайте их все перечислим: pywin32 – с помощью данной библиотеки мы будем получать информацию о материнской плате; py-cpuinfo – эта библиотека позволяет получить подробную информацию о процессоре; GPUtil – библиотека, которая предназначена для получения информации о видеокарте; psutil – это довольно известная библиотека, с помощью которой можно получить множество различной информации о системе, в нашем же случае мы будем получать информацию о HDD/SSD, а также CD/DVD-ROM и сетевых интерфейсах; python-docx – с помощью данной библиотеки мы будем сохранять отчет в документ Microsoft Word.
Для их пакетной установки выполним в терминале команду:
Информацию об операционной системе мы получим с помощью модуля platform, потому, установки дополнительных библиотек не потребуется. В данном случае мне это показалось более оптимальным решением, чем использование той же библиотеки psutil. Информацию о BIOS мы получим с помощью библиотеки wmi, так как сторонних библиотек для этих целей найти не удалось, хотя, наверное они существуют )). Также, для получения информации о модулях оперативной памяти воспользуемся этим же модулем – wmi. Так как psutil не представляет информацию о каждой из планок установленных в системный блок.
Теперь, когда мы окончательно определились с выбором библиотек для получения информации, давайте приступим к написанию кода. Но, для начала импортируем все нужные библиотеки в скрипт.
Функция для перевода объемов дисков, памяти и др.
Для начала напишем вспомогательную функцию. Думаю, что подробно останавливаться на этой функции не имеет смысла. Создадим функцию get_size(bts: int, ending='iB') -> str, которая на входе получает целое число. Затем в цикле выполняет операцию деления до тех пор, пока данное число не станет меньше 1024. После этого возвращается полученное значение с суффиксом.
Получение информации об операционной системе (platform)
Создадим функцию platform_os() -> dict. На выходе она возвращает словарь с полученными значениями. Как вы видите, используются различные методы для получения информации и сразу же формируется словарь, который возвращается из функции. Единственный недостаток данной функции состоит в том, что мне не удалось найти нормального способа получения даты установки операционной системы. И если раньше, в ОС Windows XP, для примера, можно было определить дату установки по времени создания директории Windows, то начиная с Vista данный способ не работает. И максимум, что можно узнать с помощью данного способа, это дату упаковки дистрибутива. Поэтому, я попытался узнать дату установки с помощью определения даты создания папки пользователя. Способ этот крайне не надежный, так как папка пользователя может быть создана раньше. А потому, доверять ему нельзя. Но, тем не менее я включил данный метод в словарь. После того, как вся нужная информация будет получена, возвращаем результирующий словарь из функции.
Получение информации о BIOS (wmi)
Как я уже писал ранее, найти стороннюю библиотеку для получения информации о BIOS у меня не получилось. Поэтому, для полноты скрипта, я использовал функцию из предыдущей статьи. Она получает данную информацию с помощью библиотеки wmi, которая идет в Python «из коробки».
Создадим функцию bios_wmi() -> (dict, bool). На выходе она возвращает словарь с полученными данными. Создаем объект WMI. Обращаемся к методу Win32_BIOS и забираем нужную информацию. Затем добавляем ее в словарь и возвращаем из функции, если конечно, словарь не пуст.
Получение информации о материнской плате (pywin32)
Для получения информации о материнской плате используем модуль pywin32. Создадим функцию motherboard_win32com() -> (dict, bool), которая возвращает словарь с полученными значениями. Подключаемся к объекту wmi и выполняем запрос SQL, обращаясь к методу Win32_BaseBoard. После чего забираем информацию о производителе и названии материнской платы. Добавляем в результирующий словарь и возвращаем его из функции, если он не пуст. Также обработаем, на всякий случай любое исключение, если что-то пойдет не так.
Получение информации о процессоре (cpuinfo)
Для получения информации о процессоре будем использовать библиотеку cpuinfo. Создадим функцию cpu_cpuinfo() -> (dict, bool), которая возвращает словарь с собранными значениями. Обращаемся к функции = get_cpu_info из данной библиотеки. Данная функция возвращает словарь с данными о процессоре. Потому, обращаемся к ключам словаря и забираем нужную нам информацию, добавляем ее в результирующий словарь и возвращаем из функции.
Получение информации о видеоадаптере (GPUtil)
Создадим функцию gpu_info() -> (dict, bool), которая возвращает словарь с полученными значениями. Получать данные мы будем с помощью библиотеки GPUtil, обратившись к функции данной библиотеки getGPUs, которая возвращает объект <GPUtil.GPUtil.GPU object at 0x00000…> с данными о видеоадаптере. В цикле итерируемся по данному объекту и забираем необходимую информацию, которую добавляем в результирующий словарь, после чего, возвращаем данный словарь из функции, если он не пуст.
Получение информации об оперативной памяти (wmi)
Для получения информации об оперативной памяти снова воспользуемся библиотекой «из коробки» wmi. С помощью данной библиотеки мы получали эти же данные в предыдущей статье. К сожалению, использование библиотеки psutil не дает полной информации, только лишь в общих чертах, потому, в данном случае решено было его не использовать.
Создадим функцию memory_wmi() -> (dict, bool), возвращающую словарь с полученными данными. Создаем объект WMI, обращаемся к методу Win32_PhysicalMemory. Для начала получаем полный объем оперативной памяти, который, по сути, будет суммарным значением данных об объеме каждой планки. Добавляем полученные данные в результирующий словарь. Затем итерируемся по полученным значениям и забираем нужную информацию по каждой планке, которую добавляем в результирующий словарь. После этого, возвращаем его из функции, если он не пуст.
Получение информации о HDD/SSD (psutil)
Для получения информации о дисках создадим функцию hdd_ssd_psutil() -> (dict, bool). Затем итерируемся по полученным данным и забираем нужную информацию, которую добавляем в результирующий словарь. После получения информации возвращаем его из функции, если он не пуст.
Получение информации о CD/DVD-ROM (psutil)
Для получения информации о приводах воспользуемся библиотекой psutil. Более того, функция, которая будет получать данную информацию не особо отличается от той, где мы получали информацию о дисках. Здесь мы всего лишь отфильтруем возвращаемые disk_partitions значения по 'cdrom', а затем получим информацию о нужном разделе.
Создадим функцию cdrom_psutil() -> (dict, bool). Для начала, получим информацию обо всех разделах. Затем отфильтруем полученные значения по cd-rom. Дальше, в цикле будем перебирать полученные значения и заберем только ту информацию, которая относиться к конкретному, отфильтрованному нами разделу. После чего возвратим результирующий словарь из функции, если он не пуст.
Получение информации о сетевых интерфейсах (psutil)
Для получения информации о сетевых интерфейсах будем использовать библиотеку psutil. Создадим функцию nic_psutil() -> (dict, bool). Обратимся к функции net_if_addrs, которая возвращает информацию о сетевых интерфейсах, выпилим из данной информации локальную петлю, так как она не является физическим устройством. Затем, по каждому из устройств соберем возвращаемую информацию и добавим в результирующий словарь. После чего вернем его из функции, если он не пуст.
На этом, как и в предыдущих статьях, завершим сбор информации. И выведем полученные данные в терминал, а также сохраним в документ Microsoft Word.
Функция печати полученных словарей
Ничего нового в данной функции не будет. Ее подробно я описывал в предыдущих статьях, потому, пробежимся по основным моментам. Для начала создадим глобальную строковую переменную, куда будем складывать полученные данные в строковом виде. Эти данные мы потом запишем в документ.
Создаем функцию print_wmic(part, dict_info), где part, это строка с данными об обрабатываемом словаре, а dict_info – непосредственно, сам словарь с данными. Создаем словарь синонимов, чтобы заменять значения из словарей на их эквиваленты.
А затем, непосредственно, следует тело функции, в котором мы итерируемся по словарю, проверяем тип значения ключа. Если он является словарем, итерируемся по нему. Если нет, добавляем значение и его расшифровку в переменную part. После всего добавляем значения из part в глобальную переменную wmic_info, а также выводим содержимое part в терминал.
Функция main
Создадим функцию main, в которой будем получать из функций словари, и, если они будут получены, запускать функцию печати значений. Также, в данной функции создадим документ Microsoft Word, добавим в него заголовок, и, после того, как будут получены данные из всех функций, добавим в параграф значение из строковой переменной wmic_info. После чего сохраним созданный документ и выведем для пользователя информацию о файле, а также время работы скрипта.
Теперь давайте проверим скорость работы получившегося «франкенштейна» и сравним ее со скоростью работы скриптов, которые мы написали в предыдущих статьях.
Таким образом, у нас определились явные победители данного «соревнования». Но, сборный скрипт я буду составлять из библиотек, которые идут в python «из коробки». Даже, если они используют стороннюю утилиту для сбора информации.
Для сборки составного скрипта за основу я решил взять тот, что использует модуль winreg. И, несмотря на то, что информация, которую получает данный модуль, не является полной, он все же показывает самую большую скорость работы. А дополнять его я буду функциями из скрипта, который использует subprocess и утилиту командной строки wmic, потому, что кроме «франкенштейна», у него неплохая скорость работы.
А добавим мы функцию для получения информации об оперативной памяти. Потому как я не нашел веток в реестре, где можно было бы почерпнуть данную информацию. Хотя, они наверняка есть. А также заменим функции для получения данных о HDD/SSD и CD/DVD-ROM, так как функции из скрипта использующего subprocess предоставляют больше информации.
Расписывать создание составного скрипта не имеет большого смысла. Вот, что у меня получилось в итоге:
А теперь, протестируем скорость его работы.
Что ж, скорость работы получилась удовлетворительной. Конечно, не так быстро, как чистый скрипт с winreg, но и гораздо быстрее, чем скрипты использующие другие библиотеки.
А на этом мы закончим статьи о получении информации об ОС и железе в Windows.
Спасибо за внимание. Надеюсь, данная информация будет вам полезна
Что потребуется?
Так как данный скрипт подразумевает в своей работе установку сторонних библиотек, то потребуется установить их довольно много. Ну как много, давайте их все перечислим: pywin32 – с помощью данной библиотеки мы будем получать информацию о материнской плате; py-cpuinfo – эта библиотека позволяет получить подробную информацию о процессоре; GPUtil – библиотека, которая предназначена для получения информации о видеокарте; psutil – это довольно известная библиотека, с помощью которой можно получить множество различной информации о системе, в нашем же случае мы будем получать информацию о HDD/SSD, а также CD/DVD-ROM и сетевых интерфейсах; python-docx – с помощью данной библиотеки мы будем сохранять отчет в документ Microsoft Word.
Для их пакетной установки выполним в терминале команду:
pip install pywin32 py-cpuinfo GPUtil psutil python-docx
Информацию об операционной системе мы получим с помощью модуля platform, потому, установки дополнительных библиотек не потребуется. В данном случае мне это показалось более оптимальным решением, чем использование той же библиотеки psutil. Информацию о BIOS мы получим с помощью библиотеки wmi, так как сторонних библиотек для этих целей найти не удалось, хотя, наверное они существуют )). Также, для получения информации о модулях оперативной памяти воспользуемся этим же модулем – wmi. Так как psutil не представляет информацию о каждой из планок установленных в системный блок.
Теперь, когда мы окончательно определились с выбором библиотек для получения информации, давайте приступим к написанию кода. Но, для начала импортируем все нужные библиотеки в скрипт.
Python:
import time
from datetime import datetime as dt
from os import environ, path
from platform import uname, win32_edition, processor, node
from docx import Document
from cpuinfo import get_cpu_info
from GPUtil import getGPUs
from psutil import disk_partitions, disk_usage, net_if_addrs
from win32com.client import GetObject
from wmi import WMI
Функция для перевода объемов дисков, памяти и др.
Для начала напишем вспомогательную функцию. Думаю, что подробно останавливаться на этой функции не имеет смысла. Создадим функцию 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
Получение информации об операционной системе (platform)
Создадим функцию platform_os() -> dict. На выходе она возвращает словарь с полученными значениями. Как вы видите, используются различные методы для получения информации и сразу же формируется словарь, который возвращается из функции. Единственный недостаток данной функции состоит в том, что мне не удалось найти нормального способа получения даты установки операционной системы. И если раньше, в ОС Windows XP, для примера, можно было определить дату установки по времени создания директории Windows, то начиная с Vista данный способ не работает. И максимум, что можно узнать с помощью данного способа, это дату упаковки дистрибутива. Поэтому, я попытался узнать дату установки с помощью определения даты создания папки пользователя. Способ этот крайне не надежный, так как папка пользователя может быть создана раньше. А потому, доверять ему нельзя. Но, тем не менее я включил данный метод в словарь. После того, как вся нужная информация будет получена, возвращаем результирующий словарь из функции.
Python:
# OS
def platform_os() -> dict:
os_info = dict()
if node():
os_info.update({"ComputerName": node()})
if uname().system and uname().release:
os_info.update({"Caption": f'{uname().system} {uname().release}'})
elif uname().system and not uname().release:
os_info.update({"Caption": f'{uname().system}'})
elif uname().release and not uname().system:
os_info.update({"Caption": f'{uname().release}'})
if win32_edition():
os_info.update({"EditionID": win32_edition()})
if uname().version:
os_info.update({"Version": uname().version})
if uname().machine:
os_info.update({"Architecture": uname().machine})
if environ['WINDIR']:
os_info.update({"WindowsDirectory": environ['WINDIR']})
if environ['USERNAME']:
os_info.update({"UserName": environ['USERNAME']})
if environ['USERPROFILE']:
os_info.update({"InstallDate":
dt.fromtimestamp(path.getctime(environ['USERPROFILE'])).strftime('%d.%m.%Y, %H:%M:%S')})
return os_info if os_info else False
Получение информации о BIOS (wmi)
Как я уже писал ранее, найти стороннюю библиотеку для получения информации о BIOS у меня не получилось. Поэтому, для полноты скрипта, я использовал функцию из предыдущей статьи. Она получает данную информацию с помощью библиотеки wmi, которая идет в Python «из коробки».
Создадим функцию 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
Получение информации о материнской плате (pywin32)
Для получения информации о материнской плате используем модуль pywin32. Создадим функцию motherboard_win32com() -> (dict, bool), которая возвращает словарь с полученными значениями. Подключаемся к объекту wmi и выполняем запрос SQL, обращаясь к методу Win32_BaseBoard. После чего забираем информацию о производителе и названии материнской платы. Добавляем в результирующий словарь и возвращаем его из функции, если он не пуст. Также обработаем, на всякий случай любое исключение, если что-то пойдет не так.
Python:
# Motherboard
def motherboard_win32com() -> (dict, bool):
motherboard = dict()
try:
if c := GetObject("winmgmts:\\\\.\\root\\cimv2"):
if boards := c.ExecQuery("SELECT * FROM Win32_BaseBoard"):
board = boards[0]
motherboard['Manufacturer'] = board.Manufacturer
motherboard['Product'] = board.Product
return motherboard if motherboard else False
except Exception:
return False
Получение информации о процессоре (cpuinfo)
Для получения информации о процессоре будем использовать библиотеку cpuinfo. Создадим функцию cpu_cpuinfo() -> (dict, bool), которая возвращает словарь с собранными значениями. Обращаемся к функции = get_cpu_info из данной библиотеки. Данная функция возвращает словарь с данными о процессоре. Потому, обращаемся к ключам словаря и забираем нужную нам информацию, добавляем ее в результирующий словарь и возвращаем из функции.
Python:
# CPU
def cpu_cpuinfo() -> (dict, bool):
if info := get_cpu_info():
cpu_info = {
"Name": info['brand_raw'],
"Manufacturer": info['vendor_id_raw'],
"Identifier": processor(),
"Architecture": info['arch_string_raw'],
"NumberOfLogicalProcessors": info['count'],
"NumberOfPhysicalProcessors": int(int(info['count']) / 2),
"CurrentRefreshRate": info['hz_actual_friendly'],
"L2CacheSize": info['l2_cache_size'],
"L3CacheSize": info['l3_cache_size']
}
return cpu_info if cpu_info else False
return False
Получение информации о видеоадаптере (GPUtil)
Создадим функцию gpu_info() -> (dict, bool), которая возвращает словарь с полученными значениями. Получать данные мы будем с помощью библиотеки GPUtil, обратившись к функции данной библиотеки getGPUs, которая возвращает объект <GPUtil.GPUtil.GPU object at 0x00000…> с данными о видеоадаптере. В цикле итерируемся по данному объекту и забираем необходимую информацию, которую добавляем в результирующий словарь, после чего, возвращаем данный словарь из функции, если он не пуст.
Python:
# GPU
def gpu_info() -> (dict, bool):
gpus_list = dict()
if gpus := getGPUs():
for gpu in gpus:
gpus_list.update({
"ID": gpu.id,
"Name": gpu.name,
"Load": f'{gpu.load * 100}%',
"FreeMemory": gpu.memoryFree,
"UsedMemory": gpu.memoryUsed,
"TotalMemory": gpu.memoryTotal,
"GPUTemp": f'{gpu.temperature} C'
})
return gpus_list if gpus_list else False
return False
Получение информации об оперативной памяти (wmi)
Для получения информации об оперативной памяти снова воспользуемся библиотекой «из коробки» wmi. С помощью данной библиотеки мы получали эти же данные в предыдущей статье. К сожалению, использование библиотеки psutil не дает полной информации, только лишь в общих чертах, потому, в данном случае решено было его не использовать.
Создадим функцию memory_wmi() -> (dict, bool), возвращающую словарь с полученными данными. Создаем объект WMI, обращаемся к методу Win32_PhysicalMemory. Для начала получаем полный объем оперативной памяти, который, по сути, будет суммарным значением данных об объеме каждой планки. Добавляем полученные данные в результирующий словарь. Затем итерируемся по полученным значениям и забираем нужную информацию по каждой планке, которую добавляем в результирующий словарь. После этого, возвращаем его из функции, если он не пуст.
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 (psutil)
Для получения информации о дисках создадим функцию hdd_ssd_psutil() -> (dict, bool). Затем итерируемся по полученным данным и забираем нужную информацию, которую добавляем в результирующий словарь. После получения информации возвращаем его из функции, если он не пуст.
Python:
# HDD, SSD
def hdd_ssd_psutil() -> (dict, bool):
disks = dict()
if partitions := disk_partitions():
for partition in partitions:
device = partition.device
mountpoint = partition.mountpoint
disk_us = disk_usage(mountpoint)
disk = {'Drive': device,
'Mountpoint': mountpoint,
'TotalSpace': get_size(disk_us.total),
'UsedSpace': get_size(disk_us.used),
'FreeSpace': get_size(disk_us.free),
'PercentUsed': disk_us.percent}
disks[device] = disk
return disks if disks else False
return False
Получение информации о CD/DVD-ROM (psutil)
Для получения информации о приводах воспользуемся библиотекой psutil. Более того, функция, которая будет получать данную информацию не особо отличается от той, где мы получали информацию о дисках. Здесь мы всего лишь отфильтруем возвращаемые disk_partitions значения по 'cdrom', а затем получим информацию о нужном разделе.
Создадим функцию cdrom_psutil() -> (dict, bool). Для начала, получим информацию обо всех разделах. Затем отфильтруем полученные значения по cd-rom. Дальше, в цикле будем перебирать полученные значения и заберем только ту информацию, которая относиться к конкретному, отфильтрованному нами разделу. После чего возвратим результирующий словарь из функции, если он не пуст.
Python:
# CD-ROM
def cdrom_psutil() -> (dict, bool):
info = dict()
if disks := disk_partitions():
if cdrom_disks := filter(lambda disk: 'cdrom' in disk.opts, disks):
for dsk in cdrom_disks:
try:
disk_info = disk_usage(dsk.mountpoint)
info[dsk.device] = {
'TotalSpace': get_size(disk_info.total),
'UsedSpace': get_size(disk_info.used),
'FreeSpace': get_size(disk_info.free)
}
except Exception:
pass
return info if info else False
return False
Получение информации о сетевых интерфейсах (psutil)
Для получения информации о сетевых интерфейсах будем использовать библиотеку psutil. Создадим функцию nic_psutil() -> (dict, bool). Обратимся к функции net_if_addrs, которая возвращает информацию о сетевых интерфейсах, выпилим из данной информации локальную петлю, так как она не является физическим устройством. Затем, по каждому из устройств соберем возвращаемую информацию и добавим в результирующий словарь. После чего вернем его из функции, если он не пуст.
Python:
# Network Information
def nic_psutil() -> (dict, bool):
nic = dict()
for item in net_if_addrs():
if "loopback" in item.lower():
continue
nic[item] = dict()
for adapt in net_if_addrs()[item]:
match adapt.family:
case -1:
nic[item].update({"MACAddress": adapt.address})
case 2:
nic[item].update({"IPv4Address": adapt.address,
"IPSubnet": adapt.netmask})
case 23:
nic[item].update({"IPv6Address": adapt.address})
return nic if nic else False
На этом, как и в предыдущих статьях, завершим сбор информации. И выведем полученные данные в терминал, а также сохраним в документ Microsoft Word.
Функция печати полученных словарей
Ничего нового в данной функции не будет. Ее подробно я описывал в предыдущих статьях, потому, пробежимся по основным моментам. Для начала создадим глобальную строковую переменную, куда будем складывать полученные данные в строковом виде. Эти данные мы потом запишем в документ.
Создаем функцию print_wmic(part, dict_info), где part, это строка с данными об обрабатываемом словаре, а dict_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": "Название службы", "Architecture": "Архитектура", "L2CacheSize": "Размер кэша L2",
"L3CacheSize": "Размер кэша L3", "Load": "Загрузка", "FreeMemory": "Свободная память",
"UsedMemory": "Занятая память", "TotalMemory": "Общее количество памяти", "GPUTemp": "Температура GPU",
"Mountpoint": "Точка монтирования", "TotalSpace": "Размер", "UsedSpace": "Занято",
"FreeSpace": "Свободно", "PercentUsed": "Процент использования", "EditionID": "Идентификатор редакции",
"Identifier": "Идентификатор"}
А затем, непосредственно, следует тело функции, в котором мы итерируемся по словарю, проверяем тип значения ключа. Если он является словарем, итерируемся по нему. Если нет, добавляем значение и его расшифровку в переменную part. После всего добавляем значения из part в глобальную переменную wmic_info, а также выводим содержимое part в терминал.
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'
Функция main
Создадим функцию 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 := platform_os():
print_wmic("Информация об операционной системе\n", os_info)
if bios_info := bios_wmi():
print_wmic("Информация о BIOS\n", bios_info)
if mb_info := motherboard_win32com():
print_wmic("Информация о материнской плате\n", mb_info)
if cpu_info := cpu_cpuinfo():
print_wmic("Информация о процессоре\n", cpu_info)
if gpu := gpu_info():
print_wmic("Информация о видеокарте\n", gpu)
if mem_info := memory_wmi():
print_wmic("Информация об оперативной памяти\n", mem_info)
if drive_info := hdd_ssd_psutil():
print_wmic("Информация о HDD и SSD\n", drive_info)
if cd_rom_info := cdrom_psutil():
print_wmic("Информация о CD/DVD-ROM\n", cd_rom_info)
if nic_info := nic_psutil():
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()
Python:
# pip install pywin32 py-cpuinfo GPUtil psutil python-docx
import time
from datetime import datetime as dt
from os import environ, path
from platform import uname, win32_edition, processor, node
from docx import Document
from cpuinfo import get_cpu_info
from GPUtil import getGPUs
from psutil import disk_partitions, disk_usage, net_if_addrs
from win32com.client import GetObject
from wmi import WMI
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 platform_os() -> dict:
os_info = dict()
if node():
os_info.update({"ComputerName": node()})
if uname().system and uname().release:
os_info.update({"Caption": f'{uname().system} {uname().release}'})
elif uname().system and not uname().release:
os_info.update({"Caption": f'{uname().system}'})
elif uname().release and not uname().system:
os_info.update({"Caption": f'{uname().release}'})
if win32_edition():
os_info.update({"EditionID": win32_edition()})
if uname().version:
os_info.update({"Version": uname().version})
if uname().machine:
os_info.update({"Architecture": uname().machine})
if environ['WINDIR']:
os_info.update({"WindowsDirectory": environ['WINDIR']})
if environ['USERNAME']:
os_info.update({"UserName": environ['USERNAME']})
if environ['USERPROFILE']:
os_info.update({"InstallDate":
dt.fromtimestamp(path.getctime(environ['USERPROFILE'])).strftime('%d.%m.%Y, %H:%M:%S')})
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_win32com() -> (dict, bool):
motherboard = dict()
try:
if c := GetObject("winmgmts:\\\\.\\root\\cimv2"):
if boards := c.ExecQuery("SELECT * FROM Win32_BaseBoard"):
board = boards[0]
motherboard['Manufacturer'] = board.Manufacturer
motherboard['Product'] = board.Product
return motherboard if motherboard else False
except Exception:
return False
# CPU
def cpu_cpuinfo() -> (dict, bool):
if info := get_cpu_info():
cpu_info = {
"Name": info['brand_raw'],
"Manufacturer": info['vendor_id_raw'],
"Identifier": processor(),
"Architecture": info['arch_string_raw'],
"NumberOfLogicalProcessors": info['count'],
"NumberOfPhysicalProcessors": int(int(info['count']) / 2),
"CurrentRefreshRate": info['hz_actual_friendly'],
"L2CacheSize": info['l2_cache_size'],
"L3CacheSize": info['l3_cache_size']
}
return cpu_info if cpu_info else False
return False
# GPU
def gpu_info() -> (dict, bool):
gpus_list = dict()
if gpus := getGPUs():
for gpu in gpus:
gpus_list.update({
"ID": gpu.id,
"Name": gpu.name,
"Load": f'{gpu.load * 100}%',
"FreeMemory": gpu.memoryFree,
"UsedMemory": gpu.memoryUsed,
"TotalMemory": gpu.memoryTotal,
"GPUTemp": f'{gpu.temperature} C'
})
return gpus_list if gpus_list else False
return 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_psutil() -> (dict, bool):
disks = dict()
if partitions := disk_partitions():
for partition in partitions:
device = partition.device
mountpoint = partition.mountpoint
disk_us = disk_usage(mountpoint)
disk = {'Drive': device,
'Mountpoint': mountpoint,
'TotalSpace': get_size(disk_us.total),
'UsedSpace': get_size(disk_us.used),
'FreeSpace': get_size(disk_us.free),
'PercentUsed': disk_us.percent}
disks[device] = disk
return disks if disks else False
return False
# CD-ROM
def cdrom_psutil() -> (dict, bool):
info = dict()
if disks := disk_partitions():
if cdrom_disks := filter(lambda disk: 'cdrom' in disk.opts, disks):
for dsk in cdrom_disks:
try:
disk_info = disk_usage(dsk.mountpoint)
info[dsk.device] = {
'TotalSpace': get_size(disk_info.total),
'UsedSpace': get_size(disk_info.used),
'FreeSpace': get_size(disk_info.free)
}
except Exception:
pass
return info if info else False
return False
# Network Information
def nic_psutil() -> (dict, bool):
nic = dict()
for item in net_if_addrs():
if "loopback" in item.lower():
continue
nic[item] = dict()
for adapt in net_if_addrs()[item]:
match adapt.family:
case -1:
nic[item].update({"MACAddress": adapt.address})
case 2:
nic[item].update({"IPv4Address": adapt.address,
"IPSubnet": adapt.netmask})
case 23:
nic[item].update({"IPv6Address": adapt.address})
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": "Название службы", "Architecture": "Архитектура", "L2CacheSize": "Размер кэша L2",
"L3CacheSize": "Размер кэша L3", "Load": "Загрузка", "FreeMemory": "Свободная память",
"UsedMemory": "Занятая память", "TotalMemory": "Общее количество памяти", "GPUTemp": "Температура GPU",
"Mountpoint": "Точка монтирования", "TotalSpace": "Размер", "UsedSpace": "Занято",
"FreeSpace": "Свободно", "PercentUsed": "Процент использования", "EditionID": "Идентификатор редакции",
"Identifier": "Идентификатор"}
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 := platform_os():
print_wmic("Информация об операционной системе\n", os_info)
if bios_info := bios_wmi():
print_wmic("Информация о BIOS\n", bios_info)
if mb_info := motherboard_win32com():
print_wmic("Информация о материнской плате\n", mb_info)
if cpu_info := cpu_cpuinfo():
print_wmic("Информация о процессоре\n", cpu_info)
if gpu := gpu_info():
print_wmic("Информация о видеокарте\n", gpu)
if mem_info := memory_wmi():
print_wmic("Информация об оперативной памяти\n", mem_info)
if drive_info := hdd_ssd_psutil():
print_wmic("Информация о HDD и SSD\n", drive_info)
if cd_rom_info := cdrom_psutil():
print_wmic("Информация о CD/DVD-ROM\n", cd_rom_info)
if nic_info := nic_psutil():
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()
Теперь давайте проверим скорость работы получившегося «франкенштейна» и сравним ее со скоростью работы скриптов, которые мы написали в предыдущих статьях.
- Итак, как мы видим, на первом месте по-прежнему скрипт, который использует для получения данных библиотеку winreg и читает ее из реестра;
- На втором расположился, как это ни странно, текущий «франкенштейн»;
- Третье место – библиотека subprocess и утилита wmic;
- Четвертое, почетное место – библиотека wmi.
Таким образом, у нас определились явные победители данного «соревнования». Но, сборный скрипт я буду составлять из библиотек, которые идут в python «из коробки». Даже, если они используют стороннюю утилиту для сбора информации.
Для сборки составного скрипта за основу я решил взять тот, что использует модуль winreg. И, несмотря на то, что информация, которую получает данный модуль, не является полной, он все же показывает самую большую скорость работы. А дополнять его я буду функциями из скрипта, который использует subprocess и утилиту командной строки wmic, потому, что кроме «франкенштейна», у него неплохая скорость работы.
А добавим мы функцию для получения информации об оперативной памяти. Потому как я не нашел веток в реестре, где можно было бы почерпнуть данную информацию. Хотя, они наверняка есть. А также заменим функции для получения данных о HDD/SSD и CD/DVD-ROM, так как функции из скрипта использующего subprocess предоставляют больше информации.
Расписывать создание составного скрипта не имеет большого смысла. Вот, что у меня получилось в итоге:
Python:
# pip install python-docx windows-tools
import time
from datetime import datetime as dt, timedelta
from platform import node
from struct import unpack
from winreg import OpenKeyEx, QueryValueEx, HKEY_LOCAL_MACHINE, QueryInfoKey, EnumKey, KEY_READ
from subprocess import check_output
from wmi import WMI
from docx import Document
from windows_tools import product_key
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
# Узнаем версию ОС
def winreg_os() -> (dict, bool):
try:
win_info = dict()
if comp_info := OpenKeyEx(HKEY_LOCAL_MACHINE, r"SYSTEM\CurrentControlSet\Control\ComputerName\ComputerName"):
win_info.update({'ComputerName': QueryValueEx(comp_info, 'ComputerName')[0]})
if comp_shutdown := OpenKeyEx(HKEY_LOCAL_MACHINE, r"SYSTEM\CurrentControlSet\Control\Windows"):
shutdown_time_bin = QueryValueEx(comp_shutdown, 'ShutdownTime')[0]
shutdown_time = (dt(1601, 1, 1) + timedelta(microseconds=float(unpack("<Q", shutdown_time_bin)[0]) / 10)). \
strftime('%Y-%m-%d %H:%M:%S')
win_info.update({'ShutdownTime': shutdown_time})
if win_ver := OpenKeyEx(HKEY_LOCAL_MACHINE, r"SOFTWARE\Microsoft\Windows NT\CurrentVersion"):
for key in ["ProductName", "EditionID", "DisplayVersion", "CurrentBuild", "UBR", "InstallDate",
"RegisteredOwner"]:
try:
if key == "InstallDate":
win_info.update({key: str(dt.fromtimestamp(QueryValueEx(win_ver, f'{key}')[0]))})
else:
win_info.update({key: QueryValueEx(win_ver, f'{key}')[0]})
except FileNotFoundError:
continue
if tz_key := OpenKeyEx(HKEY_LOCAL_MACHINE, r"SYSTEM\CurrentControlSet\Control\TimeZoneInformation"):
win_info.update({"TimeZone": QueryValueEx(tz_key, 'TimeZoneKeyName')[0]})
if pkey := product_key.get_windows_product_key_from_reg():
win_info.update({"ActivateKey": pkey})
elif pkey := product_key.get_windows_product_key_from_wmi():
win_info.update({"ActivateKey": pkey})
else:
win_info.update({"ActivateKey": "No Key"})
return win_info if win_info else False
except Exception:
return False
# OS
def wmic_os() -> (dict, bool):
os_info = dict()
try:
os_i = check_output("wmic OS get Caption, InstallDate, Version, WindowsDirectory, LastBootUpTime /value",
shell=True).decode().strip()
except UnicodeDecodeError:
os_i = check_output("wmic OS get Caption, InstallDate, Version, WindowsDirectory, LastBootUpTime /value",
shell=True).decode("cp866").strip()
if os_i:
out = [{x.strip().split("=")[0]: x.strip().split("=")[1]} for x in os_i.splitlines() if x.strip()]
if comp_name := check_output("wmic computersystem get name /value", shell=True).decode().strip():
os_info.update({"ComputerName": comp_name.split("=")[1].strip()})
for item in out:
for it in item:
if item[it]:
if it == "InstallDate":
date = dt.strptime(item[it][:len(item[it]) - 4], '%Y%m%d%H%M%S.%f').strftime(
"%Y-%m-%d %H:%M:%S")
item = {"InstallDate": date}
if it == "LastBootUpTime":
date = dt.strptime(item[it][:len(item[it]) - 4], '%Y%m%d%H%M%S.%f').strftime(
"%Y-%m-%d %H:%M:%S")
item = {"LastBootUpTime": date}
os_info.update(item)
if tz_get := check_output("wmic TIMEZONE get Caption /value", shell=True).decode().strip():
tz = [{"TimeZone": x.strip().split("=")[1]} for x in tz_get.splitlines() if x.strip()]
os_info.update(tz[0])
if user_get := check_output('wmic USERACCOUNT Where (Status="OK") get Name /value', shell=True).decode().strip():
user = [{"UserName": x.strip().split("=")[1]} for x in user_get.splitlines() if x.strip()]
os_info.update(user[0])
return os_info if os_info else False
# BIOS
def bios_winreg() -> (dict, bool):
md_dict = dict()
if sbv := OpenKeyEx(HKEY_LOCAL_MACHINE, r"HARDWARE\DESCRIPTION\System"):
md_dict.update({"SystemBiosVersion": QueryValueEx(sbv, "SystemBiosVersion")[0][0]})
for key in ["BIOSVendor", "BIOSVersion", "BIOSReleaseDate"]:
if bios := OpenKeyEx(HKEY_LOCAL_MACHINE, r"HARDWARE\DESCRIPTION\System\BIOS"):
try:
md_dict.update({key: QueryValueEx(bios, key)[0]})
except FileNotFoundError:
continue
else:
return False
return md_dict if md_dict else False
# BIOS
def bios_wmic() -> (dict, bool):
bios_info = dict()
if bios := check_output("wmic BIOS get Version, Manufacturer, Name /value", shell=True).decode(). \
strip():
out = [{f'{x.strip().split("=")[0]}': x.strip().split("=")[1]} for x in bios.splitlines() if x.strip()]
for item in out:
bios_info.update(item)
return bios_info if bios_info else False
return False
# Материнская плата
def motherboard_winreg() -> (dict, bool):
md_dict = dict()
if mb_info := OpenKeyEx(HKEY_LOCAL_MACHINE, r"SYSTEM\CurrentControlSet\Control\SystemInformation"):
md_dict.update({'SystemManufacturer': QueryValueEx(mb_info, 'SystemManufacturer')[0]})
md_dict.update({'SystemProductName': QueryValueEx(mb_info, 'SystemProductName')[0]})
return md_dict if md_dict else False
return False
# Motherboard
def motherboard_wmic() -> (dict, bool):
mb_info = dict()
if mb_get := check_output("wmic baseboard get Product, Manufacturer /value", shell=True).decode().strip():
out = [{f'{x.strip().split("=")[0]}': x.strip().split("=")[1]} for x in mb_get.splitlines() if x.strip()]
for item in out:
mb_info.update(item)
return mb_info if mb_info else False
return False
# Memory
def memory_wmic() -> (dict, bool):
memory_info = dict()
if total_memory_get := check_output("wmic COMPUTERSYSTEM get TotalPhysicalMemory /value",
shell=True).decode().strip():
total_memory = [{x.strip().split("=")[0]: get_size(int(x.strip().split("=")[1]))}
for x in total_memory_get.splitlines() if x.strip()]
memory_info.update(total_memory[0])
if memory_tag_get := check_output("wmic MEMORYCHIP get Tag /value", shell=True).decode().strip():
memory_tag = [x.strip().split("=")[1] for x in memory_tag_get.splitlines() if x.strip()]
for tag in memory_tag:
info_get = check_output(f'wmic MEMORYCHIP Where (Tag="{tag}") get Capacity, ConfiguredClockSpeed, '
f'Manufacturer, PartNumber, SerialNumber /value', shell=True).decode().strip()
memory_info[tag.strip()] = dict()
for x in info_get.splitlines():
if x.strip():
if x.strip().split("=")[0] == "Capacity" and x.strip().split("=")[1]:
memory_info[tag.strip()].update({
x.strip().split("=")[0].strip(): get_size(int(x.strip().split("=")[1])).strip()
})
else:
memory_info[tag.strip()].update({
x.strip().split("=")[0].strip(): x.strip().split("=")[1].strip()
})
return memory_info if memory_info 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
# CPU
def cpu_winreg():
try:
proc_info = dict()
loc = "HARDWARE\\DESCRIPTION\\System\\CentralProcessor"
with OpenKeyEx(HKEY_LOCAL_MACHINE, loc) as h_apps:
if QueryInfoKey(h_apps)[0]:
proc_info.update({"CoreCount": QueryInfoKey(h_apps)[0]})
try:
core = OpenKeyEx(h_apps, EnumKey(h_apps, 0))
proc_info.update({
"ProcessorNameString": QueryValueEx(core, 'ProcessorNameString')[0].strip(),
"Identifier": QueryValueEx(core, 'Identifier')[0].strip(),
"VendorIdentifier": QueryValueEx(core, 'VendorIdentifier')[0].strip(),
"~MHz": QueryValueEx(core, '~MHz')[0]
})
except FileNotFoundError:
return False
return proc_info if proc_info else False
except Exception:
return False
# CPU
def cpu_wmic() -> (dict, bool):
mb_info = dict()
if mb_get := check_output("wmic cpu get Name, Caption, Manufacturer, SocketDesignation, MaxClockSpeed /value",
shell=True).decode().strip():
out = [{f'{x.strip().split("=")[0]}': x.strip().split("=")[1]} for x in mb_get.splitlines() if x.strip()]
for item in out:
mb_info.update(item)
if core_all := check_output("wmic COMPUTERSYSTEM get NumberOfLogicalProcessors /value",
shell=True).decode().strip():
mb_info.update({'NumberOfPhysicalProcessors': str(int(int(core_all.split("=")[1].strip()) / 2)),
f'{core_all.split("=")[0].strip()}': core_all.split("=")[1].strip()})
return mb_info if mb_info else False
# GPU
def gpu_wmic() -> (dict, bool):
gpu = dict()
if output := check_output('wmic path win32_VideoController get Name, AdapterRAM, VideoProcessor, '
'CurrentHorizontalResolution, CurrentVerticalResolution, CurrentRefreshRate /value',
shell=True).decode().strip():
out = [{x.strip().split("=")[0]: x.strip().split("=")[1]} for x in output.splitlines() if x.strip()]
res = ""
for vrm in out:
for vr in vrm:
if vr == 'AdapterRAM':
gpu.update({"AdapterRAM": get_size(int(vrm[vr]))})
continue
if vr == 'CurrentHorizontalResolution':
res += f'{vrm[vr]}x'
continue
if vr == 'CurrentVerticalResolution':
res += str(vrm[vr])
gpu.update({"Resolution": res})
continue
gpu.update(vrm)
return gpu if gpu else False
return 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
# HDD, SSD
def hdd_ssd_wmic() -> (dict, bool):
disk_info = dict()
if caption_get := check_output("wmic diskdrive get Caption /value", shell=True).decode().strip():
caption = [x.strip().split("=")[1] for x in caption_get.splitlines() if x.strip()]
for num, cap in enumerate(caption):
if info_get := check_output(
f'wmic diskdrive Where (Caption="{cap}") get DeviceID, FirmwareRevision, MediaType, '
f'Partitions, SerialNumber, Size /value', shell=True).decode().strip():
disk_info[f'{cap} {num}'] = dict()
disk_info[f'{cap} {num}'].update({"Product": cap})
for x in info_get.splitlines():
if x.strip():
if x.strip().split("=")[0] == "Size" and x.strip().split("=")[1]:
disk_info[f'{cap} {num}'].update({
f'{x.strip().split("=")[0].strip()}': get_size(int(x.strip().split("=")[1].strip()))
})
else:
disk_info[f'{cap} {num}'].update({
f'{x.strip().split("=")[0].strip()}': x.strip().split("=")[1].strip()
})
return disk_info if disk_info 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_wmic() -> (dict, bool):
cdrom_info = dict()
if caption_get := check_output("wmic CDROM get Caption /value", shell=True).decode().strip():
caption = [x.strip().split("=")[1] for x in caption_get.splitlines() if x.strip()]
for num, cap in enumerate(caption):
if info_get := check_output(
f'wmic CDROM Where (Caption="{cap}") get Drive, VolumeName, VolumeSerialNumber, Size '
f'/value', shell=True).decode().strip():
cdrom_info[cap] = dict()
cdrom_info[cap].update({"Product": cap})
for x in info_get.splitlines():
if x.strip():
if x.strip().split("=")[0].strip() == "Size" and x.strip().split("=")[1].strip():
cdrom_info[cap].update({
f'{x.strip().split("=")[0].strip()}': get_size(int(x.strip().split("=")[1].strip()))
})
cdrom_info[cap].update({
f'{x.strip().split("=")[0].strip()}': x.strip().split("=")[1].strip()
})
return cdrom_info if cdrom_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_winreg():
try:
nic = dict()
loc = r'SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkCards'
desc = []
if adapt_name := OpenKeyEx(HKEY_LOCAL_MACHINE, loc):
for idx in range(QueryInfoKey(adapt_name)[0]):
adapter = OpenKeyEx(adapt_name, EnumKey(adapt_name, idx))
nic[QueryValueEx(adapter, 'ServiceName')[0]] = dict()
nic[QueryValueEx(adapter, 'ServiceName')[0]].update({
"Description": QueryValueEx(adapter, 'Description')[0]
})
desc.append(QueryValueEx(adapter, 'Description')[0])
loc_adapt = r'SYSTEM\ControlSet001\Control\Class\{4d36e972-e325-11ce-bfc1-08002be10318}'
cfg = []
if adapt := OpenKeyEx(HKEY_LOCAL_MACHINE, loc_adapt):
for idc in range(QueryInfoKey(adapt)[0]):
try:
adpt = OpenKeyEx(adapt, EnumKey(adapt, idc))
if QueryValueEx(adpt, 'DriverDesc')[0] in desc:
nic[QueryValueEx(adpt, 'NetCfgInstanceId')[0]].update({
"Description": QueryValueEx(adpt, 'DriverDesc')[0]
})
cfg.append(QueryValueEx(adpt, 'NetCfgInstanceId')[0])
except (FileNotFoundError, PermissionError):
continue
inter = r'SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces'
if inter_cfg := OpenKeyEx(HKEY_LOCAL_MACHINE, inter):
for idb in range(QueryInfoKey(inter_cfg)[0]):
if EnumKey(inter_cfg, idb).upper() in cfg:
nic[EnumKey(inter_cfg, idb).upper()].update({
"NetCfgInstanceId": EnumKey(inter_cfg, idb).upper()})
intr = OpenKeyEx(inter_cfg, EnumKey(inter_cfg, idb))
try:
nic[EnumKey(inter_cfg, idb).upper()].update({
"DhcpDefaultGateway": QueryValueEx(intr, 'DhcpDefaultGateway')[0]})
except FileNotFoundError:
pass
try:
nic[EnumKey(inter_cfg, idb).upper()].update({
"DhcpIPAddress": QueryValueEx(intr, 'DhcpIPAddress')[0]})
except FileNotFoundError:
pass
try:
nic[EnumKey(inter_cfg, idb).upper()].update({
"DhcpIPAddress": QueryValueEx(intr, 'DhcpIPAddress')[0]})
except FileNotFoundError:
pass
netw = r'SYSTEM\ControlSet001\Control\Network\{4D36E972-E325-11CE-BFC1-08002BE10318}' + '\\' + \
EnumKey(inter_cfg, idb).upper() + '\\' + 'Connection'
if netw_cfg := OpenKeyEx(HKEY_LOCAL_MACHINE, netw):
nic[EnumKey(inter_cfg, idb).upper()].update({
"Name": QueryValueEx(netw_cfg, 'Name')[0]})
return nic if nic else False
except Exception:
return False
# Network Interface
def nic_wmic() -> (dict, bool):
nic_info = dict()
if description_get := check_output('wmic NIC Where (PhysicalAdapter="TRUE") get Description /value', shell=True). \
decode().strip():
description = [x.strip().split("=")[1] for x in description_get.splitlines() if x.strip()]
for nic in description:
try:
nic_d = check_output(
f'wmic NIC Where (Description="{nic}") get MACAddress, Manufacturer, NetConnectionID'
f' /value', shell=True).decode().strip()
except UnicodeDecodeError:
nic_d = check_output(
f'wmic NIC Where (Description="{nic}") get MACAddress, Manufacturer, NetConnectionID'
f' /value', shell=True).decode("cp866").strip()
try:
nicconfig_d = check_output(
f'wmic NICCONFIG Where (Description="{nic}") get DHCPServer, IPAddress /value',
shell=True).decode().strip()
except UnicodeDecodeError:
nicconfig_d = check_output(
f'wmic NICCONFIG Where (Description="{nic}") get DHCPServer, IPAddress /value',
shell=True).decode("cp866").strip()
nic_info[nic.strip()] = dict()
nic_info[nic.strip()].update({"Product": nic.strip()})
if nic_d:
for x in nic_d.splitlines():
if x.strip():
nic_info[nic.strip()].update({
x.strip().split("=")[0].strip(): x.strip().split("=")[1].strip()
})
if nicconfig_d:
for x in nicconfig_d.splitlines():
if x.strip():
nic_info[nic.strip()].update({
x.strip().split("=")[0].strip(): x.strip().split("=")[1].strip()
})
return nic_info if nic_info 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": "Название службы", "CurrentBuild": "Текущая сборка", "UBR": "Номер версии",
"RegisteredOwner": "Имя пользователя", "ActivateKey": "Ключ активации",
"SystemBiosVersion": "Версия Bios системы", "BIOSVendor": "Производитель", "BIOSVersion": "Версия",
"BIOSReleaseDate": "Дата выпуска релиза", "ShutdownTime": "Время выключения", "ProductName": "Название",
"EditionID": "Идентификатор редакции", "DisplayVersion": "Версия для отображения",
"SystemManufacturer": "Производитель", "SystemProductName": "Название сокета",
"CoreCount": "Количество ядер", "ProcessorNameString": "Название", "Identifier": "Идентификатор",
"VendorIdentifier": "Производитель", "~MHz": "Тактовая частота", "Vendor": "Производитель",
"Model": "Модель", "Revision": "Ревизия", "Description": "Название",
"NetCfgInstanceId": "Идентификатор", "DhcpDefaultGateway": "Шлюз по-умолчанию",
"DhcpIPAddress": "IP-адрес"}
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()}')
if os_info := winreg_os():
print_wmic("Информация об операционной системе\n", os_info)
else:
if os_wmic := wmic_os():
print_wmic("Информация об операционной системе\n", os_wmic)
if bios_info := bios_winreg():
print_wmic("Информация о BIOS\n", bios_info)
else:
if wmic_bios := bios_wmic():
print_wmic("Информация о BIOS\n", wmic_bios)
if mb_info := motherboard_winreg():
print_wmic("Информация о материнской плате\n", mb_info)
else:
if wmic_mb := motherboard_wmic():
print_wmic("Информация о материнской плате\n", wmic_mb)
if memory_info := memory_wmic():
print_wmic("Информация об оперативной памяти\n", memory_info)
else:
if mem_wmi := memory_wmi():
print_wmic("Информация об оперативной памяти\n", mem_wmi)
if cpu_info := cpu_winreg():
print_wmic("Информация о процессоре\n", cpu_info)
else:
if wmic_cpu := cpu_wmic():
print_wmic("Информация о процессоре\n", wmic_cpu)
if gpu_info := gpu_wmic():
print_wmic("Информация о видеокарте\n", gpu_info)
else:
if wmi_gpu := gpu_wmi():
print_wmic("Информация о видеокарте\n", wmi_gpu)
if drive_info := hdd_ssd_wmic():
print_wmic("Информация о HDD и SSD\n", drive_info)
else:
if wmi_drive := hdd_ssd_wmi():
print_wmic("Информация о HDD и SSD\n", wmi_drive)
if cd_rom_info := cdrom_wmic():
print_wmic("Информация о CD/DVD-ROM\n", cd_rom_info)
else:
if wmi_cdrom := cdrom_wmi():
print_wmic("Информация о CD/DVD-ROM\n", wmi_cdrom)
if nic_info := nic_winreg():
print_wmic("Информация о физических сетевых интерфейсах\n", nic_info)
else:
if wmic_nic := nic_wmic():
print_wmic("Информация о физических сетевых интерфейсах\n", wmic_nic)
document.add_paragraph(wmic_info)
document.save(f'{node()}.docx')
print(f"Собранная информация сохранена в файл: {node()}.docx")
print(f'\nВремя работы скрипта: {time.monotonic() - t} с.')
if __name__ == "__main__":
main()
А теперь, протестируем скорость его работы.
Что ж, скорость работы получилась удовлетворительной. Конечно, не так быстро, как чистый скрипт с winreg, но и гораздо быстрее, чем скрипты использующие другие библиотеки.
А на этом мы закончим статьи о получении информации об ОС и железе в Windows.
Спасибо за внимание. Надеюсь, данная информация будет вам полезна
Вложения
Последнее редактирование модератором: