从 Python 脚本内部请求 UAC 提升?

2024-12-19 09:24:00
admin
原创
129
摘要:问题描述:我希望我的 Python 脚本能够在 Vista 上复制文件。当我从正常cmd.exe窗口运行它时,不会生成任何错误,但文件不会被复制。如果我以cmd.exe“管理员身份”运行,然后运行我的脚本,它就可以正常工作。这是有道理的,因为用户帐户控制 (UAC) 通常会阻止许多文件系统操作。有没有办法,我...

问题描述:

我希望我的 Python 脚本能够在 Vista 上复制文件。当我从正常cmd.exe窗口运行它时,不会生成任何错误,但文件不会被复制。如果我以cmd.exe“管理员身份”运行,然后运行我的脚本,它就可以正常工作。

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

有没有办法,我可以从 Python 脚本中调用 UAC 提升请求(那些对话框,上面写着“某某应用程序需要管理员访问权限,可以吗?”)

如果这不可能的话,有没有办法让我的脚本至少检测到它没有被提升,以便它可以正常失败?


解决方案 1:

截至 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, " ".join(sys.argv), None, 1)

如果您使用的是 Python 2.x,那么您应该将最后一行替换为:

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

还要注意,如果你将 Python 脚本转换为可执行文件(使用py2exe、、等工具cx_freezepyinstaller,那么你应该在第四个参数中使用sys.argv[1:]而不是。sys.argv

以下列出一些优点:

  • 无需外部库。它仅使用ctypes标准sys库。

  • 适用于 Python 2 和 Python 3。

  • 无需修改文件资源,也无需创建清单文件。

  • 如果您不在 if/else 语句下面添加代码,代码将不会被执行两次。

  • 您可以在最后一行获取 API 调用的返回值,并在失败时(代码 <= 32)采取行动。在此处检查可能的返回值。

  • 您可以通过修改第六个参数来改变生成的进程的显示方法。

有关底层 ShellExecute 调用的文档在这里。

解决方案 2:

我花了一段时间才让 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)

解决方案 3:

似乎暂时没有办法提升应用程序权限以便您执行特定任务。Windows 需要在程序启动时知道应用程序是否需要某些权限,并且会在应用程序执行任何需要这些权限的任务时要求用户确认。有两种方法可以做到这一点:

  1. 编写清单文件,告知 Windows 应用程序可能需要一些权限

  2. 从另一个程序内部以提升的权限运行该应用程序

这两篇 文章更详细地解释了其工作原理。

如果您不想为 CreateElevatedProcess API 编写一个讨厌的 ctypes 包装器,我会使用 Code Project 文章中解释的 ShellExecuteEx 技巧(Pywin32 附带了 ShellExecute 的包装器)。怎么做?像这样:

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

由于您将程序描述为“脚本”,我想这足以满足您的需要。

干杯。

解决方案 4:

只是添加这个答案以防其他人像我一样通过 Google 搜索定向到这里。我elevate在 Python 脚本中使用了该模块,并在 Windows 10 中使用管理员权限执行了该脚本。

https://pypi.org/project/elevate/

解决方案 5:

以下示例基于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()

解决方案 6:

认识到这个问题是几年前提出的,我认为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    

这利用了 COM 接口并自动指示需要管理员权限,如果您将文件复制到需要管理员权限的目录中,您会看到熟悉的对话框提示,并且在复制操作期间提供典型的文件进度对话框。

解决方案 7:

对于单行代码,将代码放到需要 UAC 的地方。

请求 UAC,若失败则继续运行:

import ctypes, sys

ctypes.windll.shell32.IsUserAnAdmin() or ctypes.windll.shell32.ShellExecuteW(
    None, "runas", sys.executable, " ".join(sys.argv), None, 1) > 32 and exit()


请求 UAC,若失败则退出:

import ctypes, sys

ctypes.windll.shell32.IsUserAnAdmin() or (ctypes.windll.shell32.ShellExecuteW(
    None, "runas", sys.executable, " ".join(sys.argv), None, 1) > 32, exit())

功能样式:

# Created by BaiJiFeiLong@gmail.com at 2022/6/24
import ctypes
import sys


def request_uac_or_skip():
    ctypes.windll.shell32.IsUserAnAdmin() or ctypes.windll.shell32.ShellExecuteW(
        None, "runas", sys.executable, " ".join(sys.argv), None, 1) > 32 and sys.exit()


def request_uac_or_exit():
    ctypes.windll.shell32.IsUserAnAdmin() or (ctypes.windll.shell32.ShellExecuteW(
        None, "runas", sys.executable, " ".join(sys.argv), None, 1) > 32, sys.exit())

解决方案 8:

这可能无法完全回答您的问题,但您也可以尝试使用 Elevate Command Powertoy 以提升的 UAC 权限运行脚本。

