python-window运维

Windows系统编程
Python是一门强大的脚本语言,它可以把其他语言编写的程序粘合在一起,可以很容易地调用外部程序,以及调用其他语言编写的动态链接库中的代码,甚至可以将Python程序打包为.exe可执行程序以便在没有安装Python的Windows系统中运行。

1. 注册表编程
对于Windows操作系统,注册表是非常重要的组成部分,Windows将几乎所有软/硬件系统配套信息都保存在注册表中。通过读取注册表中的数据,可以获取Windows平台的相应信息,比如,已安装的服务和程序列表,开机自动运行的程序列表、文件类型与程序的关联关系等;通过修改注册表中的数据,可以对Windows系统进行详细的配置。
Windows注册表有如下5个根键.

HKEY_LOCAL_MACHINE(HKLM)
HKEY_CURRENT_CONFIG(HKCC)
HKEY_CLASSES_ROOT(HKCR)
HKEY_USERS(HKU)
HKEY_CURRENT_USER(HKCU)
在Windows shell中输入regedit可以打开注册表编辑器:

在注册表编辑器界面中可以对注册表的键和值进行增删改查等操作
在注册表中,值可以为数值、字符串等多种类型,详细类型如下:
类型名 说明
REG_NONE 没有类型
REG_SZ 字符串类型
REG_EXPAND_SZ 一个可扩展的字符串值,其中可以包括环境变量
REG_BINARY 二进制类型
REG_DWORD/REG_DWORD_LITTLE_ENDIAN DWORD类型,用于存储32位无符号整数,以little-endian格式存储
REG_DWORD_BIG_ENDIAN DWORD类型,存储32位无符号整数,以big-endian格式存储
REG_LINK 到其他注册表键的链接,指定根键或到目标键的路径
REG_MULTI_SZ 一个多字符串值,指定一个非空字符串的排序列表
REG_RESOURCE_LIST 资源列表,用于枚举即插即用硬件及其配置
REG_FULL_RESOURCE_DESCRIPTOR 资源标识符,用于枚举即插即用硬件极其配置
REG_RESOURCE_REQUIREMENTS_LIST 资源需求列表,用于枚举即插即用硬件极其配置
REG_QWORD/REG_QWORD_LITTLE_ENDIAN QWORD类型,用于存储64位无符号整数,以littel-endian格式存储或未指定存储格式
对于注册表编程,可以使用win32api模块和win32con模块,其中win32api模块封装了Windows API 函数,提供了非常友好的接口。该模块中常用的注册表操作函数有8个。

RegOpenKey()/RegOpenKeyEx():打开注册表
RegCloseKey() :关闭注册表
RegQueryValue()/RegQueryValueEx():读取项值
RegCreateKey()/RegCreateKeyEx():添加项
RegDeleteKey():删除项
RegEnumKey():枚举子键
RegDeletetValue():删除值
例子,查询注册表并输出本机安装的IE浏览器软件版本信息:
import win32api
import win32con

key = win32api.RegOpenKey(win32con.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Microsoft\\Internet Explorer', 0,
win32con.KEY_ALL_ACCESS)
print(win32api.RegQueryValue(key,''))
print(win32api.RegQueryValueEx(key,'Version'))
print(win32api.RegQueryInfoKey(key))
win32api.RegCloseKey(key)
1
2
3
4
5
6
7
8
9
(该程序需要在管理员权限下运行)结果:


检测随系统启动而启动的程序列表
from win32api import *
from win32con import *


def get_values(fullname):
name = str.split(fullname, '\\', 1)
try:
if name[0] == 'HKEY_LOCAL_MACHINE':
key = RegOpenKey(HKEY_LOCAL_MACHINE, name[1], 0, KEY_READ)
elif name[0] == 'HKEY_CURRENT_USER':
key = RegOpenKey(HKEY_CURRENT_USER, name[1], 0, KEY_READ)
elif name[0] == 'HKEY_CLASSES_ROOT':
key = RegOpenKey(HKEY_CLASSES_ROOT, name[1], 0, KEY_READ)
elif name[0] == 'HKEY_CURRENT_CONFIG':
key = RegOpenKey(HKEY_CURRENT_CONFIG, name[1], 0, KEY_READ)
elif name[0] == 'HKEY_USERS':
key = RegOpenKey(HKEY_USERS, name[1], 0, KEY_READ)
else:
raise ValueError('Error,no key named', name[0])
info = RegQueryInfoKey(key)
for i in range(0, info[1]):
ValueName = RegEnumValue(key, i)
print(str.ljust(ValueName[0], 20), ValueName[1])
RegCloseKey(key)
except Exception as e:
print('Sth is wrong')
print(e)


