Running a Powershell Cmdlet in a Python Script

Run powershell Scripts INSIDE python script

I believe the easiest way to achieve what you are trying to do is by using subprocess.Popen. This function can call command-line/terminal commands from within a python script. It can be used like this:

import subprocess
subprocess.Popen()

Where your command is placed between the two brackets.

A Powershell command can be executed from the command line using the command line (see this):

powershell -command ""

Where your command is between the two quotation marks.
Since subprocess.Popen can call a command line command, you can call a powershell command through it. Here's an example using your first ps command:

import subprocess
command='Write-Host("Installing module PSWindowsUpdate if not already installed...")'
subprocess.Popen('powershell -command '+"'"+command+"'")

Alternatively, you can use subprocess.run to execute the command. The only difference it that subprocess.run executes the command and then your script continues, while subprocess.Popen runs the command while your script continues.

If you want the command to do it's thing silently (eg. without opening powershell), pass stdout=subprocess.PIPE, shell=True to subprocess.Popen with your command.
You can print the output directly with something like:

stdout_value = process.communicate()[0]
print (stdout_value)

Where process is your subprocess.Popen() object.
Now onto completing all your commands:

If you want to print the output of your commands, you can use:

import subprocess
def call_command(command):
process=subprocess.Popen('powershell -command '+"'"+command+"'", stdin=subprocess.PIPE,stdout=subprocess.PIPE, shell=True)
stdout_value = process.communicate()[0]
return stdout_value

print(call_command('Write-Host("Installing module PSWindowsUpdate if not already installed... ")'))

Simply use call_command for each command and you're done. You will see some extra characters in the output (eg. \n or \r), these are included by default for powershell to actually create a newline, etc. Basically, if you don't want them, you can remove them yourself (eg. string.replace('\n', ''))

If you want to actually open powershell, calling subprocess.Popen for each line will open one powershell terminal per line, which I don't think you'd want. I would take some more trickery to call all the commands in one powershell terminal:

One thing you could do is put your powershell commands in a file with the .ps1 file extension.you can then call it with subprocess.Popen and run it altogether in a powershell terminal.
For example:

import subprocess
subprocess.Popen("C://path/to/your/file/myfile.ps1")

But you'd have to have another file, not just your python script.

Or:

your could combine all your commands into one:

commands = """ Write-Host("Installing module PSWindowsUpdate if not already installed... ")
Install-Module PSWindowsUpdate
Write-Host("PSWindowsUpdate is now installed.")
Write-Host("")
Write-Host("Getting Windows Updates...")
Import-Module PSWindowsUpdate
$updates = Invoke-Command -ScriptBlock {Get-Wulist -verbose}
$updatenumber = ($updates.kb).count
if ($null -ne $updates){
Get-WindowsUpdate -AcceptAll -Install | Out-File C:\PSWindowsUpdate.log
do {$updatestatus = Get-Content c:\PSWindowsUpdate.log
"Currently processing the following update:"
Get-Content c:\PSWindowsUpdate.log | select-object -last 1
Start-Sleep -Seconds 10
$ErrorActionPreference = 'SilentlyContinue'
$installednumber = ([regex]::Matches($updatestatus, "Installed" )).count
$ErrorActionPreference = ‘Continue’
}until ( $installednumber -eq $updatenumber)
}
Remove-Item -path C:\PSWindowsUpdate.log"""

Then run it with subprocess:

import subprocess;
subprocess.Popen(["powershell","& {" + command+ "}"])
# or subprocess.Popen('powershell -command' + command)

To print it in the terminal instead of opening powershell, use:

import subprocess;
subprocess.Popen(["powershell","& {" + command+ "}"], stdin=subprocess.PIPE,stdout=subprocess.PIPE, shell=True)
stdout_value = process.communicate()[0]
return stdout_value

That should be it!

How to run a Powershell script in python

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

Running powershell script within python script, how to make python print the powershell output while it is running

  1. Make sure you can run powershell scripts (it is disabled by default). Likely you have already done this. http://technet.microsoft.com/en-us/library/ee176949.aspx

    Set-ExecutionPolicy RemoteSigned
  2. Run this python script on your powershell script helloworld.py:

    # -*- coding: iso-8859-1 -*-
    import subprocess, sys

    p = subprocess.Popen(["powershell.exe",
    "C:\\Users\\USER\\Desktop\\helloworld.ps1"],
    stdout=sys.stdout)
    p.communicate()

This code is based on python3.4 (or any 3.x series interpreter), though it should work on python2.x series as well.

C:\Users\MacEwin\Desktop>python helloworld.py
Hello World

How to run a PowerShell cmdlet in Python to get a list of connected USB devices?

There is a module called pyUSB that works really well.

Alternatively, to run Powershell commands, you can use the subprocess package.

import subprocess
result = subprocess.run(["powershell", "-Command", MyCommand], capture_output=True)

Running a python script via Powershell script

Assuming that python is already in your path variables you can just call a python script like this:

python C:\User\PythonScripts\TestFile.py


Related Topics



Leave a reply



Submit