jwf*_*arn 82 python windows uac windows-vista
我希望我的Python脚本能够在Vista上复制文件.当我从普通cmd.exe
窗口运行它时,不会生成错误,但不会复制文件.如果我运行cmd.exe
"作为管理员",然后运行我的脚本,它工作正常.
这是有道理的,因为用户帐户控制(UAC)通常会阻止许多文件系统操作.
有没有办法可以在Python脚本中调用UAC提升请求(这些对话框说"像这样的应用程序需要管理员访问权限,这样可以吗?")
如果那是不可能的,那么我的脚本是否有一种方法可以至少检测到它没有被提升以便它可以优雅地失败?
Mar*_*nte 83
截至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)
Run Code Online (Sandbox Code Playgroud)
如果您使用的是Python 2.x,那么您应该替换最后一行:
ctypes.windll.shell32.ShellExecuteW(None, u"runas", unicode(sys.executable), unicode(__file__), None, 1)
Run Code Online (Sandbox Code Playgroud)
还要注意的是,如果你转换你的Python脚本到一个可执行文件(使用工具,如py2exe
,cx_freeze
,pyinstaller
),那么你应该更换第四个参数为空字符串(""
).
这里的一些优点是:
ctypes
标准库.底层ShellExecute调用的文档在这里.
Jor*_*nko 66
我花了一点时间让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)
Run Code Online (Sandbox Code Playgroud)
dgu*_*lia 29
似乎没有办法提升应用程序权限一段时间来执行特定任务.Windows需要在程序开始时知道应用程序是否需要某些特权,并要求用户确认应用程序何时执行需要这些特权的任务.有两种方法可以做到这一点:
如果您不想为CreateElevatedProcess API编写令人讨厌的ctypes包装器,我会使用代码项目文章中解释的ShellExecuteEx技巧(Pywin32带有ShellExecute的包装器).怎么样?像这样的东西:
当你的程序启动时,它会检查它是否具有管理员权限,如果它没有使用ShellExecute技巧自行运行并立即退出,如果是,则执行手头的任务.
当您将程序描述为"脚本"时,我认为这足以满足您的需求.
干杯.
只是添加这个答案,以防其他人像我一样被谷歌搜索引导到这里。我elevate
在 Python 脚本中使用了该模块,并在 Windows 10 中使用管理员权限执行了该脚本。
https://pypi.org/project/elevate/
以下示例基于MARTIN DE LA FUENTE SAAVEDRA 的出色工作和公认答案。特别是,引入了两个枚举。第一个允许轻松指定如何打开提升的程序,第二个在需要轻松识别错误时提供帮助。请注意,如果您希望将所有命令行参数传递给新进程,sys.argv[0]
则可能应该替换为函数调用:subprocess.list2cmdline(sys.argv)
。
#! /usr/bin/env python3
import ctypes
import enum
import subprocess
import sys
# Reference:
# msdn.microsoft.com/en-us/library/windows/desktop/bb762153(v=vs.85).aspx
# noinspection SpellCheckingInspection
class SW(enum.IntEnum):
HIDE = 0
MAXIMIZE = 3
MINIMIZE = 6
RESTORE = 9
SHOW = 5
SHOWDEFAULT = 10
SHOWMAXIMIZED = 3
SHOWMINIMIZED = 2
SHOWMINNOACTIVE = 7
SHOWNA = 8
SHOWNOACTIVATE = 4
SHOWNORMAL = 1
class ERROR(enum.IntEnum):
ZERO = 0
FILE_NOT_FOUND = 2
PATH_NOT_FOUND = 3
BAD_FORMAT = 11
ACCESS_DENIED = 5
ASSOC_INCOMPLETE = 27
DDE_BUSY = 30
DDE_FAIL = 29
DDE_TIMEOUT = 28
DLL_NOT_FOUND = 32
NO_ASSOC = 31
OOM = 8
SHARE = 26
def bootstrap():
if ctypes.windll.shell32.IsUserAnAdmin():
main()
else:
# noinspection SpellCheckingInspection
hinstance = ctypes.windll.shell32.ShellExecuteW(
None,
'runas',
sys.executable,
subprocess.list2cmdline(sys.argv),
None,
SW.SHOWNORMAL
)
if hinstance <= 32:
raise RuntimeError(ERROR(hinstance))
def main():
# Your Code Here
print(input('Echo: '))
if __name__ == '__main__':
bootstrap()
Run Code Online (Sandbox Code Playgroud)
认识到这个问题是几年前提出的,我认为frmdstryr 使用他的模块 pywinutils在github上提供了一个更优雅的解决方案:
摘抄:
import pythoncom
from win32com.shell import shell,shellcon
def copy(src,dst,flags=shellcon.FOF_NOCONFIRMATION):
""" Copy files using the built in Windows File copy dialog
Requires absolute paths. Does NOT create root destination folder if it doesn't exist.
Overwrites and is recursive by default
@see http://msdn.microsoft.com/en-us/library/bb775799(v=vs.85).aspx for flags available
"""
# @see IFileOperation
pfo = pythoncom.CoCreateInstance(shell.CLSID_FileOperation,None,pythoncom.CLSCTX_ALL,shell.IID_IFileOperation)
# Respond with Yes to All for any dialog
# @see http://msdn.microsoft.com/en-us/library/bb775799(v=vs.85).aspx
pfo.SetOperationFlags(flags)
# Set the destionation folder
dst = shell.SHCreateItemFromParsingName(dst,None,shell.IID_IShellItem)
if type(src) not in (tuple,list):
src = (src,)
for f in src:
item = shell.SHCreateItemFromParsingName(f,None,shell.IID_IShellItem)
pfo.CopyItem(item,dst) # Schedule an operation to be performed
# @see http://msdn.microsoft.com/en-us/library/bb775780(v=vs.85).aspx
success = pfo.PerformOperations()
# @see sdn.microsoft.com/en-us/library/bb775769(v=vs.85).aspx
aborted = pfo.GetAnyOperationsAborted()
return success is None and not aborted
Run Code Online (Sandbox Code Playgroud)
这利用 COM 接口,并自动指示需要管理员权限,如果您正在复制到需要管理员权限的目录,您会看到熟悉的对话框提示,并且还在复制操作期间提供典型的文件进度对话框。
归档时间: |
|
查看次数: |
78996 次 |
最近记录: |