1. PyWinAuto入门指南·https://zhuanlan.zhihu.com/p/37283722
  2. pywinauto简明教程·https://www.dazhuanlan.com/2019/09/26/5d8bf582966da/
  3. pywinauto教程·https://blog.csdn.net/weixin_40161673/article/details/83246861

一个栗子:File.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import tkinter as tk
from tkinter import ttk
from tkinter import scrolledtext    #导入滚动文本框的模块
import tkinter.messagebox #弹窗库
import tkinter.filedialog #文件选择
from threading import Thread #线程
import uuid,socket,psutil,time,os,configparser,base64,subprocess,webbrowser,requests,json

#创建快捷方式用到的依赖
import comtypes 
from comtypes.client import CreateObject 
from comtypes.persist import IPersistFile 
from comtypes.shelllink import ShellLink 

#图标文件
from icon import Icon 

#点击框架
import subprocess
import uiautomation as auto
auto.uiautomation.SetGlobalSearchTimeout(10)  # 设置全局搜索超时 15


def PrintNetIfAddr(title="以太网",ip="192.168."):
    #"以太网","192.168.1.177"
    r""" 打印多网卡 mac 和 ip 信息 """
    dic = psutil.net_if_addrs()
    for adapter in dic:
        snicList = dic[adapter]
        mac = '无 mac 地址'
        ipv4 = '无 ipv4 地址'
        ipv6 = '无 ipv6 地址'
        for snic in snicList:
            if snic.family.name in {'AF_LINK', 'AF_PACKET'}:
                mac = snic.address
            elif snic.family.name == 'AF_INET':
                ipv4 = snic.address
            elif snic.family.name == 'AF_INET6':
                ipv6 = snic.address
        #print('%s, %s, %s, %s' % (adapter, mac, ipv4, ipv6))
        if title in adapter and ip in ipv4:
            mac = mac.replace("-",":")
            print(mac,ipv4)
            return mac,ipv4
    
    print("没有获取到网卡信息")
    return "00:00:00:00:00:00","0.0.0.0"

#初始化本地配置文件
def initConfigFile():
    config = configparser.ConfigParser()
    config.read("conf.ini")
    config.add_section("chrome")
    config.set("chrome", "path", "C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe")
    config.set("chrome", "number", "0")
    with open("conf.ini","w+") as f:
        config.write(f)

#读取配置文件
def rConfigFile():
    config = configparser.ConfigParser()
    config.read("conf.ini")
    config.sections()
    return config.get("chrome", "path"),config.get("chrome", "number")

#设置/更新配置文件
def sConfigFile():
    config = configparser.ConfigParser()
    config.read("conf.ini")
    config.set("chrome", "path", path.get())
    config.set("chrome", "number", age.get())
    with open("conf.ini","w+") as f:
        config.write(f)
        tkinter.messagebox.showinfo(title="成功", message="配置保存成功!") 
        bLog.set("配置保存成功!")

#选择文件
def selectFile():
    desktopPath = tkinter.filedialog.askopenfilename(title=u'选择文件', initialdir=(os.path.join(os.path.expanduser('~'),"Desktop")))
    if len(desktopPath) <= 0:
        return None
    if "chrome.exe" not in desktopPath:
        tkinter.messagebox.showwarning(title='文件错误', message='请选择Chrome浏览器的chrome.exe主程序!') 
        return None
    path.set(desktopPath)

#创建窗口,并居中
def center_window(win, width=0, height=0):  
    screenwidth = win.winfo_screenwidth()  
    screenheight = win.winfo_screenheight()  
    size = '%dx%d+%d+%d' % (width, height, (screenwidth - width)/2, (screenheight - height)/2)  
    win.geometry(size)  

#关闭提示
def on_closing():
    if tkinter.messagebox.askokcancel("注意!","该程序用于处理XXXX事项,确定关闭该程序吗?"):
        win.destroy()

#保存配置并创建快捷方式
def saveConfig():
    bLog.set("请稍等...")
    #这里验证用于用户第一次运行,使用默认路径时并未验证路径是否正确或是否安装的有浏览器
    if os.path.isfile(path.get()) == False:
        tkinter.messagebox.showwarning(title='文件错误', message='请确认是否安装Chrome浏览器或点击左侧重新选择浏览器路径!') 
        bLog.set("Chrome浏览器路径错误!")
        return None

    sConfigFile()

    chromePath,chromeNumber = rConfigFile()

    for BNum in range(int(chromeNumber)):
        chromePatameter = r"-ignore-certificate-errors --test-type --ignore-certificate-errors --user-data-dir=C:\ChromeRf\No"+str(BNum+1)
        vbsCenter = 'Set Shell = CreateObject("WScript.Shell") \n DesktopPath = Shell.SpecialFolders("Desktop") \n Set link = Shell.CreateShortcut(DesktopPath & "\Chrome浏览器_'+str(BNum+1)+'号.lnk") \n link.Arguments = "'+chromePatameter+'" \n link.Description = "" \n link.HotKey = "CTRL+K" \n link.IconLocation = "'+chromePath+'" \n link.TargetPath = "'+chromePath+'" \n link.WindowStyle = 1 \n link.WorkingDirectory = "'+chromePath+'" \n link.Save'
        create__file("createLnk_"+str(BNum+1)+".vbs",vbsCenter)
        subprocess.call('cscript createLnk_'+str(BNum+1)+'.vbs')
    bLog.set("快捷方式已创建,3秒后删除创建脚本!")
    print("快捷方式已创建,3秒后删除创建脚本!")    
    time.sleep(3)
    for BNum in range(int(chromeNumber)):
        os.remove('createLnk_'+str(BNum+1)+'.vbs')
        bLog.set("已删除:createLnk_"+str(BNum+1)+".vbs")
        print("已删除:",'createLnk_'+str(BNum+1)+'.vbs')  
    bLog.set("欢迎使用XXXX工具")