http://technet.microsoft.com/en-us/magazine/2008.06.elevation.aspx

我认为如果你使用它它看起来会像'elevate python yourscript.py'

解决方案 9:

您可以在某处创建一个快捷方式并将其作为目标使用:python yourscript.py,然后在属性和高级下选择以管理员身份运行。

当用户执行快捷方式时,它会要求他们提升应用程序。

解决方案 10:

上述 Jorenko 作品的一个变体允许提升的进程使用相同的控制台(但请参阅下面的评论):

def spawn_as_administrator():
    """ Spawn ourself with administrator rights and wait for new process to exit
        Make the new process use the same console as the old one.
          Raise Exception() if we could not get a handle for the new re-run the process
          Raise pywintypes.error() if we could not re-spawn
        Return the exit code of the new process,
          or return None if already running the second admin process. """
    #pylint: disable=no-name-in-module,import-error
    import win32event, win32api, win32process
    import win32com.shell.shell as shell
    if '--admin' in sys.argv:
        return None
    script = os.path.abspath(sys.argv[0])
    params = ' '.join([script] + sys.argv[1:] + ['--admin'])
    SEE_MASK_NO_CONSOLE = 0x00008000
    SEE_MASK_NOCLOSE_PROCESS = 0x00000040
    process = shell.ShellExecuteEx(lpVerb='runas', lpFile=sys.executable, lpParameters=params, fMask=SEE_MASK_NO_CONSOLE|SEE_MASK_NOCLOSE_PROCESS)
    hProcess = process['hProcess']
    if not hProcess:
        raise Exception("Could not identify administrator process to install drivers")
    # It is necessary to wait for the elevated process or else
    #  stdin lines are shared between 2 processes: they get one line each
    INFINITE = -1
    win32event.WaitForSingleObject(hProcess, INFINITE)
    exitcode = win32process.GetExitCodeProcess(hProcess)
    win32api.CloseHandle(hProcess)
    return exitcode

解决方案 11:

这主要是对 Jorenko 答案的升级,允许在 Windows 中使用带空格的参数,但在 Linux 上也应该可以很好地工作:) 此外,由于我们不使用__file__sys.argv[0]作为可执行文件,因此可以与 cx_freeze 或 py2exe 一起使用

[编辑] 免责声明:本文中的代码已过时。
我已将提升代码发布为 Python 包。
使用以下方式安装pip install command_runner

用法:

from command_runner.elevate import elevate

def main():
    """My main function that should be elevated"""
    print("Who's the administrator, now ?")

if __name__ == '__main__':
    elevate(main)

[/编辑]

import sys,ctypes,platform

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

if __name__ == '__main__':

    if platform.system() == "Windows":
        if is_admin():
            main(sys.argv[1:])
        else:
            # Re-run the program with admin rights, don't use __file__ since py2exe won't know about it
            # Use sys.argv[0] as script path and sys.argv[1:] as arguments, join them as lpstr, quoting each parameter or spaces will divide parameters
            lpParameters = ""
            # Litteraly quote all parameters which get unquoted when passed to python
            for i, item in enumerate(sys.argv[0:]):
                lpParameters += '"' + item + '" '
            try:
                ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, lpParameters , None, 1)
            except:
                sys.exit(1)
    else:
        main(sys.argv[1:])

解决方案 12:

如果您的脚本始终需要管理员权限,那么:

runas /user:Administrator "python your_script.py"
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1579  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1355  
  信创产品在政府采购中的占比分析随着信息技术的飞速发展以及国家对信息安全重视程度的不断提高,信创产业应运而生并迅速崛起。信创,即信息技术应用创新,旨在实现信息技术领域的自主可控,减少对国外技术的依赖,保障国家信息安全。政府采购作为推动信创产业发展的重要力量,其对信创产品的采购占比情况备受关注。这不仅关系到信创产业的发展前...
信创和国产化的区别   8  
  信创,即信息技术应用创新产业,旨在实现信息技术领域的自主可控,摆脱对国外技术的依赖。近年来,国货国用信创发展势头迅猛,在诸多领域取得了显著成果。这一发展趋势对科技创新产生了深远的推动作用,不仅提升了我国在信息技术领域的自主创新能力,还为经济社会的数字化转型提供了坚实支撑。信创推动核心技术突破信创产业的发展促使企业和科研...
信创工作   9  
  信创技术,即信息技术应用创新产业,旨在实现信息技术领域的自主可控与安全可靠。近年来,信创技术发展迅猛,对中小企业产生了深远的影响,带来了诸多不可忽视的价值。在数字化转型的浪潮中,中小企业面临着激烈的市场竞争和复杂多变的环境,信创技术的出现为它们提供了新的发展机遇和支撑。信创技术对中小企业的影响技术架构变革信创技术促使中...
信创国产化   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用