Ich möchte, dass mein Python - Skript Dateien unter Vista kopiert. Wenn ich es von einem normalen cmd.exe
Fenster, es werden keine Fehler generiert, die Dateien werden jedoch NICHT kopiert. Wenn ich cmd.exe
"als Administrator" und dann mein Skript ausführen, funktioniert es gut.
Dies ist sinnvoll, da die Benutzerkontensteuerung (User Account Control, UAC) normalerweise viele Dateisystemaktionen verhindert.
Gibt es eine Möglichkeit, wie ich aus einem Python Skript heraus eine UAC-Erhöhungsanforderung aufrufen kann?
Wenn das nicht möglich ist, kann mein Skript dann zumindest erkennen, dass es nicht erhöht ist, sodass es ordnungsgemäß fehlschlagen kann?
Ab 2017 ist eine einfache Methode, dies zu erreichen, die folgende:
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)
Wenn Sie Python 2.x verwenden, sollten Sie die letzte Zeile ersetzen für:
ctypes.windll.Shell32.ShellExecuteW(None, u"runas", unicode(sys.executable), unicode(__file__), None, 1)
Beachten Sie auch, dass Sie python script in eine ausführbare Datei konvertiert haben (mit Tools wie py2exe
, cx_freeze
, pyinstaller
), dann sollten Sie den vierten Parameter für eine leere Zeichenfolge ersetzen (""
).
Einige der Vorteile sind hier:
ctypes
aus der Standardbibliothek.Die Dokumentation für den zugrunde liegenden ShellExecute-Aufruf lautet hier .
Es hat eine Weile gedauert, bis die Antwort von Dguaraglia funktioniert hat. Um anderen Zeit zu sparen, habe ich Folgendes getan, um diese Idee umzusetzen:
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)
Es scheint, als gäbe es keine Möglichkeit, die Anwendungsberechtigungen für eine Weile zu erhöhen, damit Sie eine bestimmte Aufgabe ausführen können. Windows muss beim Start des Programms wissen, ob für die Anwendung bestimmte Berechtigungen erforderlich sind, und fordert den Benutzer auf, zu bestätigen, wann die Anwendung Aufgaben ausführt, die erforderlich sind diese Privilegien. Hierfür gibt es zwei Möglichkeiten:
Diese zweiArtikel erklären viel detaillierter, wie dies funktioniert.
Was ich tun würde, wenn Sie keinen bösen C-Typ-Wrapper für die CreateElevatedProcess-API schreiben möchten, ist die Verwendung des ShellExecuteEx-Tricks, der im Artikel zum Code-Projekt erläutert wird (Pywin32 wird mit einem Wrapper für ShellExecute geliefert). Wie? Etwas wie das:
Wenn Ihr Programm startet, prüft es, ob es über Administratorrechte verfügt, wenn es sich nicht selbst mithilfe des ShellExecute-Tricks ausführt, und beendet es sofort, wenn dies der Fall ist, führt es die jeweilige Aufgabe aus.
Da Sie Ihr Programm als "Skript" bezeichnen, reicht das für Ihre Anforderungen aus.
Prost.
In Anbetracht der Tatsache, dass diese Frage vor Jahren gestellt wurde, wird am github von frmdstryr mit seinem Modul pyminutils eine elegantere Lösung angeboten:
Auszug:
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
Dies nutzt die COM-Schnittstelle und zeigt automatisch an, dass Administratorrechte mit dem vertrauten Dialogfeld erforderlich sind. Aufforderung, dass Sie sehen würden, ob Sie in ein Verzeichnis kopieren, in dem Administratorrechte erforderlich sind, und bietet außerdem das typische Dialogfeld für den Dateiverlauf während des Kopiervorgangs.
Das folgende Beispiel baut auf MARTIN DE LA FUENTE SAAVEDRA exzellenter Arbeit und akzeptierter Antwort auf. Insbesondere werden zwei Aufzählungen eingeführt. Die erste ermöglicht eine einfache Spezifikation, wie ein erweitertes Programm geöffnet werden soll, und die zweite hilft, wenn Fehler leicht identifiziert werden müssen. Bitte beachten Sie, dass, wenn alle Befehlszeilenargumente an den neuen Prozess übergeben werden sollen, sys.argv[0]
Wahrscheinlich durch einen Funktionsaufruf ersetzt werden sollte: 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 __== '__main__':
bootstrap()
Dies beantwortet Ihre Frage möglicherweise nicht vollständig, aber Sie können auch versuchen, das Elevate Command Powertoy zu verwenden, um das Skript mit erhöhten UAC-Berechtigungen auszuführen.
http://technet.Microsoft.com/en-us/magazine/2008.06.elevation.aspx
Ich denke, wenn Sie es verwenden, würde es aussehen wie 'elevate python yourscript.py'
Eine Variation von Jorenkos Arbeit oben ermöglicht es dem erhöhten Prozess, dieselbe Konsole zu verwenden (siehe meinen Kommentar unten):
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
Sie können irgendwo eine Verknüpfung erstellen und als Ziel verwenden: python yourscript.py dann unter Eigenschaften und erweiterte Auswahl als Administrator ausführen.
Wenn der Benutzer die Verknüpfung ausführt, fordert er ihn auf, die Anwendung zu öffnen.
Dies ist hauptsächlich ein Upgrade von Jorenkos Antwort, das die Verwendung von Parametern mit Leerzeichen in Windows ermöglicht, aber auch unter Linux recht gut funktionieren sollte :) Funktioniert auch mit cx_freeze oder py2exe, da wir nicht __file__
Verwenden, sondern sys.argv[0]
Als ausführbare Datei
import sys,ctypes,platform
def is_admin():
try:
return ctypes.windll.Shell32.IsUserAnAdmin()
except:
raise False
if __== '__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:])
Wenn für Ihr Skript immer Administratorrechte erforderlich sind, gehen Sie wie folgt vor:
runas /user:Administrator "python your_script.py"