पायथन लिपि के भीतर से UAC उत्थान का अनुरोध करें?


91

मैं चाहता हूं कि मेरी पायथन स्क्रिप्ट विस्टा पर फाइलों की नकल करे। जब मैं इसे एक सामान्य cmd.exeविंडो से चलाता हूं , तो कोई त्रुटि उत्पन्न नहीं होती है, फिर भी फाइलें कॉपी नहीं की जाती हैं। यदि मैं cmd.exe"व्यवस्थापक के रूप में" चलाता हूं और फिर अपनी स्क्रिप्ट चलाता हूं, तो यह ठीक काम करता है।

यह समझ में आता है क्योंकि उपयोगकर्ता खाता नियंत्रण (UAC) सामान्य रूप से कई फ़ाइल सिस्टम क्रियाओं को रोकता है।

क्या कोई ऐसा तरीका है जो मैं पायथन स्क्रिप्ट के भीतर से कर सकता हूं, एक यूएसी उत्थान अनुरोध (उन संवादों को कहते हैं जो कुछ इस तरह कहते हैं "जैसे और ऐसे ऐप को एडमिन एक्सेस की आवश्यकता है, क्या यह ठीक है?")

यदि यह संभव नहीं है, तो क्या कोई तरीका है जिससे मेरी स्क्रिप्ट कम से कम यह पता लगा सके कि यह ऊंचा नहीं है, इसलिए यह इनायत से विफल हो सकता है?


3
stackoverflow.com/a/1445547/1628132 इस जवाब के बाद आप .y स्क्रिप्ट से py2.exe का उपयोग करके एक .exe बनाते हैं और 'uac_info' नामक एक ध्वज का उपयोग करते हुए इसे बहुत साफ-सुथरा समाधान कहते हैं
foxcoreg

जवाबों:


96

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)

यदि आप पायथन 2.x का उपयोग कर रहे हैं, तो आपको निम्न पंक्ति को प्रतिस्थापित करना चाहिए:

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

भी ध्यान रखें कि यदि आप आप एक निष्पादन योग्य फ़ाइल में अजगर स्क्रिप्ट परिवर्तित (जैसे उपकरण का उपयोग कर py2exe, cx_freeze, pyinstaller) तो आप का उपयोग करना चाहिए sys.argv[1:]बजाय sys.argvचौथे पैरामीटर में।

यहाँ कुछ फायदे हैं:

  • किसी बाहरी पुस्तकालय की आवश्यकता नहीं है। यह केवल का उपयोग करता है ctypesऔर sysमानक पुस्तकालय से।
  • पायथन 2 और पायथन 3 दोनों पर काम करता है।
  • फ़ाइल संसाधनों को संशोधित करने की आवश्यकता नहीं है और न ही एक प्रकट फ़ाइल बनाने की आवश्यकता है।
  • यदि आप नीचे दिए गए कोड को नहीं जोड़ते हैं, तो / फिर कथन के अनुसार, कोड को कभी भी दो बार निष्पादित नहीं किया जाएगा।
  • आप अंतिम पंक्ति में एपीआई कॉल का रिटर्न मान प्राप्त कर सकते हैं और विफल होने पर एक कार्रवाई कर सकते हैं (कोड <= 32)। यहां संभावित रिटर्न मान जांचें ।
  • आप छठे पैरामीटर को संशोधित करते हुए स्पॉन्ड प्रक्रिया की प्रदर्शन विधि को बदल सकते हैं।

अंतर्निहित ShellExecute कॉल के लिए प्रलेखन यहाँ है


8
मुझे इसे चलाने के लिए यूनिकोड इंस्टेंस का उपयोग ShellExecuteW (जैसे u'runas 'और यूनिकोड (sys.executable)) के मापदंडों के रूप में करना पड़ा।
Janosch

