111

PythonスクリプトでVistaにファイルをコピーしたい。通常のcmd.exeウィンドウから実行すると、エラーは生成されませんが、ファイルはコピーされません。cmd.exe「管理者として」実行してからスクリプトを実行すると、正常に機能します。

ユーザーアカウント制御(UAC)は通常、多くのファイルシステムアクションを防止するため、これは理にかなっています。

Pythonスクリプト内から、UAC昇格要求を呼び出す方法はありますか(「そのようなアプリには管理者アクセスが必要です、これでよろしいですか?」などのダイアログが表示されます)。

それが不可能な場合、スクリプトが昇格されていないことを少なくとも検出して、正常に失敗する可能性がある方法はありますか?

4

11 に答える 11

131

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 スクリプトを実行可能ファイルに変換した場合 ( py2execx_freeze、などのツールを使用) 、4 番目のパラメーターの代わりに をpyinstaller使用する必要があることに注意してください。sys.argv[1:]sys.argv

ここでの利点のいくつかは次のとおりです。

  • 外部ライブラリは必要ありません。標準ライブラリからのみを使用ctypesします。sys
  • Python 2 と Python 3 の両方で動作します。
  • ファイル リソースを変更したり、マニフェスト ファイルを作成したりする必要はありません。
  • if/else ステートメントの下にコードを追加しない場合、コードが 2 回実行されることはありません。
  • 最後の行で API 呼び出しの戻り値を取得し、失敗した場合にアクションを実行できます (コード <= 32)。可能な戻り値はこちらで確認してください。
  • 6 番目のパラメーターを変更することで、生成されたプロセスの表示方法を変更できます。

基礎となる ShellExecute 呼び出しのドキュメントはこちらです。

于 2017-01-30T07:10:56.903 に答える
72

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)
于 2012-07-31T18:09:35.973 に答える
29

特定のタスクを実行するために、しばらくの間、アプリケーションの特権を上げる方法はないようです。Windowsは、プログラムの開始時に、アプリケーションが特定の特権を必要とするかどうかを知る必要があり、アプリケーションがそれらの特権を必要とするタスクを実行するタイミングを確認するようにユーザーに求めます。これを行うには2つの方法があります。

  1. アプリケーションがいくつかの特権を必要とする可能性があることをWindowsに通知するマニフェストファイルを作成します
  2. 別のプログラム内から昇格された特権でアプリケーションを実行する

この2つの 記事では、これがどのように機能するかをさらに詳しく説明しています。

CreateElevatedProcess APIの厄介なctypesラッパーを作成したくない場合は、Code Projectの記事で説明されているShellExecuteExトリックを使用します(Pywin32にはShellExecuteのラッパーが付属しています)。どのように?このようなもの:

プログラムが起動すると、管理者権限があるかどうかがチェックされます。そうでない場合は、ShellExecuteトリックを使用して実行され、すぐに終了します。実行されている場合は、手元のタスクを実行します。

あなたがあなたのプログラムを「スクリプト」として説明するとき、私はあなたのニーズにはそれで十分だと思います。

乾杯。

于 2008-09-25T02:01:34.263 に答える
4

この質問が何年も前に尋ねられたことを認識して、私はfrmdstryr によって彼のモジュール 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 インターフェイスを利用し、管理者権限が必要なディレクトリにコピーする場合に表示される使い慣れたダイアログ プロンプトで管理者権限が必要であることを自動的に示し、コピー操作中に一般的なファイルの進行状況ダイアログも表示します。

于 2015-08-26T15:03:36.627 に答える
2

どこかにショートカットを作成し、ターゲットとして python yourscript.py を使用してから、プロパティの下で管理者として実行を選択します。

ユーザーがショートカットを実行すると、アプリケーションを昇格するように求められます。

于 2014-04-02T19:56:40.883 に答える
2

これはあなたの質問に完全には答えないかもしれませんが、Elevate Command Powertoy を使用して、昇格された UAC 特権でスクリプトを実行することもできます。

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

あなたがそれを使用すると、「python yourscript.pyを昇格させる」のようになると思います

于 2010-09-24T13:43:33.283 に答える
2

上記の 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
于 2015-12-11T05:34:25.443 に答える
0

スクリプトが常に管理者権限を必要とする場合:

runas /user:Administrator "python your_script.py"
于 2008-09-26T11:54:18.390 に答える