it-swarm.com.de

Wie man ein Python-Skript mit erhöhten Rechten für Windows ausführt

Ich schreibe eine Pyqt-Anwendung, die Admin-Task ausführen muss. Ich würde es vorziehen, mein Skript mit einem erhöhten Privileg zu starten. Mir ist bekannt, dass diese Frage oft in SO oder in einem anderen Forum gestellt wird. Aber die Lösung, die die Leute vorschlagen, ist, diese SO - Frage zu betrachten UAC-Erhöhung aus einem Python-Skript anfordern?

Ich kann jedoch den im Link angegebenen Beispielcode nicht ausführen. Ich habe diesen Code auf die Hauptdatei gesetzt und versucht, ihn auszuführen. 

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)
print "I am root now."

Es wird tatsächlich um Erlaubnis zum Erhöhen gebeten, aber die Druckzeile wird nie ausgeführt. Jemand kann mir helfen, den obigen Code erfolgreich auszuführen. Danke im Voraus.

41
sundar_ima

Vielen Dank für Ihre Antwort. Ich habe mein Skript mit dem von Preston Landers geschriebenen Modul/Skript zusammenarbeiten lassen. Nach zwei Tagen im Internet konnte ich feststellen, dass das Skript in der pywin32-Mailingliste verborgen war. Mit diesem Skript ist es einfacher zu überprüfen, ob der Benutzer admin ist, und wenn nicht, fragen Sie nach UAC/admin-Rechten. Es liefert Ausgabe in separaten Fenstern, um herauszufinden, was der Code tut. Beispiel für die Verwendung des im Skript enthaltenen Codes. Für alle, die alle nach UAC unter Windows suchen, schauen Sie sich diesen Code an. Ich hoffe, es hilft jemandem, nach der gleichen Lösung zu suchen. Es kann so etwas aus Ihrem Hauptskript verwendet werden: -

import admin
if not admin.isUserAdmin():
        admin.runAsAdmin()

Der eigentliche Code lautet: -

#!/usr/bin/env python
# -*- coding: utf-8; mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
# vim: fileencoding=utf-8 tabstop=4 expandtab shiftwidth=4

# (C) COPYRIGHT © Preston Landers 2010
# Released under the same license as Python 2.6.5


import sys, os, traceback, types

def isUserAdmin():

    if os.name == 'nt':
        import ctypes
        # WARNING: requires Windows XP SP2 or higher!
        try:
            return ctypes.windll.Shell32.IsUserAnAdmin()
        except:
            traceback.print_exc()
            print "Admin check failed, assuming not an admin."
            return False
    Elif os.name == 'posix':
        # Check for root on Posix
        return os.getuid() == 0
    else:
        raise RuntimeError, "Unsupported operating system for this module: %s" % (os.name,)

def runAsAdmin(cmdLine=None, wait=True):

    if os.name != 'nt':
        raise RuntimeError, "This function is only implemented on Windows."

    import win32api, win32con, win32event, win32process
    from win32com.Shell.shell import ShellExecuteEx
    from win32com.Shell import shellcon

    python_exe = sys.executable

    if cmdLine is None:
        cmdLine = [python_exe] + sys.argv
    Elif type(cmdLine) not in (types.TupleType,types.ListType):
        raise ValueError, "cmdLine is not a sequence."
    cmd = '"%s"' % (cmdLine[0],)
    # XXX TODO: isn't there a function or something we can call to massage command line params?
    params = " ".join(['"%s"' % (x,) for x in cmdLine[1:]])
    cmdDir = ''
    showCmd = win32con.SW_SHOWNORMAL
    #showCmd = win32con.SW_HIDE
    lpVerb = 'runas'  # causes UAC elevation Prompt.

    # print "Running", cmd, params

    # ShellExecute() doesn't seem to allow us to fetch the PID or handle
    # of the process, so we can't get anything useful from it. Therefore
    # the more complex ShellExecuteEx() must be used.

    # procHandle = win32api.ShellExecute(0, lpVerb, cmd, params, cmdDir, showCmd)

    procInfo = ShellExecuteEx(nShow=showCmd,
                              fMask=shellcon.SEE_MASK_NOCLOSEPROCESS,
                              lpVerb=lpVerb,
                              lpFile=cmd,
                              lpParameters=params)

    if wait:
        procHandle = procInfo['hProcess']    
        obj = win32event.WaitForSingleObject(procHandle, win32event.INFINITE)
        rc = win32process.GetExitCodeProcess(procHandle)
        #print "Process handle %s returned code %s" % (procHandle, rc)
    else:
        rc = None

    return rc

def test():
    rc = 0
    if not isUserAdmin():
        print "You're not an admin.", os.getpid(), "params: ", sys.argv
        #rc = runAsAdmin(["c:\\Windows\\notepad.exe"])
        rc = runAsAdmin()
    else:
        print "You are an admin!", os.getpid(), "params: ", sys.argv
        rc = 0
    x = raw_input('Press Enter to exit.')
    return rc


if __== "__main__":
    sys.exit(test())
62
sundar_ima

in den Kommentaren zu der antwort haben Sie den Code von genommen, jemand sagt ShellExecuteEx schreibt seinen STDOUT nicht zurück in die Ursprungs-Shell. Sie sehen also nicht "Ich bin jetzt root", obwohl der Code wahrscheinlich gut funktioniert.

