1

So my question is how do I run a PowerShell script in python, with passable variables from python, then have the python run the PowerShell script, and then from there have specific variables from the PowerShell script pass to the python script.

What I have already is each code working separately. As you can see I am passing in hidden variables from a .ini file and from there I am trying to pass the compList to Powershell.

I am not confident that I am running the command right to call PowerShell and pass the args in my python script

preferences = configparser.ConfigParser()
preferences.read('config.ini')

hostName = preferences.get('Directory', 'hostName')
port = preferences.get('Directory', 'port')
serviceName = preferences.get('Directory', 'serviceName')
usr = preferences.get('Credentials', 'userName')
pswrd = preferences.get('Credentials', 'password')
compList = preferences.get('ComputerList', 'compList')
compList = list(compList.split(","))

p = subprocess.Popen(["powershell.exe", r"C:\Users\pecorgx\TestPS1.ps1", 'arg1 @("compList")'], stdout=sys.stdout)
p.communicate()

My PowerShell Script:

$ArrComputers =  $arg1


Clear-Host
foreach ($Computer in $ArrComputers) 
{
    $computerSystem = get-wmiobject Win32_ComputerSystem -Computer $Computer
    $computerBIOS = get-wmiobject Win32_BIOS -Computer $Computer
    $computerOS = get-wmiobject Win32_OperatingSystem -Computer $Computer
    $computerCPU = get-wmiobject Win32_Processor -Computer $Computer
    $hdds = Get-WmiObject Win32_LogicalDisk -ComputerName $Computer -Filter drivetype=3
        write-host "System Information for: " $computerSystem.Name -BackgroundColor DarkCyan
        "-------------------------------------------------------"
        "Manufacturer: " + $computerSystem.Manufacturer
        "Model: " + $computerSystem.Model
        "Serial Number: " + $computerBIOS.SerialNumber
        "CPU: " + $computerCPU.Name
        foreach ($computerhdd in $hdds) { "HDD Drive Letter: " + $computerhdd.DeviceID + "HDD Capacity:" + "{0:N2}" -f ($computerHDD.Size/1GB) + "GB" + " HDD Space: " + "{0:P2}" -f ($computerHDD.FreeSpace/$computerHDD.Size) }
        "RAM: " + "{0:N2}" -f ($computerSystem.TotalPhysicalMemory/1GB) + "GB"
        "Operating System: " + $computerOS.caption + ", Service Pack: " + $computerOS.ServicePackMajorVersion
        "User logged In: " + $computerSystem.UserName
        "Last Reboot: " + $computerOS.ConvertToDateTime($computerOS.LastBootUpTime)
        ""
        "-------------------------------------------------------"
}

I think I am passing this correctly but I want the Powershell to pass back to my python script

$computerSystem.TotalPhysicalMemory/1GB
$computerSystem.Manufacturer
$computerSystem.Model
$computerBIOS.SerialNumber
$computerCPU.Name

and I want this var $computerHDD.Size/1GB to be passed into a list to be also passed to my python script

EDIT: I decided to just use .txt to pass commands. I made $myOBJ = "" | Select "computer" then made $myOBJ.computer = [string](....) with (...) being things I want to pass back out after the script has ran Would love to know a solution to use without having a third party help

