如何在Python子进程中以管理员权限运行PowerShell的Get-VM并获取输出
在Python中运行需管理员权限的PowerShell
Get-VM命令并获取输出 问题背景
正尝试开发一个半自动化导出Hyper-V虚拟机的程序,指定特定虚拟机导出需要用到Get-VM和Export-VM命令,但目前卡在如何在Python脚本中运行这些PowerShell命令。需要实现:运行需管理员权限的Get-VM命令,并将输出打印到Python控制台(不强制要求不打开PowerShell终端,只要输出能同步到Python输出流即可)。
尝试的代码
import subprocess, sys, boto3, os from botocore.exceptions import ClientError cwd = os.getcwd() tmp = cwd + "\commandOut.txt" ##def run(cmd): ## global cwd, tmp ## cmd = 'powershell Get-VM -ArgumentList "/c "' + tmp +'" -Verb "runAs"' ## #subprocess.check_output(cmd, shell=True) ## subprocess.check_output('powershell Get-VM -ArgumentList "/c ".\commandOut.tmp" -Verb "runAs"', shell=True) ## with open('%TEMP%.\donetstat.tmp', 'x') as f: ## f.write(p.communicate()) ## ## ##if __name__ == '__main__': ## #hello_command = "Get-VM" ## #run(hello_command) ## #with open(tmp, 'w+') as f: ## #for line in f: ## #print(line.strip()) ## if hello_info.returncode != 0: ## print("An error occured: %s", hello_info.stderr) ## else: ## print(">", hello_info.stdout) ##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) stream = subprocess.Popen("Start-Process powershell -Verb runas -ArgumentList \"-NoExit -c Get-VM \"") output = stream.communicate() print(output)
遇到的错误
Traceback (most recent call last): File "C:\Users\user\Desktop\VM-MigrationProgram\VM-MigrationTool.py", line 38, in <module> stream = subprocess.Popen("Start-Process powershell -Verb runas -ArgumentList \"-NoExit -c Get-VM \"") File "C:\Users\user\AppData\Local\Programs\Python\Python310\lib\subprocess.py", line 966, in __init__ self._execute_child(args, executable, preexec_fn, close_fds, File "C:\Users\user\AppData\Local\Programs\Python\Python310\lib\subprocess.py", line 1435, in _execute_child hp, ht, pid, tid = _winapi.CreateProcess(executable, args, FileNotFoundError: [WinError 2] The system cannot find the file specified
解决方案
问题根源
当前代码错误是因为subprocess.Popen默认将整个字符串当作可执行文件路径,而非命令行命令。另外Start-Process会新开进程,无法直接捕获输出,需要调整执行逻辑。
方案1:让Python脚本以管理员权限运行后执行命令
先判断脚本是否有管理员权限,无权限则重启获取,之后直接调用Get-VM并捕获输出:
import subprocess import sys import ctypes import os def is_admin(): try: return ctypes.windll.shell32.IsUserAnAdmin() except: return False def run_powershell_command(cmd): # 调用PowerShell执行命令并捕获输出 result = subprocess.run( ["powershell", "-Command", cmd], capture_output=True, text=True, check=False ) if result.returncode != 0: print(f"命令执行出错: {result.stderr}") else: print(result.stdout) if __name__ == "__main__": if not is_admin(): # 以管理员权限重启脚本 ctypes.windll.shell32.ShellExecuteW( None, "runas", sys.executable, " ".join(sys.argv), None, 1 ) sys.exit() # 执行Get-VM命令 run_powershell_command("Get-VM")
方案2:通过临时文件获取管理员权限命令的输出
若不想让整个脚本以管理员权限运行,可通过Start-Process重定向输出到临时文件,再读取文件内容:
import subprocess import os import tempfile def run_admin_powershell(cmd): # 创建临时文件存储输出 with tempfile.NamedTemporaryFile(mode='r', delete=False, suffix='.txt') as tmp_file: tmp_path = tmp_file.name # 构造命令:以管理员身份执行并将输出写入临时文件 ps_cmd = f'Start-Process powershell -Verb RunAs -ArgumentList "-Command {cmd} | Out-File -FilePath \'{tmp_path}\' -Encoding utf8" -Wait' subprocess.run(["powershell", "-Command", ps_cmd], shell=True) # 读取并打印输出 with open(tmp_path, 'r', encoding='utf8') as f: print(f.read()) # 删除临时文件 os.unlink(tmp_path) if __name__ == "__main__": run_admin_powershell("Get-VM")
说明
- 方案1更直接,脚本以管理员权限运行后可直接捕获输出,无需依赖临时文件,体验更好。
- 方案2适用于仅需部分命令获取管理员权限的场景,但需要通过临时文件传递输出,且会弹出UAC权限确认窗口。
内容的提问来源于stack exchange,提问作者PlatPlayZ
相关产品推荐
相关产品推荐

