source

Python 스크립트 내에서 UAC 권한 상승을 요청하시겠습니까?

ittop 2023. 4. 27. 22:43
반응형

Python 스크립트 내에서 UAC 권한 상승을 요청하시겠습니까?

나는 내 파이썬 스크립트가 비스타에서 파일을 복사하기를 원합니다.정상적인 상태에서 실행할 수 있습니다.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, " ".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_freeze,pyinstaller그러면 당신은 사용해야 합니다.sys.argv[1:]sys.argv네 번째 파라미터에 있습니다.

여기서 얻을 수 있는 이점은 다음과 같습니다.

  • 외부 라이브러리가 필요하지 않습니다.사용만 가능합니다.ctypes그리고.sys표준 도서관에서.
  • Python 2와 Python 3 모두에서 작동합니다.
  • 파일 리소스를 수정하거나 매니페스트 파일을 만들 필요가 없습니다.
  • if/else 문 아래에 코드를 추가하지 않으면 코드가 두 번 실행되지 않습니다.
  • API 호출의 반환값을 마지막 줄에서 얻고 실패 시 조치를 취할 수 있습니다(코드 <= 32).가능한 반환 을 여기에서 확인하십시오.
  • 여섯 번째 모수를 수정하는 생성된 공정의 표시 방법을 변경할 수 있습니다.

기본 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)

특정 작업을 수행하기 위해 당분간 응용 프로그램 권한을 높일 수 있는 방법이 없는 것 같습니다.프로그램을 시작할 때 응용 프로그램에 특정 권한이 필요한지 여부를 알아야 하며 응용 프로그램이 해당 권한이 필요한 작업을 수행할 때 사용자에게 확인을 요청합니다.두 가지 방법이 있습니다.

  1. 응용 프로그램에 일부 권한이 필요할 수 있음을 Windows에 알리는 매니페스트 파일 작성
  2. 다른 프로그램 내부에서 상승된 권한으로 응용 프로그램 실행

개의 기사는 이것이 어떻게 작동하는지 훨씬 더 자세히 설명합니다.

CreateElevatedProcess API에 대해 불쾌한 ctypes 래퍼를 작성하고 싶지 않다면 코드 프로젝트 기사에 설명된 ShellExecute 트릭을 사용합니다(Pywin32는 ShellExecute용 래퍼와 함께 제공됨).어떻게요? 이런 거요.

프로그램이 시작되면 관리자 권한이 있는지 확인하고, 프로그램이 실행되지 않으면 ShellExecute 트릭을 사용하여 자동으로 실행되고, 실행되면 즉시 종료되며, 실행 중인 작업을 수행합니다.

당신이 당신의 프로그램을 "스크립트"라고 묘사한 것처럼, 저는 그것이 당신의 필요에 충분하다고 생각합니다.

건배.

다른 사람들이 저처럼 구글 검색에 의해 여기에 지시될 경우를 대비하여 이 답변을 추가하는 것입니다.사용했습니다.elevate모듈과 Windows 10에서 관리자 권한으로 실행되는 스크립트가 있습니다.

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

다음 예시는 MARTIN DE LA FUENTE SAVEDRA의 우수한 작업과 수용된 답변을 기반으로 합니다.특히, 두 개의 열거형이 소개됩니다.첫 번째는 상승된 프로그램을 여는 방법을 쉽게 지정할 수 있도록 하고, 두 번째는 오류를 쉽게 식별해야 할 때 도움이 됩니다.모든 명령줄 인수를 새 프로세스에 전달하려면 다음을 수행하십시오.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()

이 질문이 수년 전에 제기된 것임을 인식하고, 저는 frmdstrryr이 모듈 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 인터페이스가 사용되며 관리자 권한이 필요한 디렉토리에 복사했는지 확인할 수 있는 익숙한 대화 상자 프롬프트에서 관리자 권한이 필요함을 자동으로 나타내며 복사 작업 중 일반적인 파일 진행률 대화 상자도 제공합니다.

이렇게 하면 질문에 완전히 대답할 수는 없지만 상승된 UAC 권한으로 스크립트를 실행하기 위해 상승 명령 파워토이를 사용해 볼 수도 있습니다.

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

만약 당신이 그것을 사용한다면 그것은 'python 당신의 스크립트를 상승시키는' 것처럼 보일 것이라고 생각합니다.파이'

어딘가에 바로 가기를 만들 수 있고 대상으로 python yourscript.py 을 사용한 다음 속성 및 고급 선택에서 관리자로 실행을 선택할 수 있습니다.

사용자가 바로 가기를 실행하면 응용프로그램을 올리도록 요청합니다.

위의 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

이것은 대부분 Windows에서 공백이 있는 매개 변수를 사용할 수 있는 Jorenko의 답변을 업그레이드한 것이지만 Linux에서도 상당히 잘 작동할 것입니다 :) 또한 사용하지 않기 때문에 cx_freeze 또는 py2exe와 함께 작동할 것입니다.__file__그렇지만sys.argv[0]실행할 수 있는 대로

[EDIT] 고지 사항:이 게시물의 코드는 오래되었습니다.권한 상승 코드를 파이썬 패키지로 게시했습니다.설치 대상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:])

한 줄기의 경우, 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())

스크립트에 항상 관리자 권한이 필요한 경우:

runas /user:Administrator "python your_script.py"

언급URL : https://stackoverflow.com/questions/130763/request-uac-elevation-from-within-a-python-script

반응형