简体   繁体   English

Python - 在子进程中运行 powershell 命令

[英]Python - Running powershell commands in a subprocess

I am trying to create a program to semi-automate the exporting of VMs from HyperV which requires the use of Get-VM and Export-VM if I want to choose specific VMs to export (which I do), but my current struggle right now is to get these PowerShell commands to run from my python script.我正在尝试创建一个程序来半自动化从 HyperV 导出 VM,如果我想选择要导出的特定 VM(我会这样做),这需要使用Get-VMExport-VM ,但我目前的挣扎是让这些 PowerShell 命令从我的 python 脚本中运行。 As you can see from my code below I've done a lot of tinkering trying to get it to work...正如您从下面的代码中看到的那样,我已经做了很多修改以使其正常工作......

How do I get the code to run Get-VM , which needs to be run with elevated permissions, and have the output be printed into the python console?如何获取运行Get-VM的代码,该代码需要以提升的权限运行,并将输出打印到 python 控制台中? (I have no need nor particularly want for a PowerShell terminal to open but if it does I don't care, as long as the output also gets put into the python output stream.) (我不需要也特别希望打开 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)

Currently, it outputs...目前,它输出...

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

So as far as I can tell what I wanted to do is kinda a pain and hasn't really been done before so what I did was make a solution (Go Figure).因此,据我所知,我想做的事情有点痛苦,而且以前还没有真正做过,所以我所做的就是提出一个解决方案(见图)。 What I did was create the following script which I plan to use for VM stuff but right now all it does is use the subprocess library to send a cmd command which launches PowerShell with the start-process command starting up another PowerShell as administrator using -Verb runas then it passes in the argument to start minimized, the command you wanna run and a place to put the output which is what we use to get it back into python.我所做的是创建以下脚本,我计划将其用于 VM 内容,但现在它所做的只是使用 subprocess 库发送一个 cmd 命令,该命令使用 start-process 命令启动 PowerShell,使用 -Verb 以管理员身份启动另一个 PowerShell runas 然后它传入参数以开始最小化,你想要运行的命令和一个放置输出的地方,这是我们用来把它放回 python 的地方。

import subprocess, sys, boto3, os, progressbar, time
from botocore.exceptions import ClientError
cwd = os.getcwd()
tmpPSconsole = cwd + "\cPStmp.txt"

def clearConsole(console):
    validateConsoleExists(console)
    temp = []
    temp.clear()
    File = open(console, "w")
    File.writelines(temp)
    File.close()

def validateConsoleExists(console):
    try:
        File = open(console, "x")
        File.close()
    except:
        print("")
        #file exists

def removeTempConsole(console):
    validateConsoleExists(console)
    os.remove(console)

def isEmptyConsole(console):
    validateConsoleExists(console)
    file = open(console, "r")
    data = file.read()
    output = len(data) < 2
    file.close()
    return output

def printConsole(console):
    validateConsoleExists(console)
    file = open(console, "r")
    data = file.read()
    print(data)

def runElevatedPS(command):
    global tmpPSconsole, cwd
    validateConsoleExists(tmpPSconsole)
    clearConsole(tmpPSconsole)
    cmdCommand = "powershell.exe start-process powershell -Verb runas -ArgumentList '-WindowSTyle Minimized -c " + command + " >\"" + tmpPSconsole + "\"'"
    print(cwd + "> ")
    print(cwd + "> " + cmdCommand)
    subprocess.Popen(cmdCommand)
    count = 0
    maxNum=100
    with progressbar.ProgressBar(max_value=maxNum) as bar:
        while(isEmptyConsole(tmpPSconsole)):
            time.sleep(5)
            if(count < 99):
                bar.update(count)
                count += 1
        time.sleep(2)
        count = maxNum - count
        bar.update(count)
    printConsole(tmpPSconsole)

if __name__ == '__main__':
    running_command = "Get-VM"
    runElevatedPS(running_command)
    removeTempConsole(tmpPSconsole)
    end = str(input("Press any key to exit the Program"))

I believe that in my python program's current state the import of boto3 is completely unused and I can't remember if sys was used either but in any case the others definitely do get used.我相信在我的 python 程序的当前状态下,boto3 的导入完全未使用,我不记得是否使用了 sys 但无论如何其他人肯定会使用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM