2017-01-27 14 views
3

私はすべてのアクセス許可を必要とする多数のアプリケーションを実行する方法を困惑させようとしてきました。 DameWare、MSC.exe、PowerShell.exe、SCCM Manager Consoleのようなアプリケーションは、私の日常業務ルーチンで使用されています。Windowsで昇格した権限でスクリプトを実行するにはどうすればよいですか?

私は今Win7を実行しており、最終的にWin10に移行する予定です。毎日私はこれらのプログラムを実行しており、1つ1つずつ実行し、それぞれに名前とパスワードを入力するのは時間がかかります。私はちょうど「退屈なものを自動化する」と思って、Pythonにそれをさせました。

この質問には(How to run python script with elevated privilege on windows)答えがあり、「admin」という古いモジュールのコードが掲載されています。しかし、Python 2+で書かれており、Python 3.5以降ではうまく動作しません。私は私の限らPythonの知識をどうする知ってやったが、私はそれが私はいくつかの研究を行ってきたと私は見つけることができるすべては、Python 2のドキュメントまたは例である

Traceback (most recent call last): 
    File "<pyshell#1>", line 1, in <module> 
    runAsAdmin('cmd.exe') 
    File "I:\Scripting\Python\admin.py", line 41, in runAsAdmin 
    elif type(cmdLine) not in (types.TupleType,types.ListType): 
AttributeError: module 'types' has no attribute 'TupleType' 

を実行しようとしたときにエラーが発生しておきます、 Python 3変換/同等のものはありません。

ここにadmin.pyソースがあります。私はこれをPython 3.5以上に移植することができました。あなたが提供できるすべての助けに感謝します!

#!/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 = input('Press Enter to exit.') 
    return rc 


if __name__ == "__main__": 
    sys.exit(test()) 
+0

あなたが実際にあなたが取得しているエラーを示していません。スタックトレースの興味深い部分。 **完全**スタックトレースを含めてください。 –

+0

完全なスタックトレースを含むようにOPを編集しました。 –

+0

'types.TupleType' _does_は' types'モジュールのPython 2.7.13バージョンに存在するので、エラーは意味を持ちません。この特定の問題のために、 'type(())'またはより読み易い 'type(tuple()) 'を置き換えることができます。 – martineau

答えて

2

試してみてくださいPythonの3に存在しないtypes.TupleTypetypes.ListTypeのように見える代わりに、次の

elif type(cmdLine) not in (tuple, list)

値の誤差を正確にされていないの「cmdLineはシーケンスではない」と言った後、文字列はシーケンスなので正確ですが、実際にはValueErrorを生成する必要があります。私は "cmdLineは空でないタプルまたはリスト、またはNoneでなければなりません"と言い換えることもできます。 cmdLineが文字列以外の繰り返し可能であるかどうかをより広く確認するために更新することができますが、それは過度の可能性があります。

+0

これは、スタックトレースのバグを削除しました!ありがとう!おそらく文字列が別の方法で有効であるかどうかを確認するためにスクリプトを少し修正するでしょう。元の作者がそこで達成しようとしていたことは分かりません。 –

+0

@RyanBarnes著者は 'cmdLine'がタプルまたはリストであることを検証しようとしているだけで、次の行のインデックス操作が期待通りに機能するようにしています。 'cmdLine'が文字列だった場合、それらのインデックス操作は引き続き動作しますが、予期しない結果が発生します。 –

+1

@ Ryan:Python 3で同じことを達成することは、 'elif isinstance(cmdLine、collections.Sequence)であり、isinstance(cmdLine、str)ではないと思います: – martineau

1

次の例は、Windowsで昇格された特権でプログラムを実行する簡単な方法を示しています。列挙は、オペレーティングシステムと対話するときに必要な値を単純化するためのものです。 1つ目は、昇格したプログラムのオープン方法を簡単に指定することができ、2つ目はエラーを簡単に特定する必要がある場合に役立ちます。すべてのコマンドライン引数を新しいプロセスに渡したい場合は、sys.argv[0]をおそらく関数呼び出し:subprocess.list2cmdline(sys.argv)に置き換えてください。

#! /usr/bin/env python3 
import ctypes 
import enum 
import sys 


# Reference: 
# msdn.microsoft.com/en-us/library/windows/desktop/bb762153(v=vs.85).aspx 


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: 
     hinstance = ctypes.windll.shell32.ShellExecuteW(
      None, 'runas', sys.executable, sys.argv[0], None, SW.SHOWNORMAL 
     ) 
     if hinstance <= 32: 
      raise RuntimeError(ERROR(hinstance)) 


def main(): 
    # Your Code Here 
    print(input('Echo: ')) 


if __name__ == '__main__': 
    bootstrap() 
+0

私は受け入れられた答えが問題を解決すると信じていますが、この答えはより広いタイトルの問題を実際に解決するものです。 – code11