6
@ जोंसच, ऐसा इसलिए है क्योंकि आप पायथन 2.x का उपयोग कर रहे हैं, जबकि मेरा कोड पायथन 3 में है (जहां सभी तारों को यूनिकोड के रूप में माना जाता है)। लेकिन यह उल्लेख करना अच्छा है, धन्यवाद!
मार्तीन डे ला

2
@ अगर मैं इस कोड को विंडोज कमांड लाइन से इस तरह चला रहा हूं: "python yourcode.py" यह सिर्फ python.exe खोलता है। वहाँ एक तरह से यह तय है?
user2978216

1
@ user2978216 मेरे पास एक ही मुद्दा था। लाइन ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, "", None, 1) sys.executableमें केवल अजगर दुभाषिया (उदाहरण के लिए C:\Python27\Python.exe) का समाधान होता है, समाधान चल रहे स्क्रिप्ट को एक तर्क (प्रतिकृति "") के रूप में जोड़ना है । ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, __file__, None, 1)यह भी ध्यान दें, इसके लिए अजगर 2.x में काम करने के लिए, सभी स्ट्रिंग तर्कों को यूनिकोड (यानी u"runas", unicode(sys.executable)और unicode(__file__))
जेवियर Ubillos

2
@HrvojeT दोनों, ShellExecuteWऔर विंडोज एपीआई में फ़ंक्शन के ShellExecuteAलिए कॉल हैं ShellExecute। पूर्व स्ट्रिंग्स को यूनिकोड प्रारूप में होने के लिए बाध्य करता है और उत्तरार्द्ध का उपयोग एएनएसआई प्रारूप के साथ किया जाता है
मार्टीन डी ला फ्यूएंट

69

मुझे डगररगलिया के उत्तर पर काम करने में थोड़ा समय लगा, इसलिए दूसरों के समय को बचाने के हित में, इस विचार को लागू करने के लिए मैंने यहां क्या किया:

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
यह सिर्फ ऊपर उठने और फिर बाहर निकलने के लिए लगता है ... अगर मैं कुछ प्रिंट स्टेटमेंट्स में
डालूं तो

6
@JoranBeasley, आपको कोई आउटपुट नहीं दिखेगा। ShellExecuteEx अपने STDOUT को मूल शेल पर वापस पोस्ट नहीं करता है। उस संबंध में, डिबगिंग होगा ... चुनौतीपूर्ण। लेकिन विशेषाधिकार-उत्थान की चाल निश्चित रूप से काम करती है।
टिम कीटिंग

1
@TimKeating, ActiveState के पास एक ऐसा नुस्खा है जिसे डीबग करना थोड़ा आसान होना चाहिए: मानक अजगर लॉगिंग के साथ DebugView उपयोगिता का उपयोग करें
samwyse

1
समान कंसोल में आउटपुट प्राप्त करना असंभव प्रतीत होता है, लेकिन ShellExecuteEx के तर्क nShow = 5 के साथ, एक नई कमांड विंडो एलिवेटेड स्क्रिप्ट से आउटपुट के साथ खुलेगी।
एमिल स्टायरके

2
उद्धरण के लिए, आप subprocess.list2cmdlineइसे ठीक से करने के लिए उपयोग कर सकते हैं ।
कोडरफ़ॉर्फ़िनिटी

29

ऐसा लगता है कि किसी विशेष कार्य को करने के लिए कुछ समय के लिए एप्लिकेशन विशेषाधिकार को बढ़ाने का कोई तरीका नहीं है। विंडोज को कार्यक्रम की शुरुआत में यह जानना होगा कि क्या एप्लिकेशन को कुछ विशेषाधिकारों की आवश्यकता है, और उपयोगकर्ता को यह पुष्टि करने के लिए कहेंगे कि आवेदन किसी भी कार्य को करता है जिसे उन विशेषाधिकारों की आवश्यकता है । इसे करने के दो तरीके हैं:

  1. एक मैनिफ़ेस्ट फ़ाइल लिखें जो बताता है कि विंडोज़ को एप्लिकेशन को कुछ विशेषाधिकारों की आवश्यकता हो सकती है
  2. किसी अन्य प्रोग्राम के अंदर से उन्नत विशेषाधिकार के साथ एप्लिकेशन को चलाएं

