U盘解锁/锁定,适用于学校、公司、以及任何存在授权使用的场景

此帖属于上一贴的更新,

U盘解锁/锁屏——修改于坛友思路

https://bbs.songma.com/thread-1766402-1-1.html

(出处: 论坛)

上一贴作为python初学的技术交流贴,坛友提出了许多有意义、有建设性的提议,试着实现了一下,以下是相关内容。

必看:由于我打包的时候忘记删除配置文件,请下载压缩包后先删除config.ini,不然会直接被锁定,如果已经被锁定请重启电脑再删除文件目录下的config.ini。

图片[1] - U盘解锁/锁定,适用于学校、公司、以及任何存在授权使用的场景 - 宋马

适用场景:学校(教师正常使用,学生不能随意玩电脑)、公司(自己的电脑不方便给其他人用,设密码也不合适)、公用电脑(临时离开不方便关机)等等。

锁定方式:用

windll

.

user32

.

BlockInput

(

True

)

屏蔽键盘和鼠标操作,界面不会有任何变化,此时只能调动

ctrl+alt+del和锁屏热键,但由于循环锁定,所以依然不能进行其他操作。

授权方式:以下两种方式可同时开启,满足其一即可解锁电脑。
1.给指定U盘授权解锁电脑:判断U盘序列号是否在授权名单,不在名单的U盘不能操作电脑。
2.给U盘指定文件授权解锁电脑:判断U盘的指定路径中是否存在指定文件,存在就可以解锁。

使用方法:

U盘解锁/锁定,适用于学校、公司、以及任何存在授权使用的场景

初次打开软件

:默认如果先插U盘再开软件,U盘会出目前已授权列表中。如果先打开软件再插入U盘,U盘会出目前未授权列表中,需要选中未授权列表中的每一项,逐个

<添加>

到授权U盘列表,同时也可以勾选

<指定文件授权>

,会弹出一个选择文件的窗口,选择想要指定的文件就好,所有的授权设置完成后必定要点击

<保存>

,最后

<退出>

第二次及后来启动软件

:不会直接出现软件界面,会在任务栏界面出现一把锁,只能

<右键>

会出现菜单,点击

<设置>

就会打开软件界面,可以重新设置授权,界面实时刷新,可实时修改授权名单和设置,修改后记得点击

<保存>

,点击

<退出>

会解锁软件的所有进程。

开机自启

:可以通过系统的启动文件夹或者注册表等任何方法实现自启,会触发目前已知

唯二之一的bug

不会有窗口,任务栏也没有图标(绝对静默)

,但进程启动运行,功能正常,就是不能打开设置界面。如果需要调整授权,需要用任务管理器结束进程然后

双击启动软件

,然后任务栏就有图标了。

我解决不了(不想解决)的问题:

bug1:

通过系统自启启动软件或者cmd启动软件任务栏不会出现图标,除此之外一切正常。

bug2:

无论是点击界面内的退出还是状态栏右键退出,状态栏的图标都不会主动消失,需要鼠标从图标上经过一下才会消失,这个可能是我系统的bug。

打包后的文件很大(73M),cpu占用在锁定状态会多一些。

软件打包后图标右下角有个小盾牌,据网上说带有这个盾牌的程序设置开机自启有必定难度,我用vbs可以实现静默自启,但bug1依然存在。

代码不美观且难以理解。

最后会贴出源码和成品,希望坛友能指正优化一下我的程序。自学了基础部分,写这个程序遇到许多困难,csdn都查烂了。

软件还有不完善的地方,我有一些解决思路但懒,不必定啥时候修复,这是我写的第2个GUI工具,真的很佩服论坛里的大佬。

成品链接:https://www.123pan.com/s/TctA-nW5j.html

from tkinter import END, Checkbutton, Listbox, Tk, Label, Button, filedialog, PhotoImage
from tkinter.messagebox import askokcancel
from ctypes import windll
from wmi import WMI
from os import _exit, path
from time import sleep
from threading import Thread
from pythoncom import CoInitialize
from pystray import MenuItem, Icon, Menu
from PIL import Image

# 状态栏图标


def icon():
    def show_window():
        global is_w
        # 首次启动不显示窗口
        if is_w == 0:
            Thread(target=window).start()
            is_w = 1
        else:
            root_windows.deiconify()

    menu = (MenuItem('设置', show_window), MenuItem('退出', exit),
            Menu.SEPARATOR)
    image = Image.open("icon.png")
    icon = Icon("icon", image, "授权已开启", menu)

    icon.run()

# 设置主窗口