anstatt etwas zu drucken, schreiben Sie in eine Datei:

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)
with open("somefilename.txt", "w") as out:
    print >> out, "i am root"

und dann in die Datei schauen.

8
andrew cooke

Hier ist eine Lösung mit einer stdout-Umleitung:

def elevate():
    import ctypes, win32com.Shell.shell, win32event, win32process
    outpath = r'%s\%s.out' % (os.environ["TEMP"], os.path.basename(__file__))
    if ctypes.windll.Shell32.IsUserAnAdmin():
        if os.path.isfile(outpath):
            sys.stderr = sys.stdout = open(outpath, 'w', 0)
        return
    with open(outpath, 'w+', 0) as outfile:
        hProc = win32com.Shell.shell.ShellExecuteEx(lpFile=sys.executable, \
            lpVerb='runas', lpParameters=' '.join(sys.argv), fMask=64, nShow=0)['hProcess']
        while True:
            hr = win32event.WaitForSingleObject(hProc, 40)
            while True:
                line = outfile.readline()
                if not line: break
                sys.stdout.write(line)
            if hr != 0x102: break
    os.remove(outpath)
    sys.stderr = ''
    sys.exit(win32process.GetExitCodeProcess(hProc))

if __== '__main__':
    elevate()
    main()
6
Florent B.

Hier ist eine Lösung, die nur das Modul ctypes benötigt. Unterstützt pyinstaller umschlossenes Programm.

#!python
# coding: utf-8
import sys
import ctypes

def run_as_admin(argv=None, debug=False):
    Shell32 = ctypes.windll.Shell32
    if argv is None and Shell32.IsUserAnAdmin():
        return True

    if argv is None:
        argv = sys.argv
    if hasattr(sys, '_MEIPASS'):
        # Support pyinstaller wrapped program.
        arguments = map(unicode, argv[1:])
    else:
        arguments = map(unicode, argv)
    argument_line = u' '.join(arguments)
    executable = unicode(sys.executable)
    if debug:
        print 'Command line: ', executable, argument_line
    ret = Shell32.ShellExecuteW(None, u"runas", executable, argument_line, None, 1)
    if int(ret) <= 32:
        return False
    return None


if __== '__main__':
    ret = run_as_admin()
    if ret is True:
        print 'I have admin privilege.'
        raw_input('Press ENTER to exit.')
    Elif ret is None:
        print 'I am elevating to admin privilege.'
        raw_input('Press ENTER to exit.')
    else:
        print 'Error(ret=%d): cannot elevate privilege.' % (ret, )
5
Gary Lee

Ich habe eine sehr einfache Lösung für dieses Problem gefunden.

  1. Erstellen Sie eine Verknüpfung für python.exe
  2. Ändern Sie das Verknüpfungsziel in etwas wie C:\xxx\...\python.exe your_script.py.
  3. Klicken Sie im Eigenschaftenbereich der Verknüpfung auf "Erweitert ..." und klicken Sie auf die Option "Als Administrator ausführen".

Ich bin nicht sicher, ob die Zauber dieser Optionen richtig sind, da ich die chinesische Version von Windows verwende.

1
delphifirst

Auch wenn sich Ihr Arbeitsverzeichnis unterscheidet, können Sie lpDirectory verwenden

    procInfo = ShellExecuteEx(nShow=showCmd,
                          lpVerb=lpVerb,
                          lpFile=cmd,
                          lpDirectory= unicode(direc),
                          lpParameters=params)

Wird hilfreich sein, wenn das Ändern des Pfads keine wünschenswerte Option ist

0
Pranav

Ich kann bestätigen, dass die Lösung von delphifirst funktioniert und die einfachste und einfachste Lösung für das Problem ist, ein Python-Skript mit erhöhten Berechtigungen auszuführen.

Ich habe eine Verknüpfung zur ausführbaren Python-Datei (python.exe) erstellt und die Verknüpfung dann geändert, indem der Name meines Skripts nach dem Aufruf von python.exe hinzugefügt wurde. Als Nächstes habe ich auf der Registerkarte "Kompatibilität" der Verknüpfung "Als Administrator ausführen" geprüft. Wenn die Verknüpfung ausgeführt wird, erhalten Sie eine Eingabeaufforderung, mit der Sie das Skript als Administrator ausführen können.

Meine spezielle Python-Anwendung war ein Installationsprogramm. Das Programm ermöglicht die Installation und Deinstallation einer anderen Python-App. In meinem Fall habe ich zwei Verknüpfungen erstellt, eine namens "appname install" und die andere "appname uninstall". Der einzige Unterschied zwischen den beiden Tastenkombinationen ist das Argument, das auf den Namen des Python-Skripts folgt. In der Installer-Version lautet das Argument "install". In der Deinstallationsversion lautet das Argument "uninstall". Code im Installationsskript wertet das angegebene Argument aus und ruft bei Bedarf die entsprechende Funktion (Installieren oder Deinstallieren) auf.

Ich hoffe, meine Erklärung hilft anderen dabei, schneller herauszufinden, wie ein Python-Skript mit erhöhten Berechtigungen ausgeführt wird.

0
John Moore