从Python脚本中请求UAC提升?

2024-06-09 02:42:44 发布

您现在位置:Python中文网/ 问答频道 /正文

我想要我的Python脚本在Vista上复制文件。当我从普通的cmd.exe窗口运行它时,不会生成错误,但不会复制文件。如果我以管理员身份运行cmd.exe,然后运行我的脚本,它就可以正常工作。

这是有意义的,因为用户帐户控制(UAC)通常会阻止许多文件系统操作。

有没有办法从Python脚本中调用UAC提升请求(那些对话框会说“某某应用需要管理员访问,可以吗?”)

如果这是不可能的,是否有一种方法,我的脚本至少可以检测到它没有被提升,以便它可以优雅地失败?


Tags: 文件方法用户脚本cmd管理员错误身份
3条回答

我花了一点时间才让dguaraglia的答案生效,所以为了节省其他人的时间,下面是我为实现这个想法所做的:

import os
import sys
import win32com.shell.shell as shell
ASADMIN = 'asadmin'

if sys.argv[-1] != ASADMIN:
    script = os.path.abspath(sys.argv[0])
    params = ' '.join([script] + sys.argv[1:] + [ASADMIN])
    shell.ShellExecuteEx(lpVerb='runas', lpFile=sys.executable, lpParameters=params)
    sys.exit(0)

截至2017年,实现这一目标的简单方法如下:

import ctypes, sys

def is_admin():
    try:
        return ctypes.windll.shell32.IsUserAnAdmin()
    except:
        return False

if is_admin():
    # Code of your program here
else:
    # Re-run the program with admin rights
    ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, __file__, None, 1)

如果使用的是Python2.x,则应将最后一行替换为:

ctypes.windll.shell32.ShellExecuteW(None, u"runas", unicode(sys.executable), unicode(__file__), None, 1)

还要注意,如果您将python脚本转换为可执行文件(使用诸如py2execx_freezepyinstaller之类的工具),那么您应该替换空字符串("")的第四个参数。

这里的一些优点是:

  • 不需要外部库(也不需要Python for Windows扩展)。它只使用标准库中的ctypes
  • 适用于Python2和Python3。
  • 无需修改文件资源或创建清单文件。
  • 如果不在If/else语句下面添加代码,代码就不会被执行两次。
  • 如果用户拒绝UAC提示,您可以很容易地将其修改为具有特殊行为。
  • 可以指定修改第四个参数的参数。
  • 可以指定修改第六个参数的显示方法。

底层ShellExecute调用的文档是here

似乎暂时无法提升应用程序权限以执行特定任务。Windows需要在程序启动时知道应用程序是否需要某些特权,并要求用户确认应用程序何时执行任何需要这些特权的任务。有两种方法:

  1. 编写一个清单文件,告诉Windows应用程序可能需要一些特权
  2. 从另一个程序内部以提升的权限运行应用程序

这个twoarticles更详细地解释了这是如何工作的。

如果您不想为createElevatedProcessAPI编写一个讨厌的ctypes包装器,我要做的是使用代码项目文章中解释的ShellExecuteEx技巧(Pywin32附带了ShellExecute的包装器)。怎样?像这样的:

当程序启动时,它会检查它是否具有管理员权限,如果没有,它会使用ShellExecute技巧运行自己并立即退出,如果有,它将执行手头的任务。

当你把你的程序描述为“脚本”时,我想这已经足够满足你的需要了。

干杯。

相关问题 更多 >