#创建文件
def create__file(file_path,msg):
    f=open(file_path,"a")
    f.write(msg)
    f.close

#打开计划任务
def schtasks():
    cmdObj = os.popen("taskschd")

#打开首页
def openHome():
    webbrowser.open("http://www.baidu.com", new=0, autoraise=True)



#开启异步
def asyncs(f):
    def wrapper(*args, **kwargs):
        thr = Thread(target=f, args=args, kwargs=kwargs)
        thr.start()

    return wrapper

#请求接口
@asyncs
def getHttpApi():
    mac,ipv4 = PrintNetIfAddr()
    postUrl = "https://www.iicode.top/api.php"
    postData = {
        "action":"getConfig",
        "mac":mac
    }
    try:
        res = requests.post(postUrl,data = postData)
    except Exception as e:
        bLog.set("网络请求出现问题,暂时无法使用!")
        print("网络请求出现问题:",postUrl)
        #print(e)
    if "res" in locals():
        jsonObj = json.loads(res.text)  
        identityText.set("单位:"+jsonObj['remarks'])
        serverDateText.set("服务器时间:"+jsonObj['serverDate'])
        print(jsonObj['remarks'])
        #1.重启浏览器 2推送机器状态 3重启 4关机 5

        bLog.set("程序待命中...")
        

#输入密码
@asyncs
def inputPass():
    print(auto.GetRootControl())
    try:
        #打开指定程序
        #subprocess.Popen('notepad.exe')
        # 首先从桌面的第一层子控件中找到记事本程序的窗口WindowControl,再从这个窗口查找子控件
        notepadWindow = auto.WindowControl(searchDepth=4, ClassName='#32770')
        print(notepadWindow.Name)
        notepadWindow.SetTopmost(True)
        # 查找notepadWindow所有子孙控件中的第一个EditControl,因为EditControl是第一个子控件,可以不指定深度
        notepadWindow.EditControl(Name="计算机(C):").GetValuePattern().SetValue('Hello')
        notepadWindow.EditControl(Name="用户名:").GetValuePattern().SetValue('Hi')
        # 先从notepadWindow的第一层子控件中查找TitleBarControl, 
        # 然后从TitleBarControl的子孙控件中找第二个ButtonControl, 即最大化按钮,并点击按钮
        #notepadWindow.TitleBarControl(Depth=1).ButtonControl(foundIndex=2).Click()
        # 从notepadWindow前两层子孙控件中查找Name为'关闭'的按钮并点击按钮
        notepadWindow.ButtonControl(searchDepth=2, Name='最小化').Click()
        # 这时记事本弹出是否保存提示,按热键Alt+N不保存退出。
        auto.SendKeys('{Alt}s')
    except Exception as e:
        print("找不到主窗口")
   

@asyncs
def clockLoop():
    count = 0
    while True:
        time.sleep(1)
        if count%20 == 0:#20秒执行一次
            getHttpApi()
            inputPass()
        if count>=2678400:#一个月归零一次 2678400 秒大概是一个月的时间
            count = 0
        count += 1  