def window():
    global is_update
    global root_windows, listbox1, listbox2, listbox3, button1, button2, button3, button4, checkbutton
    root_windows = Tk()

    # 窗口大小,设置屏幕居中
    screenwidth = root_windows.winfo_screenwidth()
    screenheight = root_windows.winfo_screenheight()
    root_windows.geometry(
        f"419x260+{int((screenwidth-419)/2)}+{int((screenheight-236)/2)}")
    root_windows.resizable(False, False)
    root_windows.iconphoto(False, PhotoImage(file=f'{work_path}\icon.png'))
    root_windows.title("Lock_Screen_v1.1 by ifdess from 52pj.cn")

    # 标签
    lable1 = Label(root_windows, text="未授权U盘:")
    lable1.place(x=20, y=10)
    # 标签
    lable2 = Label(root_windows, text="已授权U盘:")
    lable2.place(x=255, y=10)

    # 未授权列表框
    listbox1 = Listbox(root_windows)
    u_now = get_u()
    for item in u_yes:
        try:
            u_now.remove(item)
        except:
            pass
    for i in u_now:
        listbox1.insert(END, i)
    listbox1.place(x=20, y=35)

    # 已授权列表框
    listbox2 = Listbox(root_windows)
    for i in u_yes:
        listbox2.insert(END, i)
    listbox2.place(x=255, y=35)

    # 文件模式复选框
    checkbutton = Checkbutton(root_windows,
                              text="指定文件授权", command=select_file)
    checkbutton.place(x=16, y=226)

    # 指定文件列表框
    listbox3 = Listbox(root_windows, height=1, width=39)
    if file_yes:
        listbox3.insert(END, file_yes)
        checkbutton.select()
    else:
        pass
    listbox3.place(x=120, y=228)

    # 添加按钮
    button1 = Button(root_windows, text="添加 >>",
                     height=1, width=8, command=add)
    button1.place(x=177, y=42)

    # 删除按钮
    button2 = Button(root_windows, text=" << 删除",
                     height=1, width=8, command=delete)
    button2.place(x=177, y=89)

    # 保存按钮
    button3 = Button(root_windows, text="保存", height=1,
                     width=8, command=save_config)
    button3.place(x=177, y=136)

    # 退出按钮
    button4 = Button(root_windows, text="退出", height=1, width=8, command=exit)
    button4.place(x=177, y=183)

    if is_update == 0:
        Thread(target=update_u, daemon=True).start()
        is_update = 1

    # 设置叉是隐藏窗口
    if path.exists(f"{work_path}/config.ini"):
        root_windows.protocol("WM_DELETE_WINDOW", root_windows.withdraw)
    else:
        root_windows.protocol("WM_DELETE_WINDOW", exit)
    root_windows.mainloop()


work_path = path.dirname(path.abspath(__file__))


# 保存配置文件
def save_config():
    global u_yes, file_yes
    with open(f"{work_path}\config.ini", "w") as c:
        c.write(str(u_yes)+"
")
        c.write(str(file_yes))
    askokcancel(title="通知", message="配置保存成功。")


# 读取配置文件
def read_config():
    global u_yes, file_yes
    if path.exists(f"{work_path}/config.ini"):
        with open(f"{work_path}\config.ini", "r") as c:
            u_yes = eval(c.readline())
            file_yes = c.readline()
    else:
        u_yes = get_u()
        file_yes = ""


# 获取U盘型号和序列号,保存为列表
def get_u(var=[]):
    var = []
    CoInitialize()
    for item in WMI().Win32_DiskDrive():
        if item.MediaType == "Removable Media":
            var.append(item.Model+" "+item.SerialNumber)
    return var


# 删除选中项
def delete():
    global u_yes, listbox1, listbox2
    try:
        u_yes.remove(listbox2.get(listbox2.curselection()))
        listbox2.delete(listbox2.curselection())
        listbox1.delete(0, END)
    except:
        pass


# 添加选中项
def add():
    global u_yes, listbox1, listbox2
    u_yes.append(listbox1.get(listbox1.curselection()))
    listbox2.insert(END, (listbox1.get(listbox1.curselection())))
    listbox1.delete(listbox1.curselection())


# 核心判断程序,是否屏蔽
def run():
    global is_w
    while True:
        if get_u() == []:
            windll.user32.BlockInput(True)
        else:
            # 判断实时获取的U盘列表和刚开机时的U盘列表是否有交集,如果有就代表教师U盘仍旧保持插入
            if list(set(get_u()).intersection(u_yes)) == []:
                if is_file():
                    windll.user32.BlockInput(False)
                else:
                    windll.user32.BlockInput(True)
            else:
                windll.user32.BlockInput(False)
            sleep(0.001)

# 打开选择文件的窗口,并处理文件路径


def select_file():
    global select_path, listbox3, file_yes, CheckBox
    if len(file_yes) != 0:
        file_yes = ""
        listbox3.delete(0, END)
    else:
        selected_file_path = filedialog.askopenfilename()
        file_yes = selected_file_path[2:]
        if len(file_yes) == 0:
            checkbutton.deselect()
        else:
            listbox3.delete(0, END)
            listbox3.insert(END, selected_file_path[2:])
            file_yes = selected_file_path[2:]
            checkbutton.select()


# 遍历所有盘路径,判断授权文件是否存在
def is_file():
    global file_yes
    if len(file_yes) == 0:
        return False
    else:
        for item in [chr(abc) for abc in range(97, 123)]:
            if path.exists(f"{item}:{file_yes}"):
                return True


def exit():
    _exit(0)


# 更新显示列表
def update_u():
    global listbox1
    u_temp = []
    while True:
        u_now = get_u()
        for item in u_yes:
            try:
                u_now.remove(item)
            except:
                pass
        if u_now != u_temp and u_now != None:
            listbox1.delete(0, END)
            u_temp = u_now
            for item in u_now:
                listbox1.insert(END, item)
        else:
            pass
        sleep(0.001)


# 程序开始
read_config()
if path.exists(f"{work_path}/config.ini"):
    is_w = 0
    is_update = 0
    Thread(target=icon).start()
    Thread(target=run).start()

else:
    is_update = 0
    window()

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
评论 共47条

请登录后发表评论