if __name__ == '__main__':
KeyNames = ['HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run',
r'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce',
r'HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run',
r'HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\RunOnce']
for KeyName in KeyNames:
print('*'*30)
print(KeyName)
get_values(KeyName)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
结果:


操作Windows注册表的另外一种常用方式是使用Python模块winreg,该模块提供了OpenKey(),DeleteKey(),DeleteValue(),CreateKey(),SetValue(),QueryValueEx(),EnumValue()和EnumKey()等大量用于注册表访问和操作的方法。
有一篇博客总结得很好,详情

下面的代码演示了使用模块winreg枚举注册表值的用法:
import winreg

key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, r'Software\Microsoft\Windows\CurrentVersion\Explorer')
try:
i = 0
while 1:
Name, Value, Type = winreg.EnumValue(key, i)
print(repr(Name), ':', repr(Value), ':', Type)
i += 1
except WindowsError as e:
# print(e)
pass

"""
_winreg.QueryValueEx(key,value_name)
该函数用于获取某个key中指定value的data和type,返回类型是tuple
"""
print('=' * 20)
Name = 'link'
Value, Type = winreg.QueryValueEx(key, Name)
print(Name, Value)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
结果:


2.创建可执行文件
将Python程序转换为.exe版本可执行文件之后再发布,可以保证在没有安装Python环境的Windows平台上运行。为了将Python程序转换为.exe可执行文件,需要用到py2exe和distutils模块

py2exe 有一定的限制性,可用在python2版本以上或者python3.4版本以下

例如,将上面检测随系统启动而启动的程序列表的代码保存为文件CheckAndViewAutoRunsInSystem.py,然后编写setup.py文件,内容为:

import distutils
import py2exe
distutils.core.setup(console=['CheckAndViewAutoRunsInSystem.py']) # 对于GUI应用程序,应该将关键字console改为windows
1
2
3
最后在命令提示符下执行如下命令

python setup.py py2exe
1
如果创建成功会在当前文件夹下生成一个dist子文件夹,其中包含了最终程序执行所需要的所有内容。

另一个更好用的Python程序打包工具是pyinstaller,可以通过

pip install pyinstaller
1
来安装该工具。
安装好了之后直接在shell中使用命令

pyinstaller -F -w python文件名
1
即可将当前目录下的Python程序以及其依赖包打包称为python文件名.exe.

使用方法参考http://c.biancheng.net/view/2690.html

如果安装失败,可以尝试先运行这段shell

pip install future -i https://pypi.tuna.tsinghua.edu.cn/simple,
1
然后再

pip install pyinstaller
1
3. 调用外部程序
3.1 使用os模块的方法调用外部程序
import os
os.system('notepad.exe') # 打开系统自带的记事本
os.system('notepad c:\\dir.txt') # 用记事本文件编辑c盘下的dir,txt
1
2
3
0
1
使用上面的system方法也可以调用Windows系统命令,如dir,xcopy等,但有一个缺点,不论启动什么程序会先启动一个控制台窗口,然后再打开被调程序
也可以使用os模块的popen()方法打开外部程序,这样不会出现命令提示符窗口.

os.popen(r'C:\Program Files (x86)\Tencent\WeChat\WeChat.exe') # 打开微信
1
<os._wrap_close at 0x213dca90408>
1
或者,还可以使用os模块的startfile()方法来打开外部程序或文件,系统将自动关联相应的程序来打开或执行文件

os.startfile(r'C:\Users\ASUS\Desktop\CheckMD5OfFile.py') # 打开Py文件,系统会使用其模式打开方式打开它,我的就是pycharm
1
3.2 使用win32api模块用ShellExecute()函数来启动外部程序
具体用法