if __name__ == "__main__":
    #声明对象
    win = tk.Tk()
    #设置窗口主题
    win.title("XXXX辅助工具 Python版")
    #窗口是否允许拉伸
    win.resizable(width=False,height=False)
    #窗口透明度
    win.attributes('-alpha', 1.0)

    #居中
    center_window(win,700,190)

    #创建顶部日志容器,父级容器为win
    monty_top = ttk.LabelFrame(win,text="日志区")
    #设置行 列 外边距x 外边距y
    monty_top.grid(row=0,column=0,padx=5,pady=5,sticky=tk.W)

    #右边按钮区域容器
    monty_right = ttk.LabelFrame(win,text="操作区")
    #设置行 列 外边距x 外边距y
    monty_right.grid(row=0,column=1,padx=5,pady=5,rowspan=2,sticky=tk.W)

    #左边选择路径容器
    monty_left = ttk.LabelFrame(win,text="常规区")
    #设置行 列 外边距x 外边距y
    monty_left.grid(row=1,column=0,padx=5,pady=5,sticky=tk.W)

    ##################################顶部容器##################################
    #标签
    bLog = tk.StringVar()
    ttk.Label(monty_top,text="欢迎使用XXXX工具",font=("华文行楷",20),width=40,textvariable=bLog).grid(row=0,column=0,sticky=tk.W)
    bLog.set("欢迎使用XXXX工具")
    ##################################左边容器##################################

    #判断配置文件是否存在,否正初始化
    if os.path.isfile("conf.ini") == False:
        initConfigFile()

    #读取配置文件
    chromePath,chromeNumber = rConfigFile()

    #按钮
    action = ttk.Button(monty_left,text="Chrome浏览器:",command=selectFile)
    action.grid(row=0,column=0,sticky=tk.W)

    #输入框
    path = tk.StringVar()
    pathEntered = ttk.Entry(monty_left,width=48,textvariable=path)
    pathEntered.grid(row=0,column=1,sticky=tk.W)
    #程序启动自动聚焦到这里
    pathEntered.focus()
    path.set(chromePath)

    #标签
    ttk.Label(monty_left,text="数量:").grid(row=0,column=2,sticky=tk.W)

    #下拉框
    age = tk.StringVar()
    ageChosen = ttk.Combobox(monty_left,width=6,textvariable=age,state="readonly")
    #设置下拉框内的值
    ageChosen["values"] = (0,1,2,3,4)
    ageChosen.grid(row=0,column=3)
    #下拉框默认的值 此处为下标参数
    ageChosen.current(chromeNumber) 

    #显示配置
    monty_config = ttk.LabelFrame(monty_left)
    #设置行 列 外边距x 外边距y
    monty_config.grid(row=1,column=0,padx=20,pady=2,columnspan=4,sticky=tk.W)

    #标签
    macText = tk.StringVar()
    ipText = tk.StringVar()
    pcNameText = tk.StringVar()
    identityText = tk.StringVar()
    serverDateText = tk.StringVar()
    runDateText = tk.StringVar() 
    ttk.Label(monty_config,text="MAC地址:获取中...",textvariable=macText).grid(row=0,column=0,padx=10,sticky=tk.W)
    ttk.Label(monty_config,text="本机IP:获取中...",textvariable=ipText).grid(row=0,column=1,padx=10,sticky=tk.W)
    ttk.Label(monty_config,text="主机名:获取中...",textvariable=pcNameText).grid(row=0,column=2,padx=10,sticky=tk.W)
    ttk.Label(monty_config,text="开机时间:获取中...",textvariable=runDateText).grid(row=1,column=0,padx=10,sticky=tk.W)
    ttk.Label(monty_config,text="单位:获取中...",textvariable=identityText).grid(row=1,column=1,padx=10,sticky=tk.W)
    ttk.Label(monty_config,text="服务器时间:获取中...",textvariable=serverDateText).grid(row=1,column=2,padx=10,sticky=tk.W)


    #获取本机电脑名
    pcname = socket.getfqdn(socket.gethostname())
    #获取本机ip
    mac,ipv4 = PrintNetIfAddr()
    macText.set("MAC地址:"+mac)
    ipText.set("本机IP:"+ipv4)
    pcNameText.set("主机名:"+pcname)
    runDateText.set("开机时间:"+time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(psutil.boot_time())))
    identityText.set("单位:获取中..")
    serverDateText.set("服务器时间:获取中...")

    ##################################右边容器##################################
    #标签
    action = ttk.Button(monty_right,text="保存配置",command=saveConfig)
    action.grid(row=0,column=0,sticky=tk.W)

    action1 = ttk.Button(monty_right,text="输入密码",command=inputPass)
    action1.grid(row=1,column=0,sticky=tk.W)

    action2 = ttk.Button(monty_right,text="检查更新",command=getHttpApi)
    action2.grid(row=2,column=0,sticky=tk.W)

    action3 = ttk.Button(monty_right,text="计划任务",command=schtasks)
    action3.grid(row=3,column=0,sticky=tk.W)

    action4 = ttk.Button(monty_right,text="打开首页",command=openHome)
    action4.grid(row=4,column=0,sticky=tk.W)

    #设置应用内的图标
    with open('tmp.ico','wb') as tmp:
        tmp.write(base64.b64decode(Icon().img))
    win.iconbitmap('tmp.ico')
    os.remove('tmp.ico')

    #监听窗口将被关闭
    win.protocol("WM_DELETE_WINDOW", on_closing)
    
    #开启时钟循环
    clockLoop()

    win.mainloop()      # 当调用mainloop()时,窗口才会显示出来

打包为exe文件

pyinstaller  --clean --win-private-assemblies -F .\File.py

案例图

Snipaste_2020-09-21_17-23-32.png

最后修改:2023 年 12 月 05 日
如果觉得我的文章对你有用,请随意赞赏