使用Python进行Windows系统管理
手动管理Windows系统管理的活动可能非常耗费精力。如果我们能够使用几行Python代码来代替手动管理这些任务会怎样?在下面的教程中,我们将了解一个允许程序基于系统管理执行不同进程的模块,这个Python模块被称为WMI模块。
WMI ,即Windows管理工具,是微软对于DMTF的通用信息模型(简称CMI)的实现,DMTF是一种厂商中立的行业标准方法用于展示管理信息。它允许程序员通过具有适当权限的所需代理查询任何计算机上的几乎任何数据。
Python提供了 wmi 模块,它作为一个简单的封装,围绕着可用的 WMI 类和功能,供系统管理员使用来从本地或远程的Windows机器查询数据。
在本教程中,我们将了解如何使用 wmi 模块来执行基于Windows系统管理的各种活动。但在开始之前,让我们先安装所需的模块。
如何安装Python wmi模块
为了安装Python模块,我们需要“pip”,这是一个用于管理从可信公共存储库安装模块所需的包的框架。一旦我们有了“pip”,我们就可以使用以下命令从Windows命令提示符(CMD)或终端安装 wmi 模块:
语法:
$ python.exe -m pip install wmi
验证安装
模块安装完成后,我们可以通过创建一个空的Python程序文件并写入一个 import 语句来验证它,如下所示:
文件:verify.py
import wmi
现在,保存上述文件并在终端中使用以下命令执行:
语法:
$ python verify.py
如果上述的Python程序文件没有返回任何错误,那么该模块已经正确安装。然而,在出现异常的情况下,尝试重新安装该模块,并建议参考该模块的官方文档。
建立连接
在下面的部分中,我们将通过建立与一台机器的连接来开始。大多数情况下,我们将使用以下Python语法连接到本地机器:
语法:
# connecting to local machine
my_connection = wmi.WMI()
假设我们想要连接到远程机器。在这种情况下,我们必须提供一个机器名(或者IP地址)并使用以下参数,如’ 用户 ‘和’ 密码 ‘来传递凭据,以便我们可以验证该账户并建立远程WMI连接。
示例:
# importing the required module
import wmi
# connecting to a remote machine
my_connection = wmi.WMI("13.78.128.231", user = r"mango", password = "mango@123")
找到一个WMI类
现在我们已经建立了连接,然而,要查询关于系统的具体信息,我们必须先找到能提供这些信息的WMI类。我们还可以使用WMI对象的“classes”属性,例如wmi.WMI().classes,来返回WMI类的列表。
从这些提取出来的类中,我们可以使用特定的关键词来过滤,以找到我们正在寻找的特定类,如下例所示:
示例:
# importing the required module
import wmi
# connecting to a local machine
my_connection = wmi.WMI()
# extracting the class names from WMI
for className in my_connection.classes:
if 'Process' in className:
print(className)
输出:
Win32_ProcessStartTrace
Win32_PerfFormattedData_PerfOS_Processor
Win32_PerfFormattedData_PerfProc_Process
Win32_SessionProcess
Win32_PerfRawData_PerfProc_Process
Win32_PerfRawData_Counters_PerProcessorNetworkInterfaceCardActivity
Win32_PerfRawData_LSM_UserInputDelayperProcess
Win32_PerfFormattedData_Counters_ProcessV2
Win32_PerfFormattedData_LSM_UserInputDelayperProcess
Win32_PerfFormattedData_Counters_PerProcessorNetworkInterfaceCardActivity
Win32_Processor
Win32_ProcessTrace
CIM_OSProcess
CIM_ProcessExecutable
CIM_Processor
CIM_AssociatedProcessorMemory
Win32_ComputerSystemProcessor
Win32_PerfFormattedData_GPUPerformanceCounters_GPUProcessMemory
Win32_PerfRawData_HvStats_HyperVHypervisorLogicalProcessor
Win32_PerfFormattedData_Counters_ProcessorInformation
CIM_ProcessThread
CIM_Process
Win32_PerfFormattedData_Counters_PerProcessorNetworkActivityCycles
Win32_AssociatedProcessorMemory
Win32_PerfRawData_HvStats_HyperVHypervisorRootVirtualProcessor
Win32_PerfFormattedData_Counters_SecurityPerProcessStatistics
Win32_ProcessStartup
Win32_PerfRawData_GPUPerformanceCounters_GPUProcessMemory
Win32_PerfRawData_Counters_ProcessorInformation
Win32_PerfRawData_Counters_ProcessV2
Win32_PerfRawData_Counters_PerProcessorNetworkActivityCycles
Win32_PerfRawData_Counters_SecurityPerProcessStatistics
Win32_PerfFormattedData_HvStats_HyperVHypervisorLogicalProcessor
Win32_Process
Win32_PerfFormattedData_HvStats_HyperVHypervisorRootVirtualProcessor
Win32_NamedJobObjectProcess
Win32_SystemProcesses
Win32_ProcessStopTrace
Win32_PerfRawData_PerfOS_Processor
说明:
在上面的代码片段中,我们导入了 wmi 模块并建立了与本地机器的连接。然后,我们使用 for 循环遍历模块中的每个类来提取类名。
查找WMI类的方法和属性
即使我们知道 WMI 类的名称,我们仍然需要知道这些类提供的属性的准确名称和可以执行特定操作的方法。为了检索特定 WMI 类的方法和属性,我们可以创建一个 WMI 连接并利用点运算符(.)和’类名’来访问命名空间,然后使用’ properties ‘或’ methods ‘属性返回一个Python属性/方法名称的列表。
让我们来看一个示例来演示相同的情况:
例:
# importing the wmi module
import wmi
# printing all properties
print("Properties of WMI class:")
print(wmi.WMI().Win32_Process.methods.keys())
# printing all methods
print("\nMethods of WMI class:")
print(wmi.WMI().Win32_Process.properties.keys())
输出:
Properties of WMI class:
dict_keys(['Create', 'Terminate', 'GetOwner', 'GetOwnerSid', 'SetPriority', 'AttachDebugger', 'GetAvailableVirtualSize'])
Methods of WMI class:
dict_keys(['Caption', 'CommandLine', 'CreationClassName', 'CreationDate', 'CSCreationClassName', 'CSName', 'Description', 'ExecutablePath', 'ExecutionState', 'Handle', 'HandleCount', 'InstallDate', 'KernelModeTime', 'MaximumWorkingSetSize', 'MinimumWorkingSetSize', 'Name', 'OSCreationClassName', 'OSName', 'OtherOperationCount', 'OtherTransferCount', 'PageFaults', 'PageFileUsage', 'ParentProcessId', 'PeakPageFileUsage', 'PeakVirtualSize', 'PeakWorkingSetSize', 'Priority', 'PrivatePageCount', 'ProcessId', 'QuotaNonPagedPoolUsage', 'QuotaPagedPoolUsage', 'QuotaPeakNonPagedPoolUsage', 'QuotaPeakPagedPoolUsage', 'ReadOperationCount', 'ReadTransferCount', 'SessionId', 'Status', 'TerminationDate', 'ThreadCount', 'UserModeTime', 'VirtualSize', 'WindowsVersion', 'WorkingSetSize', 'WriteOperationCount', 'WriteTransferCount'])
说明:
在上面的代码片段中,我们导入了所需的模块。然后我们使用 WMI() 建立了与远程计算机的连接。然后我们写下了WMI类的名称,后面紧跟着点运算符(.),以及关键词 ‘properties’ 和 ‘methods’ ,以打印出所有用户的属性和方法。
处理过程
由于我们已经收集了关于Win32_Process类的方法和属性的信息,现在我们将使用WMI类的类名,后面跟着一个开放和关闭的括号,以返回WMI类的对象。
让我们来看下面的示例,演示了相同的过程:
示例:
# importing the wmi module
import wmi
# establishing the connection with a local machine
my_connection = wmi.WMI()
# processing list
for process in my_connection.Win32_Process():
print("ID: {0}\nHandle Count: {1}\nProcess Name: {2}\n".format(
process.ProcessId, process.HandleCount, process.Name
)
)
输出:
ID: 0
Handle Count: 0
Process Name: System Idle Process
ID: 4
Handle Count: 5863
Process Name: System
ID: 160
Handle Count: 0
Process Name: Registry
ID: 540
Handle Count: 57
Process Name: smss.exe
ID: 788
Handle Count: 773
Process Name: csrss.exe
ID: 892
Handle Count: 149
Process Name: wininit.exe
ID: 912
Handle Count: 765
Process Name: csrss.exe
ID: 964
Handle Count: 714
Process Name: services.exe
ID: 984
Handle Count: 1571
Process Name: lsass.exe
ID: 568
Handle Count: 267
Process Name: winlogon.exe
ID: 1056
Handle Count: 1746
Process Name: svchost.exe
ID: 1084
Handle Count: 33
Process Name: fontdrvhost.exe
.
.
.
ID: 14104
Handle Count: 301
Process Name: python3.9.exe
解释:
在以上的代码片段中,我们导入了 wmi 模块,并与本地机器建立了成功的连接。我们使用 for 循环遍历每个进程的ID、句柄计数和进程名称来提取进程列表。
我们还可以通过进程名称和属性来过滤这些进程,只打印选择的进程。例如,我们想选择所有名为’ code.exe ‘的正在本地运行的进程,然后通过条件语句过滤出句柄计数超过 100 的进程: **if
让我们考虑以下脚本以理解相同的情况:
示例:
# importing the wmi module
import wmi
# establishing the connection with a local machine
my_connection = wmi.WMI()
# filtering specific processes
for process in my_connection.Win32_Process(name = "code.exe"):
if process.HandleCount > 100:
# only processes with Handle Count above 100
print("ID: {0}\nHandle Count: {1}\nProcess Name: {2}\n".format(
process.ProcessId, process.HandleCount, process.Name
)
)
输出:
ID: 10464
Handle Count: 859
Process Name: Code.exe
ID: 14796
Handle Count: 228
Process Name: Code.exe
ID: 12388
Handle Count: 704
Process Name: Code.exe
ID: 2504
Handle Count: 284
Process Name: Code.exe
ID: 1044
Handle Count: 485
Process Name: Code.exe
ID: 12668
Handle Count: 334
Process Name: Code.exe
ID: 8088
Handle Count: 362
Process Name: Code.exe
ID: 10720
Handle Count: 180
Process Name: Code.exe
ID: 8976
Handle Count: 210
Process Name: Code.exe
ID: 14804
Handle Count: 278
Process Name: Code.exe
解释:
在上面的代码片段中,我们再次导入了 wmi 模块并与本地计算机建立了连接。然后,我们使用 for 循环遍历 WMI 类中的进程,并指定要过滤的进程的名称。我们还包括了if条件语句,以便仅打印那些处理句柄计数大于 100 的进程详细信息。
WMI模块还允许程序员开始一个新进程并终止任何现有进程。
让我们考虑以下示例,演示了相同的情况,我们创建了一个新进程,然后将进程ID存储起来以便唯一标识该进程,以便以后使用该ID终止它:
示例:
# importing the wmi module
import wmi
# establishing the connection with the local machine
my_connection = wmi.WMI()
# starting a new process and capturing the process ID
process_id, return_val = my_connection.Win32_Process.Create(CommandLine = "notepad.exe")
# killing the process using process ID
my_connection.Win32_Process(ProcessId = process_id)[0].Terminate()
解释:
在上面的代码片段中,我们已经导入了 wmi 模块,并与本地机器建立了成功的连接。然后,我们使用 Create() 函数启动了一个新的进程,并存储了它的进程ID。最后,我们使用 Terminate() 函数终止了该进程。
处理服务
我们可以采用类似的方法,通过使用名为 Win32_Service 的 WMI 类来列出和筛选出正在运行在机器上的服务。
让我们考虑以下演示相同功能的代码片段:
示例:
# importing the wmi module
import wmi
# establishing connection with a local machine
my_connection = wmi.WMI()
# listing services
for service in my_connection.Win32_Service(StartMode = "Auto", State = "Running"):
# filtering the service names
if 'Windows' in service.DisplayName:
print("Status: {0} \nStart Mode: {1} \nService Name: {2} \nDisplay Name: {3} \n\n".format(
service.State, service.StartMode, service.Name, service.DisplayName
)
)
输出:
Status: Running
Start Mode: Auto
Service Name: AudioEndpointBuilder
Display Name: Windows Audio Endpoint Builder
Status: Running
Start Mode: Auto
Service Name: Audiosrv
Display Name: Windows Audio
Status: Running
Start Mode: Auto
Service Name: EventLog
Display Name: Windows Event Log
Status: Running
Start Mode: Auto
Service Name: FontCache
Display Name: Windows Font Cache Service
Status: Running
Start Mode: Auto
Service Name: mpssvc
Display Name: Windows Defender Firewall
Status: Running
Start Mode: Auto
Service Name: StiSvc
Display Name: Windows Image Acquisition (WIA)
Status: Running
Start Mode: Auto
Service Name: Wcmsvc
Display Name: Windows Connection Manager
Status: Running
Start Mode: Auto
Service Name: Winmgmt
Display Name: Windows Management Instrumentation
Status: Running
Start Mode: Auto
Service Name: WpnService
Display Name: Windows Push Notifications System Service
Status: Running
Start Mode: Auto
Service Name: WSearch
Display Name: Windows Search
Status: Running
Start Mode: Auto
Service Name: WpnUserService_a17f9
Display Name: Windows Push Notifications User Service_a17f9
解释:
在上面的代码片段中,我们导入了 wmi 模块并与本地机器建立了连接。然后,我们使用 for 循环来遍历 wmi 模块中的 Win32_Services 类,并根据给定的条件进行筛选。我们还使用条件语句来过滤所需的服务。
我们可以使用这些类执行其他几个功能,例如启动和停止服务等等。