यह दो लेख बहुत अधिक विस्तार से बताते हैं कि यह कैसे काम करता है।

यदि आप CreateElevatedProcess API के लिए एक नॉटी ctypes रैपर लिखना नहीं चाहते हैं, तो मैं क्या करूँगा, कोड प्रोजेक्ट आलेख में बताई गई ShellExecuteEx चाल का उपयोग करता है (Pywin32 ShellExute के लिए एक आवरण के साथ आता है)। कैसे? कुछ इस तरह:

जब आपका प्रोग्राम शुरू होता है, तो यह जांचता है कि इसमें प्रशासक के विशेषाधिकार हैं या नहीं, यदि यह स्वयं शेलएक्स्यूट्यूट ट्रिक का उपयोग करके नहीं चलता है और तुरंत बाहर निकल जाता है, यदि ऐसा होता है, तो यह कार्य हाथ में करता है।

जैसा कि आप अपने कार्यक्रम को "स्क्रिप्ट" के रूप में वर्णित करते हैं, मुझे लगता है कि यह आपकी आवश्यकताओं के लिए पर्याप्त है।

चीयर्स।


उन लिंक के लिए धन्यवाद, वे यूएसी सामान के बारे में बहुत कुछ पता लगाने के लिए मेरे लिए बहुत उपयोगी थे।
कॉलन

4
कुछ आप इस पर ध्यान देना चाह सकते हैं कि आप os.startfile ($ EXECUTABLE, "रनस") का उपयोग करके PyWin32 के बिना ShellExecute कर सकते हैं (मुझे इसे स्थापित करने में समस्या थी)।
Mc में मैक मैकायड

@ माइक - लेकिन runasहालांकि एक नया संकेत लाता है। और startfile कमांड लाइन तर्क स्वीकार नहीं करता है$EXECUTABLE.
श्रीधर रत्नाकुमार

मैंने इस तकनीक के पूर्ण कार्यान्वयन के साथ एक और उत्तर जोड़ा, जो किसी भी अजगर स्क्रिप्ट की शुरुआत में जोड़ा जा सकता है।
जोरेंको

दूसरी कड़ी का लेख था, "MSDN मैगज़ीन जनवरी 2007" में "लिस्ट प्रिविलेज: टीच योर एप्स टू प्ले विथ विथ विंडोज विस्टा यूजर अकाउंट कंट्रोल", लेकिन यह मुद्दा अब केवल .chmफाइल के रूप में उपलब्ध है ।
पीटर

6

इस उत्तर को जोड़ने के मामले में अन्य लोगों को यहां Google खोज द्वारा निर्देशित किया गया है जैसा कि मैं था। मैंने elevateअपनी पायथन लिपि में मॉड्यूल का उपयोग किया और स्क्रिप्ट को विंडोज 10 में प्रशासक विशेषाधिकार के साथ निष्पादित किया गया।

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


अरे, मैंने elevateमॉड्यूल का उपयोग करने की कोशिश की और मुझे "सिस्टम द्वारा फ़ाइल को एक्सेस नहीं किया जा सकता है" त्रुटि, किसी भी विचार कि ऐसा क्यों होगा?
paxos1977

@ paxos1977 क्या आप एक कोड स्निपेट पोस्ट कर सकते हैं जो उस त्रुटि को प्रदर्शित करता है? धन्यवाद!
इरविंग मोय

4

