一、subprocess.Popen
Python执行 cmd指令属于外部调用,subprocess.Popen 方法即可,实现如下:
# !/usr/bin/python3
# coding: utf-8
import subprocess
def command(cmd, timeout=1800000):
try:
sp = subprocess.Popen(
cmd,
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
print("[PID] %s: %s" % (sp.pid, cmd))
sp.wait(timeout=timeout)
stderr = str(sp.stderr.read().decode("gbk")).strip()
stdout = str(sp.stdout.read().decode("gbk")).strip()
if "" != stderr:
raise Exception(stderr)
if stdout.find("失败") > -1:
raise Exception(stdout)
except Exception as e:
raise e
参考资料
二、bat 获取管理员权限
但当系统权限不足时,肿么办?
先看传统 bat的处理方式:
@echo off
echo get admin rights
cacls.exe "%SystemDrive%\System Volume Information" >nul 2>nul
if %errorlevel%==0 goto isAdmin
if exist "%temp%\getAdmin.vbs" del /f /q "%temp%\getAdmin.vbs"
echo Set shell = CreateObject^("Shell.Application"^)>"%temp%\getAdmin.vbs"
echo shell.ShellExecute "%~s0","","","runas",1 >>"%temp%\getAdmin.vbs"
echo WScript.Quit >>"%temp%\getAdmin.vbs"
"%temp%\getAdmin.vbs" /f
if exist "%temp%\getAdmin.vbs" del /f /q "%temp%\getAdmin.vbs"
exit
:isAdmin
sc stop WebClient
pause
这段代码的主要流程:
1、调用 cacls.exe 程序查询“系统卷标信息”,验证是否具备管理员权限
2、不具备管理员权限时创建getAdmin.vbs脚本,脚本内容如下
Set shell = CreateObject("Shell.Application")
shell.ShellExecute "%~s0","","","runas",1
WScript.Quit
3、强制执行这个 getAdmin.vbs脚本
4、删除 getAdmin.vbs脚本文件 并退出
那么getAdmin.vbs脚本又做了什么呢?
脚本内容只有三行
① Set shell = CreateObject("Shell.Application") 创建 Shell对象
② 以管理员权限运行当前脚本(bat脚本),其中参数 "%~s0" 是当前脚本的绝对路径,"runas" 是 shell指令 runas,"1"是管理员权限
③ 脚本退出
总体流程就是 bat在权限不足情况下创建了一个 vb脚本,让 vb脚本反向调用bat
三、Python 的曲线救国
想要做一个工具类,可以实现任意 cmd指令的管理员权限下的执行
挖坑式的自造轮子:
① 创建一个空的 bat文件,动态写入cmd指令
② 创建一个固定内容的 vb脚本
③ Python调用 vb脚本, vb 调用 bat
1、文件结构
2、../tool/script/shell.vbs
cwd = CreateObject("Scripting.FileSystemObject").GetFile(Wscript.ScriptFullName).ParentFolder.Path
path = cwd & "\cmd.bat"
Set shell = CreateObject("Shell.Application")
shell.ShellExecute path,"","","runas",1
WScript.Quit
参考资料
3、方法实现
工具方法 runAdmin 实现代码如下:
注意:因 cmd指令是动态写入文件,固 runAdmin 方法不支持并发,调用时要加线程锁
# !/usr/bin/python3
# coding: utf-8
import os
import subprocess
import traceback
def runAdmin(cmd, timeout=1800000):
f = None
try:
bat = os.getcwd() + r"\tool\script\cmd.bat"
f = open(bat, 'w')
f.write(cmd)
except Exception as e:
traceback.print_exc()
raise e
finally:
if f:
f.close()
try:
shell = os.getcwd() + r"\tool\script\shell.vbs"
sp = subprocess.Popen(
shell,
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
print("[PID] %s: %s" % (sp.pid, cmd))
sp.wait(timeout=timeout)
stderr = str(sp.stderr.read().decode("gbk")).strip()
stdout = str(sp.stdout.read().decode("gbk")).strip()
if "" != stderr:
raise Exception(stderr)
if stdout.find("失败") > -1:
raise Exception(stdout)
except Exception as e:
raise e
如有纰漏,敬请@