Я хочу, чтобы мой скрипт Python копировал файлы в Vista. Когда я запускаю его из обычного cmd.exe
окна, ошибок не возникает, но файлы НЕ копируются. Если я запускаю cmd.exe
«как администратор», а затем запускаю свой сценарий, он работает нормально.
Это имеет смысл, поскольку контроль учетных записей пользователей (UAC) обычно предотвращает многие действия файловой системы.
Можно ли из сценария Python вызвать запрос на повышение прав UAC (в тех диалоговых окнах, которые говорят что-то вроде «такому-то приложению нужен доступ администратора, это нормально?»)
Если это невозможно, есть ли способ, которым мой сценарий может по крайней мере обнаружить, что он не повышен, чтобы он мог корректно завершиться с ошибкой?
python
windows
windows-vista
uac
Jwfearn
источник
источник
Ответы:
По состоянию на 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)
Также обратите внимание , что если вы конвертированы вам питон скрипт в исполняемый файл ( с помощью таких инструментов , как
py2exe
,cx_freeze
,pyinstaller
) , то вы должны использоватьsys.argv[1:]
вместоsys.argv
в четвертом параметре.Вот некоторые из преимуществ:
ctypes
иsys
из стандартной библиотеки.Документация для основного вызова ShellExecute находится здесь .
источник
ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, "", None, 1)
sys.executable
разрешается только интерпретатор python (напримерC:\Python27\Python.exe
). Решение состоит в том, чтобы добавить запущенный скрипт в качестве аргумента (замена""
).ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, __file__, None, 1)
Также обратите внимание, что для этого , чтобы работать в Python 2.x, все строковые аргументы должны быть Unicode (то естьu"runas"
,unicode(sys.executable)
аunicode(__file__)
)ShellExecuteW
иShellExecuteA
являются вызовамиShellExecute
функции в Windows API. Первый обязывает строки быть в формате Unicode, а второй используется с форматом ANSIМне потребовалось некоторое время, чтобы получить ответ от 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)
источник
subprocess.list2cmdline
чтобы сделать это правильно.Кажется, что нет возможности на время повысить привилегии приложения, чтобы вы могли выполнять конкретную задачу. Windows должна знать при запуске программы, требует ли приложение определенных привилегий, и будет запрашивать у пользователя подтверждение, когда приложение выполняет какие-либо задачи, требующие этих привилегий. Есть два способа сделать это:
В этих двух статьях более подробно объясняется, как это работает.
Что бы я сделал, если вы не хотите писать неприятную оболочку ctypes для API CreateElevatedProcess, это использовать трюк ShellExecuteEx, описанный в статье Code Project (Pywin32 поставляется с оболочкой для ShellExecute). Как? Что-то вроде этого:
Когда ваша программа запускается, она проверяет, есть ли у нее права администратора, если нет, запускается сама с помощью трюка ShellExecute и немедленно завершает работу, если да, то выполняет поставленную задачу.
Поскольку вы описываете свою программу как «сценарий», я полагаю, что этого достаточно для ваших нужд.
Ура.
источник
runas
выводит новую подсказку. И StartFile не принимает аргументы командной строки$EXECUTABLE.
.chm
файла.Просто добавляю этот ответ на тот случай, если другие направляются сюда поиском Google, как и я. Я использовал
elevate
модуль в своем скрипте Python и скрипт, выполненный с правами администратора в Windows 10.https://pypi.org/project/elevate/
источник
elevate
модуль и получаю ошибку «Файл не доступен для системы», есть идеи, почему это могло произойти?Следующий пример основан на отличной работе 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()
источник
Учитывая, что этот вопрос был задан много лет назад, я думаю, что на github frmdstryr предлагает более элегантное решение с использованием его модуля pywinutils:
Отрывок:
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 и автоматически указывается, что необходимы права администратора, с помощью знакомого диалогового окна, которое вы могли бы увидеть, если бы вы копировали в каталог, где требуются права администратора, а также предоставляет типичный диалог выполнения файла во время операции копирования.
источник
Это может не полностью ответить на ваш вопрос, но вы также можете попробовать использовать Powertoy команды Elevate, чтобы запустить сценарий с повышенными привилегиями UAC.
http://technet.microsoft.com/en-us/magazine/2008.06.elevation.aspx
Я думаю, если вы воспользуетесь им, это будет выглядеть как «поднять python yourscript.py»
источник
Вы можете создать ярлык где-нибудь и в качестве цели использовать: python yourscript.py, затем в свойствах и дополнительных настройках выберите запуск от имени администратора.
Когда пользователь запускает ярлык, он попросит его повысить уровень приложения.
источник
Если ваш сценарий всегда требует прав администратора, тогда:
runas /user:Administrator "python your_script.py"
источник
your_script.py
от имени администратора. Убедитесь, что вы поняли комментарий @Kugel .Вариант работы Йоренко выше позволяет процессу с повышенными правами использовать ту же консоль (но см. Мой комментарий ниже):
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, но также должно работать достаточно хорошо в Linux :) Кроме того, он будет работать с cx_freeze или py2exe, поскольку мы не используем,
__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:])
источник