निम्न उदाहरण पर बनाता है मार्टिन डे ला फुएंटे सावेदरा के उत्कृष्ट काम और स्वीकृत उत्तर । विशेष रूप से, दो गणना पेश की जाती हैं। पहला आसान विनिर्देशन के लिए अनुमति देता है कि कैसे एक ऊंचा कार्यक्रम खोला जाना है, और दूसरा मदद करता है जब त्रुटियों को आसानी से पहचानने की आवश्यकता होती है। कृपया ध्यान दें कि यदि आप चाहते हैं कि सभी कमांड लाइन तर्क नई प्रक्रिया में पारित हो जाएं, 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()

4

इस प्रश्न को मान्यता देते हुए वर्षों पहले पूछा गया था, मुझे लगता है कि जीथब पर अधिक सुरुचिपूर्ण समाधान पेश किया गया है उनके मॉड्यूल pywinutils का उपयोग करके frmdstryr द्वारा :

अंश:

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 इंटरफ़ेस का उपयोग करता है और स्वचालित रूप से इंगित करता है कि व्यवस्थापक विशेषाधिकार परिचित डायलॉग प्रॉम्प्ट के साथ आवश्यक हैं जो कि आप देखेंगे कि क्या आप एक निर्देशिका में कॉपी कर रहे हैं जहां व्यवस्थापक विशेषाधिकारों की आवश्यकता होती है और कॉपी ऑपरेशन के दौरान विशिष्ट फ़ाइल प्रगति संवाद भी प्रदान करता है।


2

यह पूरी तरह से आपके प्रश्न का उत्तर नहीं दे सकता है, लेकिन आप एलिवेटेड एएसी विशेषाधिकार के साथ स्क्रिप्ट को चलाने के लिए एलिवेट कमांड पॉवरटॉय का उपयोग करने का भी प्रयास कर सकते हैं।

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

मुझे लगता है कि यदि आप इसका उपयोग करते हैं तो यह 'एलीवेट पाइथ हियरस्क्रिप्ट' जैसा लगेगा।


2

आप कहीं और लक्ष्य के रूप में शॉर्टकट का उपयोग कर सकते हैं: python yourscript.py फिर संपत्तियों के अंतर्गत और व्यवस्थापक के रूप में उन्नत चयन चलाएं।

जब उपयोगकर्ता शॉर्टकट निष्पादित करता है तो यह उन्हें एप्लिकेशन को ऊंचा करने के लिए कहेगा।


1

यदि आपकी स्क्रिप्ट को हमेशा एक प्रशासक के विशेषाधिकारों की आवश्यकता होती है तो:

runas /user:Administrator "python your_script.py"

14
सावधान, उन्नयन! = प्रशासक के रूप में चल रहा है
कुगेल

मैं अजगर के लिए नया हूं ... क्या आप मुझे बता सकते हैं कि मैं वह कोड कहां डालूंगा?
रहत इस्लाम खान

@RahatIslamKhan: एक कमांड प्रॉम्प्ट विंडो खोलें और इसे वहां रखें: कमांड your_script.pyएक प्रशासक उपयोगकर्ता के रूप में चलता है । सुनिश्चित करें कि आप @ कुगेल की टिप्पणी को समझते हैं ।
jfs

1

जोरेन्को के काम के ऊपर एक बदलाव एक ही कंसोल का उपयोग करने के लिए उन्नत प्रक्रिया की अनुमति देता है (लेकिन नीचे मेरी टिप्पणी देखें):

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

माफ़ करना। समान कंसोल विकल्प (SEE_MASK_NO_CONSOLE) केवल तभी काम करता है जब आप पहले से ही उन्नत हैं। मेरी गलती।
बरवाइन

1

यह ज्यादातर जोरेन्को के जवाब के लिए एक उन्नयन है, जो विंडोज में रिक्त स्थान के साथ मापदंडों का उपयोग करने की अनुमति देता है, लेकिन लिनक्स पर भी काफी अच्छी तरह से काम करना चाहिए :) इसके अलावा, cx_freeze या py2.exe के साथ काम करेंगे क्योंकि हम उपयोग नहीं करते हैं __file__लेकिन sys.argv[0]निष्पादन योग्य के रूप में

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:])
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.