简体   繁体   中英

Passing variables between Powershell commands in a python script

I have to invoke two powershell commands via a python script. I am currently using subprocess.Popen for this.

The first command returns a powershell object. Example:

PS>$temp = <powershell_command_1>

The $temp object has multiple properties in it. The entire object has to be passed to a second powershell object in the same script. eg.

PS><powershell_command_2> -object $temp

If $temp were to be a string, I have no problems with passing the python string variable. However, in this case $temp is an object. How can I pass this value to the second PS cmdlet?

Here is the traceback

Traceback (most recent call last):
  File "file.py", line 430, in <module>
    status = c1.configure_cluster()
  File "file.py", line 319, in configure_cluster
    configure_cluster = subprocess.Popen([self.powershell_binary,'-ExecutionPolicy','ByPass',r'Cmdlet2', temp], stdout=subprocess.PIPE)
  File "C:\Python34\lib\subprocess.py", line 858, in __init__
    restore_signals, start_new_session)
  File "C:\Python34\lib\subprocess.py", line 1085, in _execute_child
    args = list2cmdline(args)
  File "C:\Python34\lib\subprocess.py", line 663, in list2cmdline
    needquote = (" " in arg) or ("\t" in arg) or not arg
TypeError: Type str doesn't support the buffer API

If the two commands can be run together then just run them together, but as you say you have to run them separately you could try using Export-Clixml to save the object to a file then Import-Clixml to reload it. Here's a working example:

#!/usr/bin/env python3
import base64, subprocess, sys

def powershell(cmd, input=None):
    cmd64 = base64.encodebytes(cmd.encode('utf-16-le')).decode('ascii').strip()
    stdin = None if input is None else subprocess.PIPE
    process = subprocess.Popen(["powershell.exe", "-NonInteractive", "-EncodedCommand", cmd64], stdin=stdin, stdout=subprocess.PIPE)
    if input is not None:
        input = input.encode(sys.stdout.encoding)
    output, stderr = process.communicate(input)
    output = output.decode(sys.stdout.encoding).replace('\r\n', '\n')
    return output

command=r"""
$data = Get-ChildItem C:\Python34
$data | Export-Clixml -Path c:\temp\state.xml
$data
"""
output = powershell(command)
print(output)
print("Do some processing here...")
result = """NEWS.txt=1
README.txt=1
\u00a3.txt=1
"""
command = r"""
$in = $input|Out-String
$selected = $in | ConvertFrom-StringData
$data = Import-Clixml -Path c:\\temp\\state.xml
$data |? { $selected.ContainsKey($_.Name) } | Select Length,FullName
"""
output = powershell(command, result)
print(output)

Which gives the following output:

C:\Temp>py state.py


    Directory: C:\Python34


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
d----        24/10/2014     11:52            DLLs
d----        24/10/2014     11:52            Doc
d----        24/10/2014     11:52            include
d----        24/10/2014     11:52            Lib
d----        24/10/2014     11:52            libs
d----        05/11/2014     16:53            Scripts
d----        24/10/2014     11:52            tcl
d----        24/10/2014     11:52            Tools
-a---        06/10/2014     22:19      31073 LICENSE.txt
-a---        21/09/2014     21:03     367504 NEWS.txt
-a---        06/10/2014     22:15      27136 python.exe
-a---        06/10/2014     22:15      27648 pythonw.exe
-a---        06/10/2014     22:10       6942 README.txt
-a---        19/11/2014     11:59          5 £.txt



Do some processing here...

                                 Length FullName
                                 ------ --------
                                 367504 C:\Python34\NEWS.txt
                                   6942 C:\Python34\README.txt
                                      5 C:\Python34\£.txt

You could of course load the XML into Python and manipulate it, in which case use ConvertTo-Xml -as string rather than Export-CliXml though I'm not quite sure how you get that converted back to Powershell objects rather than an xml object. (Edit: Powershell's import-clixml from string covers round-tripping objects through Clixml without using a file).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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