import win32api
win32api.ShellExecute(0,'open','notepad.exe','','',0) # 0表示后台运行程序
1
2
42
1
win32api.ShellExecute(0,'open','notepad.exe','','',1) # 1表示前台运行程序
1
42
1
win32api.ShellExecute(0,'open','notepad.exe',r'C:\Users\ASUS\Desktop\student.txt','',1) # 传递参数path打开指定文件
1
42
1
win32api.ShellExecute(0,'open','www.baidu.com',',','',1) # 打开网址
1
42
1
win32api.ShellExecute(0,'open',r'C:\Users\ASUS\Desktop\student.txt','','',1) # 相当于双击文件
1
42
1
使用这种方式运行程序或者打开文件时,不会像os模块的system()方法那样先打开一个cmd,并且系统将根据文件类型自动关联相应程序并打开文件,类似于双击打开文件。

3.3 通过创建进程来启动外部程序
import win32process
# 打开记事本程序
handle = win32process.CreateProcess(r'C:\windows\notepad.exe','',None,None,0,win32process.CREATE_NO_WINDOW,None,None,win32process.STARTUPINFO())
1
2
3
# 关闭刚刚打开的记事本程序
win32process.TerminateProcess(handle[0],0)
1
2
handle = win32process.CreateProcess(r'C:\windows\notepad.exe','',None,None,0,win32process.CREATE_NO_WINDOW,None,None,win32process.STARTUPINFO())
import win32event
win32event.WaitForSingleObject(handle[0],-1) # 设置打开的记事本程序需要手动关闭
1
2
3
0
1
3.4 通过ctypes来调用动态链接库代码
ctypes是Python处理动态链接库的标准扩展模块,提供了与C语言兼容的数据类型,允许再python程序中调用动态链接库或共享库中的代码,从而支持Python与其他编程语言的混合编程,充分发挥各自的优势,大幅提高开发效率和允许效率。
另外,NumPy模块也提供了一个函数numpy.ctypeslib.load_library()用来打开指定的动态链接库并返回一个ctypes对象,通过该对象可以访问动态链接库中的函数。
或者,使用SciPy库的Weave模块也可以方便地将C++程序以字符串的形式嵌入到Python程序中。
ctypes 提供了3种方法调用动态链接库:

cdll :cdll加载的库导出的函数必须使用标准的cdecl调用约定(函数的参数从右往左依次压入栈内,在函数执行完成后,由函数的调用者负责函数的栈帧平衡)
windll :windll加载的库导出的函数必须使用stdcall调用约定(Win32 API的原生约定)
oledll :oledll方法和windll类似,不过假设函数返回一个HRESULT错误代码
下面的代码调用Windows动态链接库user32.dll中的MessageBoxA()函数来显示对话框:

import ctypes
user32 = ctypes.windll.LoadLibrary('user32.dll')
user32.MessageBoxA(0,str.encode('Hello world!'),str.encode('Python ctypes'),0)
1
2
3
1
1
或者使用下面更为简洁的形式:

import ctypes
ctypes.windll.user32.MessageBoxA(0,str.encode('Hello world!'),str.encode('Python ctypes'),0)
1
2
1
1
下面的代码调用标准C函数库msvcrt中的printf()函数输出文本:

import ctypes
msvcrt = ctypes.cdll.LoadLibrary('msvcrt')
printf = msvcrt.wprintf
printf('hello world!')
1
2
3
4
12
1
或者使用下面形式:

import ctypes
ctypes.cdll.msvcrt.wprintf('hello python!')
1
2
13
1
上面的程序在jupternotebook中输出的是字符数量而不是字符,如果将上面的代码保存为.py文件,通过python命令符来运行就可以输出字符串。
ctypes提供了与C语言兼容的数据类型,但在Python中使用C语言的结构体时,需要通过类来改写。下表给出了基本类型的对应关系:

