Эта статья является продолжением двух предыдущих статей: раз, два о способах получения информации об операционной системе и железе компьютера с помощью стандартных модулей Python. И если в первых двух статьях были рассмотрены такие модули как: winreg, для получения информации из реестра; subprocess.check_out для получения вывода консольной утилиты wmic, то здесь мы рассмотрим еще один модуль из стандартных библиотек – wmi.
WMI – это инструментарий управления Windows. Сам по себе инструментарий, это расширенная и адаптированная под Windows технология WBEM. В основе данной технологии лежит идея создания универсального интерфейса для управления, а также мониторинга различными системами и компонентами информационной среда. К слову, утилита wmic, это, по сути, надстройка над WMI, для упрощения взаимодействия с данным инструментарием.
В Python «из коробки» доступна библиотека wmi, как раз таки для взаимодействия с данным инструментарием. И именно ее мы будем использовать в создаваемом скрипте для получения информации.
Что потребуется?
Как и в предыдущих статьях я добавил в скрипт стороннюю библиотеку python-docx, с помощью которой создается документ Microsoft Word, в который и сохраняется вся полученная информация. Для установки данной библиотеки пишем в терминале команду:
Однако вы можете использовать различные способы для сохранения. От csv до json. Просто, в рамках данной статьи данный способ показался мне удобным.
После того, как будут установлены необходимые библиотеки, импортируем все, что нам необходимо в создаваемый скрипт.
Для начала создадим вспомогательную функцию, с помощью которой будем переводить размеры из байтов или мегабайтов в нужные нам, для облегчения восприятия информации.
Создадим функцию get_size(bts: int, ending='iB') -> str, которая на входе получает целое число, а возвращает строку с конвертированными данными. Ну, а дальше все просто. Выполняем итерации до тех пор, пока исходное значение не будет меньше 1024. И после возвращаем размер.
Теперь давайте приступим к написанию функций для получения информации. В конце данной статьи проведем небольшое сравнение скорости работы текущего скрипта, с написанными ранее.
Получение информации об операционной системе
Создадим функцию wmi_os() -> dict, которая возвращает словарь с полученными значениями. Создадим объект WMI и обратимся к методу Win32_ComputerSystem. С помощью данного метода получим имя компьютера и добавим его в словарь.
Теперь необходимо получить информацию о пользователях системы. Так как их может быть несколько, получаем информацию по каждому из них и сохраняем в список.
Затем обращаемся к методу Win32_OperatingSystem и получаем такую информацию, как: название ОС, время последней загрузки, которое тут же переводим в человекочитаемый формат. Версию ОС, номер сборки, дату установки операционной системы, директорию установки. Добавляем полученные данные в результирующий словарь. Также добавляем в словарь список с именами пользователей. После того, как информация будет получена, возвращаем результирующий словарь из функции, если он не пуст.
Получение информации о BIOS
Создадим функцию bios_wmi() -> (dict, bool), которая возвращает словарь с полученными значениями. Также создаем объект WMI. Получаем словарь со значениями из метода Win32_BIOS, затем получаем производителя, имя и версию. Добавляем полученные значения в результирующий словарь и возвращаем его из функции, если словарь не пуст.
Получение информации о материнской плате
Создадим функцию motherboard_wmi() -> (dict, bool), возвращающую словарь с полученными значениями. Создаем объект WMI. Обращаемся к методу Win32_BaseBoard, получаем словарь со значениями и забираем информацию о производителе и модели материнской платы. Добавляем полученные данные в результирующий словарь, после чего возвращаем его из функции, если он не пуст.
Получаем информацию о процессоре
Создаем функцию cpu_wmi() -> (dict, bool), возвращающую словарь с полученными значениями. Как и в предыдущих функциях создаем объект WMI. Обращаемся к методу Win32_Processor и забираем словарь со значениями, после чего, добавляем данные значения в результирующий словарь и возвращаем из функции, если он не пуст.
Получаем информацию о видеоадаптере
Создадим функцию gpu_wmi() -> (dict, bool). Она будет возвращать словарь с полученными значениями. Создаем объект WMI и обращаемся к методу Win32_VideoController. Забираем значения: название, видеопамять, разрешение, частоту и видеопроцессор. Добавляем полученные данные в результирующий словарь и возвращаем его из функции, если он не пуст.
Получаем информацию об оперативной памяти
Создадим функцию memory_wmi() -> (dict, bool), которая возвращает словарь с полученными значениями. Создаем объект WMI. Получаем данные о суммарном объеме оперативной памяти и добавляем полученное значение в результирующий словарь.
Затем итерируемся по полученным данным и забираем значения отдельно для каждой планки оперативной памяти. Создаем для каждой планки словарь и наполняем его полученными значениями. Затем возвращаем результирующий словарь из функции, если он не пуст.
Получаем информацию о HDD/SSD
Создадим функцию hdd_ssd_wmi() -> (dict, bool). Она будет возвращать словарь с полученными значениями. Затем создаем объект WMI, Получаем информацию о дисках с помощью метода Win32_DiskDrive, итерируемся по полученным значениям. Создаем отдельный словарь для каждого диска и добавляем значения в созданный словарь. Затем возвращаем результирующий словарь из функции, если он не пуст.
Получаем информацию о CD/DVD-ROM
Для получения информации о приводах создадим функцию cdrom_wmi() -> (dict, bool). Как и все предыдущие функции, она будет возвращать словарь с полученными значениями. Создадим объект WMI. Обратимся к методу Win32_CDROMDrive. В цикле проитерируемся по полученным значениям. Создадим для каждого привода отдельный словарь и наполним его полученными значениями. После чего, вернем результирующий словарь из функции, если он не пуст.
Получаем данные о сетевых адаптерах
Создадим функцию nic_wmi() -> (dict, bool). Данная функция также возвращает словарь с информацией о каждом физическом сетевом адаптере. Создаем объект WMI, получаем описание каждого физического сетевого адаптера и складываем его в список. Оно пригодится нам далее. Итерируемся по полученным значениям, проверяем, не равно ли описание адаптера тому, что у нас в списке. Если да, создаем для адаптера словарь и заполняем его данными. После чего, возвращаем результирующий словарь из функции, если он не пуст.
На этом закончим получение информации. Теперь необходимо создать функцию для печати и сохранения полученных значений.
Функция для печати полученных значений из словарей
Создадим функцию print_wmic(part, dict_info). На входе она получает строку с описанием данных содержащихся в словаре. И собственно сам словарь, из которого нужно получить и вывести информацию в терминал и добавить в строковую переменную. Данную переменную мы создадим глобально: wmic_info = "".
Теперь создадим словарь синонимов. Они будут необходимы при печати данных, чтобы распечатывались не значения из словаря, а их синонимы на русском языке.
Ну и дальше, точно такая же функция, как и в предыдущих статьях. Использую ее, потому, что удобно. Итерируемся по переданному в функцию словарю. Проверяем тип значения по ключу. Если тип значения словарь, итерируемся по нему, забираем данные и добавляем в строковую переменную part. Если тип не словарь, добавляем текущий ключ и значение. Так же, все собранные данные добавляем в строковую глобальную переменную wmic_info.
Функция main
И еще одна функция, в которой мы будем запускать функции, получать из них словари. И если они будут получены, то запускать функцию печати. Также, здесь создаем документ Microsoft Word, в который для начала добавляем заголовок. А затем уже в конце, когда отработают все функции, добавляем параграф, куда передаем значение строковой переменной wmic_info. После сохраняем документ с именем компьютера. И выводим для пользователя информацию о сохраненном документе, а также время работы скрипта.
Теперь протестируем созданный скрипт на скорость работы и попробуем сравнить с другими скриптами, которые были описаны ранее, в предыдущих частях.
Как видим, на последнем месте текущий скрипт. Неожиданно, скрипт использующий для сбора информации вывод утилиты wmic оказался на втором месте. Ну и по скорости сбора лидирует скрипт, который собирает информацию из реестра. Что не удивительно. Так как данные берутся не с помощью опроса оборудования, а напрямую.
В следующий раз рассмотрим сбор информации с помощью сторонних библиотек. Это будет так еще сборная солянка. А заодно сравним все способы. Также постараюсь объединить самые быстрые способы. И протестировать время. По сути, если их комбинировать, то получить информации можно гораздо больше, чем при использовании только одного способа.
А на этом, пожалуй, все.
Спасибо за внимание. Надеюсь, данная информация будет вам полезна
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()
Теперь протестируем созданный скрипт на скорость работы и попробуем сравнить с другими скриптами, которые были описаны ранее, в предыдущих частях.
Как видим, на последнем месте текущий скрипт. Неожиданно, скрипт использующий для сбора информации вывод утилиты 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()
А на этом, пожалуй, все.
Спасибо за внимание. Надеюсь, данная информация будет вам полезна
Вложения
Последнее редактирование: