最近更新于 2025-02-04 16:52
测试环境
Windows 11 24H2
Python 3.13.1
实现
import sys
import ctypes
def getPackagedStatus():
    """
    获取打包状态
    Returns:
        bool: 是否为打包状态
    """
    return getattr(sys, 'frozen', False)
def quotingArgs(args: list[str]) -> str:
    """
    为参数添加双引号并拼接为一个字符串,保证参数可以正确处理
    Params:
        args (list[str]): 参数列表
    Returns:
        str: 拼接后的字符串
    """
    return ' '.join(f' "{arg}"' for arg in args)
def checkAdmin():
    """
    检查是否是管理员
    Returns:
        bool: 是否是管理员
    """
    try:
        return ctypes.windll.shell32.IsUserAnAdmin()
    except:
        return False
def runAsAdmin() -> tuple[bool, str]:
    """
    以管理员身份
    Returns:
        (状态, 消息): 三种状态:None:已经是管理员身份;True 以管理员身份重新运行成功;False 以管理员身份重新运行失败
    """
    if checkAdmin():
        return None, '已经是管理员'
    try:
        if getPackagedStatus():
            params = quotingArgs(sys.argv[1:])
        else:
            params = quotingArgs(sys.argv)
        result = ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, params, None, 1)
        if result > 32:
            return True, '以管理员运行成功'
        else:
            match result:
                case 5:
                    error = '访问被拒绝'
                case _:
                    error = ''
            return False, f'以管理员身份运行失败,错误代码:{result} {error}'
    except Exception as e:
        return False, f'以管理员身份运行时发生错误:{e}'
from commontools import CommonTools
def main():
    status, info = CommonTools.runAsAdmin()
    if status is None:
        ###################################
        # 把需要以管理员身份运行的代码放在这里
        ###################################
        info += ' 工作逻辑放在这里'
        print(info)
        import time
        time.sleep(3)
        print('到此一游')
        import os
        os.system('pause')
    elif status:
        info += ' 以管理员身份运行了一个新程序,我的寿命到此结束了'
        print(info)
    else:
        print(info)
if __name__ == '__main__':
    main()
(1) 代码运行
① 以管理员身份运行

② 以非管理员身份运行,但拒绝授权

③ 以非管理员身份运行,同意授权
上面是非管理员,它请求以管理员重新运行了自己,下面新运行的程序就已经是管理员身份了

(2)打包后运行
① 以管理员身份运行

② 以非管理员身份运行,但拒绝授权

③ 以非管理员身份运行,同意授权

注意
使用调试运行可能会出现闪退的现象。
比如我用 VScode 调试程序,VScode 是非管理员运行的,使用上面代码提权会重新运行自身,那么调试启动的进程就结束了,会连带把调试启动的进程尝试提权新运行的拥有管理员权限的进程一起关闭,也就是出现闪退的情况。
Windows 下 Python 程序提权管理员