ctypes 类型 C 类型 Python 类型
c_bool _Bool bool (1)
c_char char 单字符字节对象
c_wchar wchar_t 单字符字符串
c_byte char 整型
c_ubyte unsigned char 整型
c_short short 整型
c_ushort unsigned short 整型
c_int int 整型
c_uint unsigned int 整型
c_long long 整型
c_ulong unsigned long 整型
c_longlong __int64 或 long long 整型
c_ulonglong unsigned __int64 或 unsigned long long 整型
c_size_t size_t 整型
c_ssize_t ssize_t 或 Py_ssize_t 整型
c_float float 浮点数
c_double double 浮点数
c_longdouble long double 浮点数
c_char_p char * (NUL terminated) 字节串对象或 None
c_wchar_p wchar_t * (NUL terminated) 字符串或 None
c_void_p void * int 或 None
枚举进程列表
from ctypes.wintypes import *
from ctypes import *
import collections

kernel32 = windll.kernel32


class tagPROCESSENTRY32(Structure):
"""定义结构体"""
_fields_ = [('dwSize', DWORD),
('cntUsage', DWORD),
('th32ProcessID', DWORD),
('th32DefaultHeapID', POINTER(ULONG)),
('th32ModuleID', DWORD),
('cntThreads', DWORD),
('th32ParentProcessID', DWORD),
('pcPriClassBase', LONG),
('dwFlags', DWORD),
('szExeFile', c_char * 260),
]


def enumProcess():
hSnapshot = kernel32.CreateToolhelp32Snapshot(15, 0)
fProcessEntry32 = tagPROCESSENTRY32()
processClass = collections.namedtuple("processInfo","processName processID")
processSet = []
if hSnapshot:
fProcessEntry32.dwSize = sizeof(fProcessEntry32)
listloop = kernel32.Process32First(hSnapshot,byref(fProcessEntry32))
while listloop:
processName = (fProcessEntry32.szExeFile)
processID = fProcessEntry32.th32ProcessID
processSet.append(processClass(processName,processID))
listloop=kernel32.Process32Next(hSnapshot,byref(fProcessEntry32))
return processSet

for i in enumProcess():
print("Name:",i.processName,"\tID:",i.processID)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
结果:

————————————————

4. 判断操作系统的版本
某些情况下,程序可能依赖于特定版本操作系统中的功能或者希望程序在不同版本的操作系统中有不同的表现,因此能够在程序运行时获知操作系统的版本就变得非常有必要。Python支持使用多种不同的方法来获取版本的操作信息。

使用os模块
import os
print(os.popen('ver').read())
1
2
Microsoft Windows [版本 10.0.17134.1365]
1
使用sys模块
import sys
print(sys.getwindowsversion())
1
2
sys.getwindowsversion(major=10, minor=0, build=17134, platform=2, service_pack='')
1
使用platform模块
import platform
print(platform.platform())
1
2
Windows-10-10.0.17134-SP0
1
Windows管理规范(WMI)是Windows的一项核心技术,它以公共信息模型对象管理器为基础,是一个描述Windows操作系统构成单元的对象数据库。WMI是Windows的核心组件,通过编写WMI脚本和应用程序可以获取计算机系统、软件和硬件信息,还可以对计算机进行管理,比如开关机,重启计算机等

import wmi
wmiShell = wmi.WMI()
print(wmiShell.Win32_OperatingSystem()[0].Caption)
1
2
3
Microsoft Windows 10 教育版
1
5. 系统运维
系统运维涉及的内容非常广泛,包括文件系统、数据库、用户账号的维护,任务调度与分配,CPU、内存、网络带宽、硬盘空间、IP地址等资源的分配与运行状态监测,等等。

Python标准库os提供了大量可用于系统运维的函数,如下表所示。另外,Python标准库sys,platform以及扩展库psutil等也提供了很多支持系统运维的功能。

5.1 Python扩展库psutil
跨平台的Python扩展库psutil可以用来查询进程或CPU,内存、硬盘以及网络等系统资源占用率等信息,常用于系统运行状态检测和维护。可以使用pip工具安装该库

查看CPU信息
import psutil
psutil.cpu_count() # 查看CPU核数
1
2
8
1
psutil.cpu_count(logical=False) # 查看物理CPU个数
1
4
1
psutil.cpu_percent() # 查看CPU利用率
1
5.5
1
psutil.cpu_percent(percpu=True) # 查看每个CPU的使用率
1
[9.6, 4.6, 6.8, 2.9, 5.3, 2.6, 4.1, 7.5]
1
psutil.cpu_times() # 查看CPU时间分配情况
1
scputimes(user=213684.48437499997, system=91249.70312499953, idle=2627046.046875, interrupt=5928.90625, dpc=2668.21875)
1
查看开机时间
import datetime
t = psutil.boot_time()
datetime.datetime.fromtimestamp(t).strftime('%Y-%m-%d %H:%M:%S')
1
2
3
'2020-04-03 20:44:02'
1
查看内存信息
virtual_memory = psutil.virtual_memory()
transimite = 1024*1024*1024
virtual_memory.total/transimite # 内存总大小,单位G
1
2
3
7.855434417724609
1
virtual_memory.used /transimite # 已使用内存
1
4.221714019775391
1
virtual_memory.free /transimite # 空闲内存
1
3.6337203979492188
1
virtual_memory.percent # 内存使用率
1
53.7
1
查看磁盘信息
psutil.disk_partitions() # 查看所有分区信息
1
[sdiskpart(device='C:\\', mountpoint='C:\\', fstype='NTFS', opts='rw,fixed'),
sdiskpart(device='D:\\', mountpoint='D:\\', fstype='NTFS', opts='rw,fixed'),
sdiskpart(device='E:\\', mountpoint='E:\\', fstype='NTFS', opts='rw,fixed')]
1
2
3
psutil.disk_usage('c:\\') # 查看指定分区的磁盘空间情况
1
sdiskusage(total=255087415296, used=119552417792, free=135534997504, percent=46.9)
1
psutil.disk_io_counters(perdisk=True) # 查看硬盘读写操作情况
1
{'PhysicalDrive0': sdiskio(read_count=841260, write_count=797732, read_bytes=51322807808, write_bytes=22576006656, read_time=14925, write_time=6073),
'PhysicalDrive1': sdiskio(read_count=19143288, write_count=1932248, read_bytes=188740736000, write_bytes=48545219584, read_time=13975, write_time=9851)}
1
2
查看网络信息
psutil.net_io_counters() # 流量与收发包信息
1
snetio(bytes_sent=6492719, bytes_recv=20874975, packets_sent=34273, packets_recv=39337, errin=0, errout=0, dropin=0, dropout=0)
1
psutil.net_if_addrs() # 网络连接信息
1
{'以太网': [snicaddr(family=<AddressFamily.AF_LINK: -1>, address='04-92-26-0B-A3-FD', netmask=None, broadcast=None, ptp=None),
snicaddr(family=<AddressFamily.AF_INET: 2>, address='169.254.206.44', netmask='255.255.0.0', broadcast=None, ptp=None),
snicaddr(family=<AddressFamily.AF_INET6: 23>, address='fe80::b557:5f36:f121:ce2c', netmask=None, broadcast=None, ptp=None)],
'本地连接* 2': [snicaddr(family=<AddressFamily.AF_LINK: -1>, address='B4-69-21-C7-22-CB', netmask=None, broadcast=None, ptp=None),
snicaddr(family=<AddressFamily.AF_INET: 2>, address='169.254.149.13', netmask='255.255.0.0', broadcast=None, ptp=None),
snicaddr(family=<AddressFamily.AF_INET6: 23>, address='fe80::3db3:d044:f5a3:950d', netmask=None, broadcast=None, ptp=None)],
'本地连接* 3': [snicaddr(family=<AddressFamily.AF_LINK: -1>, address='B6-69-21-C7-22-CA', netmask=None, broadcast=None, ptp=None),
snicaddr(family=<AddressFamily.AF_INET: 2>, address='169.254.108.36', netmask='255.255.0.0', broadcast=None, ptp=None),
snicaddr(family=<AddressFamily.AF_INET6: 23>, address='fe80::6db0:bd1d:8d20:6c24', netmask=None, broadcast=None, ptp=None)],
'以太网 2': [snicaddr(family=<AddressFamily.AF_LINK: -1>, address='00-FF-7E-88-A1-7D', netmask=None, broadcast=None, ptp=None),
snicaddr(family=<AddressFamily.AF_INET: 2>, address='169.254.58.37', netmask='255.255.0.0', broadcast=None, ptp=None),
snicaddr(family=<AddressFamily.AF_INET6: 23>, address='fe80::54ba:253f:faa5:3a25', netmask=None, broadcast=None, ptp=None)],
'VMware Network Adapter VMnet1': [snicaddr(family=<AddressFamily.AF_LINK: -1>, address='00-50-56-C0-00-01', netmask=None, broadcast=None, ptp=None),
snicaddr(family=<AddressFamily.AF_INET: 2>, address='192.168.232.1', netmask='255.255.255.0', broadcast=None, ptp=None),
snicaddr(family=<AddressFamily.AF_INET6: 23>, address='fe80::3d30:da6c:13bd:da5d', netmask=None, broadcast=None, ptp=None)],
'VMware Network Adapter VMnet0': [snicaddr(family=<AddressFamily.AF_LINK: -1>, address='00-50-56-C0-00-00', netmask=None, broadcast=None, ptp=None),
snicaddr(family=<AddressFamily.AF_INET: 2>, address='192.168.146.1', netmask='255.255.255.0', broadcast=None, ptp=None),
snicaddr(family=<AddressFamily.AF_INET6: 23>, address='fe80::c897:fd9a:5887:176a', netmask=None, broadcast=None, ptp=None)],
'VMware Network Adapter VMnet18': [snicaddr(family=<AddressFamily.AF_LINK: -1>, address='00-50-56-C0-00-12', netmask=None, broadcast=None, ptp=None),
snicaddr(family=<AddressFamily.AF_INET: 2>, address='192.168.80.1', netmask='255.255.255.0', broadcast=None, ptp=None),
snicaddr(family=<AddressFamily.AF_INET6: 23>, address='fe80::20cf:9b92:ab9c:ff0', netmask=None, broadcast=None, ptp=None)],
'WLAN': [snicaddr(family=<AddressFamily.AF_LINK: -1>, address='B4-69-21-C7-22-CA', netmask=None, broadcast=None, ptp=None),
snicaddr(family=<AddressFamily.AF_INET: 2>, address='192.168.0.104', netmask='255.255.255.0', broadcast=None, ptp=None),
snicaddr(family=<AddressFamily.AF_INET6: 23>, address='fe80::b497:808c:abbd:2bb6', netmask=None, broadcast=None, ptp=None)],
'蓝牙网络连接': [snicaddr(family=<AddressFamily.AF_LINK: -1>, address='B4-69-21-C7-22-CE', netmask=None, broadcast=None, ptp=None),
snicaddr(family=<AddressFamily.AF_INET: 2>, address='169.254.208.169', netmask='255.255.0.0', broadcast=None, ptp=None),
snicaddr(family=<AddressFamily.AF_INET6: 23>, address='fe80::5c09:e1fc:30da:d0a9', netmask=None, broadcast=None, ptp=None)],
'Loopback Pseudo-Interface 1': [snicaddr(family=<AddressFamily.AF_INET: 2>, address='127.0.0.1', netmask='255.0.0.0', broadcast=None, ptp=None),
snicaddr(family=<AddressFamily.AF_INET6: 23>, address='::1', netmask=None, broadcast=None, ptp=None)]}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
查看当前登陆用户信息
psutil.users()
1
[suser(name='ASUS', terminal=None, host='0.4.0.0', started=1586161862.3275075, pid=None)]
1
查看进程信息
psutil.pids() # 查看当前所有进程
1
p = psutil.Process(15396) # 获取指定id的进程
print(p)
1
2
psutil.Process(pid=15396, name='rail.exe', started='2020-04-10 18:46:46')
1
p.name() # 进程名
1
'rail.exe'
1
p.username() # 查看创建该进程的用户名
1
'DESKTOP-5DBLA47\\ASUS'
1
p.cmdline() # 查看该进程对应的exe文件
1
['E:\\tencent\\apps\\rail\\rail.exe',
'-q',
'27847835',
'-u',
'603617035',
'-l',
'0',
'-at',
'0',
'-v',
'1',
'-pf',
'-r',
'CN',
'-p',
'E:\\tencent',
'-c',
'RailProxy8887732']
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
p.cwd() # 查看该进程的工作目录
1
p.exe() # 进程对应的可执行文件
1
'E:\\TENCENT\\apps\\Rail\\rail.exe'
1
p.cpu_affinity() # 该进程CPU占用情况(运行在哪些CPU上)
1
[0, 1, 2, 3, 4, 5, 6, 7]
1
p.num_threads() # 该进程包含的线程数量
1
25
1
p.threads() # 该进程所有线程对象
1
[]
1
p.status() # 进程状态
1
'running'
1
p.is_running() # 进程是否在运行
1
True
1
p.suspend() # 挂起该进程
1
p.resume() # 恢复该进程
1
p.kill() # 结束该进程
1
检查记事本程序是否在运行,如果在运行则返回记事本程序对应的进程ID
for id in psutil.pids():
try:
p=psutil.Process(id)
if os.path.basename(p.exe())=='notepad.exe':
print(id)
except Exception as e:
print(e)
1
2
3
4
5
6
7
psutil.AccessDenied (pid=0)
23620
1
2
5.2 使用pywin32实现事件查看器
Windows系统会对运行过程中发生的很多事情进行记录,通过事件查看器可以查看系统日志,常用于计算机取证、事后调查、责任定位以及攻击向量分析等,对于服务器管理和运行维护具有重要意义。