5
  • If you have the powershell script print out json, you should be able to deserialize that in python pretty easily Commented Apr 13, 2021 at 21:25
  • And by "print out" I mean to std out, not a file. Commented Apr 13, 2021 at 21:26
  • This looks relevant: stackoverflow.com/questions/4537259/… Commented Apr 13, 2021 at 21:29
  • Why do you have this random r in this command --- subprocess.Popen(["powershell.exe", r"C:\Users\pecorgx\TestPS1.ps1" In your ps1, you are not showing what is in $arg1, anywhere, so, $ArrComputers = $arg1, would be empty. It would be more prudent to set up the info you are after as a hashtable to pscustomobject and return that. Also, why not just use the built-in Get-ComputerInfo cmdlet directly to get this info vs all these calls? Commented Apr 14, 2021 at 1:18
  • r for raw string Commented Apr 14, 2021 at 16:16

1 Answer 1

2

Here is simplified example of your use case:

import subprocess;
process=subprocess.Popen(["powershell","Get-Childitem C:\\Windows\\*.log"],stdout=subprocess.PIPE);
result=process.communicate()[0]
print (result)

Of course the above is just printing out a directory list, but you just replace that command with your .ps1 script path.

Also, as noted in my comment, why not just use the ...

# Get specifics for a module, cmdlet, or function
(Get-Command -Name Get-ComputerInfo).Parameters
(Get-Command -Name Get-ComputerInfo).Parameters.Keys
Get-help -Name Get-ComputerInfo -Examples
Get-Help -Name Get-ComputerInfo -Detailed
Get-help -Name Get-ComputerInfo -Full
Get-help -Name Get-ComputerInfo -Online

Get-ComputerInfo -Property '*'

... cmdlet, to collect this info and select the properties you want? Only running the other collectors for info that Get-ComputerInfo does not provide.

There is also the built-in ...

Get-PhysicalDisk
Get-Volume

... cmdlets to get storage information.

How about constructing your output details this way...

Clear-Host
$env:COMPUTERNAME | 
ForEach-Object{
    $computerSystem = Get-wmiobject Win32_ComputerSystem -ComputerName $PSItem
    $computerBIOS   = Get-wmiobject Win32_BIOS -ComputerName $PSItem
    $computerOS     = Get-wmiobject Win32_OperatingSystem -ComputerName $PSItem
    $computerCPU    = Get-wmiobject Win32_Processor -ComputerName $PSItem


    (
        $ComputerInfo = [PSCustomObject]@{
                            Manufacturer    = $computerSystem.Manufacturer
                            Model           = $computerSystem.Model
                            SerialNumber    = $computerBIOS.SerialNumber
                            CPU             = $computerCPU.Name 
                            RAM             = [math]::Round($($computerSystem.TotalPhysicalMemory/1GB), 3)
                            OperatingSystem = "$($computerOS.caption), Service Pack: $($computerOS.ServicePackMajorVersion)"
                            LoggedOnUser    = $env:USERNAME  
                            LastReboot      = $computerOS.ConvertToDateTime($computerOS.LastBootUpTime) 
                        }
    )

    (
        $StorageInfo = [PSCustomObject]@{
                            DeviceID      = (Get-Volume).DriveLetter
                            Size          = Get-Volume | ForEach {[math]::Round($($PSitem.Size/1GB), 3)}
                            SizeRemaining = Get-Volume | ForEach {[math]::Round($($PSitem.SizeRemaining/1GB), 3)}
                        }
    )
}

... or combine and ouput this way

Clear-Host
$env:COMPUTERNAME | 
ForEach-Object{
    $ComputerSystem  = Get-wmiobject Win32_ComputerSystem -ComputerName $PSItem | 
                       Select-Object -Property Manufacturer, Model, UserName

    $ComputerBIOS    = Get-wmiobject Win32_BIOS -ComputerName $PSItem| 
                       Select-Object -Property SerialNumber

    $ComputerOS      = Get-wmiobject Win32_OperatingSystem -ComputerName $PSItem  | 
                       Select-Object -Property Caption, ServicePackMajorVersion, 
                       @{
                            Name       = 'LastReboot'
                            Expression = {$PSItem.ConvertToDateTime($PSItem.LastBootUpTime)}
                       }

    $ComputerCPU     = Get-wmiobject Win32_Processor -ComputerName $PSItem | 
                       Select-Object -Property Name

    $ComputerStorage = Get-WmiObject Win32_LogicalDisk -ComputerName $PSItem -Filter drivetype=3 | 
                       Select-Object -Property DeviceID, 
                       @{
                           Name        = 'Size'
                           Expression = {[math]::Round($($PSitem.Size/1GB), 3)}
                       }, 
                       @{
                           Name        = 'FreeSpace'
                           Expression = {[math]::Round($($PSitem.FreeSpace/1GB), 3)}
                       }


    $ComputerDetails = New-Object -Type PSObject

    $ComputerSystem, $ComputerBIOS, $ComputerOS, $ComputerCPU, $ComputerStorage | 
    ForEach-Object {
        $CurObj = $PSItem 
        $PSItem | 
        Get-Member | 
        Where-Object {$PSItem.MemberType -match 'NoteProperty'} | 
        ForEach-Object {
            $NewMember = $PSItem.Name
            $ComputerDetails | 
            Add-Member -MemberType NoteProperty -Name $NewMember -Value $CurObj.$NewMember
        }
    }
}
$ComputerDetails
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.