我希望我的Python脚本能够在Vista上复制文件.当我从普通cmd.exe
窗口运行它时,不会生成错误,但不会复制文件.如果我运行cmd.exe
"作为管理员",然后运行我的脚本,它工作正常.
这是有道理的,因为用户帐户控制(UAC)通常会阻止许多文件系统操作.
有没有办法可以在Python脚本中调用UAC提升请求(这些对话框说"像这样的应用程序需要管理员访问权限,这样可以吗?")
如果那是不可能的,那么我的脚本是否有一种方法可以至少检测到它没有被提升以便它可以优雅地失败?
截至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)
如果您使用的是Python 2.x,那么您应该替换最后一行:
ctypes.windll.shell32.ShellExecuteW(None, u"runas", unicode(sys.executable), unicode(__file__), None, 1)
还要注意的是,如果你转换你的Python脚本到一个可执行文件(使用工具,如py2exe
,cx_freeze
,pyinstaller
),那么你应该更换第四个参数为空字符串(""
).
这里的一些优点是:
不需要外部库(也不是用于Windows扩展的Python).它仅使用ctypes
标准库.
适用于Python 2和Python 3.
无需修改文件资源也无需创建清单文件.
如果你没有在if/else语句下面添加代码,那么代码将不会被执行两次.
如果用户拒绝UAC提示,您可以轻松地将其修改为具有特殊行为.
您可以指定修改第四个参数的参数.
您可以指定修改第六个参数的显示方法.
底层ShellExecute调用的文档在这里.
我花了一点时间让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)
似乎没有办法提升应用程序权限一段时间来执行特定任务.Windows需要在程序开始时知道应用程序是否需要某些特权,并要求用户确认应用程序何时执行需要这些特权的任务.有两种方法可以做到这一点:
编写一个清单文件,告诉Windows应用程序可能需要一些权限
从另一个程序内部使用提升的权限运行应用程序
这两篇 文章更详细地解释了它是如何工作的.
如果您不想为CreateElevatedProcess API编写令人讨厌的ctypes包装器,我会使用代码项目文章中解释的ShellExecuteEx技巧(Pywin32带有ShellExecute的包装器).怎么样?像这样的东西:
当你的程序启动时,它会检查它是否具有管理员权限,如果它没有使用ShellExecute技巧自行运行并立即退出,如果是,则执行手头的任务.
当您将程序描述为"脚本"时,我认为这足以满足您的需求.
干杯.