通过pywin32模块提供的多个子模块可以实现事件查看器的操作

具体实现:
import win32evtlog
import win32evtlogutil
import win32security
import win32con
import winerror
import time
import re
import sys
import traceback
import threading


def date2sec(evt_date):
"""
把类似于'6/26/15 15:54:09'格式的日期转换为1970年以来经过的秒数
:param evt_date:
:return:
"""
# 把日期和时间分开
the_date, the_time = evt_date.split()
(month, day, year) = map(lambda x: int(x), the_date.split(r'/'))
(hour, minute, second) = map(lambda x: int(x), the_time.split(r':'))
if 70 < year < 100:
year += 1990
elif year < 50:
year += 2000
tup = (year, month, day, hour, minute, second, 0, 0, 0)
seconds = time.mktime(tup)
return seconds


def main(computer='.', logtype='System', interval=480):
flags = win32evtlog.EVENTLOG_BACKWARDS_READ | win32evtlog.EVENTLOG_SEQUENTIAL_READ
evt_dict = {win32con.EVENTLOG_AUDIT_FAILURE: '审核失败事件',
win32con.EVENTLOG_AUDIT_SUCCESS: '审核成功事件',
win32con.EVENTLOG_INFORMATION_TYPE: '通知事件',
win32con.EVENTLOG_WARNING_TYPE: '警告事件',
win32con.EVENTLOG_ERROR_TYPE: '错误事件',
}
begin_sec = time.time()
begin_time = time.strftime('%H:%M:%S', time.localtime(begin_sec))
try:
# 打开日志
hand = win32evtlog.OpenEventLog(computer, logtype)
except:
print(f'无法打开{computer}服务器上的{logtype}日志')
return
print(logtype, 'events found in the last {0} hours before {1} '.format(interval / 60 / 60, begin_time))
events = 1
while events:
events = win32evtlog.ReadEventLog(hand, flags, 0)
for ev_obj in events:
try:
the_time = ev_obj.TimeGenerated.Format('%D %H:%M:%S')
seconds = date2sec(the_time)
# 只查看指定时间段内的日志
if seconds < begin_sec - interval:
break
computer = ev_obj.ComputerName
cat = str(ev_obj.EventCategory)
src = str(ev_obj.SourceName)
record = str(ev_obj.RecordNumber)
evt_id = str(winerror.HRESULT_CODE(ev_obj.EventID))
evt_type = evt_dict[ev_obj.EventType]
msg = win32evtlogutil.SafeFormatMessage(ev_obj, logtype)
print(':'.join((the_time, computer, src, cat, record, evt_id, evt_type, msg)))
print('='*20)
if seconds<begin_sec-interval:
break
except Exception as e:
print('something wrong...')
print(e)

win32evtlog.CloseEventLog(hand)

t3 = threading.Thread(target=main,args=('.','Application',5400))
t3.start()
t3.join()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
结果:

————————————————
版权声明:本文为CSDN博主「ChanZany」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_41819729/article/details/105467361

posted @   菩提浪子  阅读(442)  评论(0编辑  收藏  举报
编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示