You first need to install pythonnet and pypsrp
pip install pythonnet pypsrp
Below is the code which uses pythonnet to execute the powershell command and pypsrp to deserialize it into Python object:
import sys
from typing import Any, Dict
import xml.etree.ElementTree as ET
from io import StringIO
from pathlib import Path
import clr
from pypsrp.serializer import Serializer
def find_powershell_dll() -> Path:
"""Find the path to System.Management.Automation.dll file in the Windows.NET directory."""
powershell_dll_path = next(Path(r"C:\Windows\Microsoft.NET").rglob("System.Management.Automation.dll"), None)
if powershell_dll_path is None:
raise FileNotFoundError
return powershell_dll_path
def add_dll_path_to_sys(powershell_dll_path: Path) -> None:
"""Add the parent folder path of the PowerShell DLL to sys.path."""
folder_path = powershell_dll_path.parent
sys.path.append(str(folder_path))
def initialize_powershell_automation() -> None:
"""Initialize PowerShell by adding the required reference and importing the necessary modules."""
clr.AddReference("System.Management.Automation")
def invoke_powershell_command(command: str, **kwargs: Dict[str, Any]) -> list:
"""Invoke a PowerShell command and return the output."""
from System.Management.Automation import PowerShell
ps = PowerShell.Create()
ps.AddCommand(command)
for key, value in kwargs.items():
ps.AddParameter(key, value)
output = ps.Invoke()
ps.Stop()
ps = PowerShell.Create()
ps.AddCommand("Format-List").AddParameter("InputObject", output)
ps.AddCommand("Out-String")
stdout = ps.Invoke()
stdout = stdout.pop().ToString() if stdout else ""
return output, stdout
def serialize_output_to_xml(output: list) -> str:
"""Serialize the PowerShell output to XML format."""
from System.Management.Automation import PSSerializer
serialized_psobject = PSSerializer.Serialize(output, 2)
return serialized_psobject
def parse_xml_data(serialized_data: str) -> list:
"""Parse the serialized XML data and return the deserialized objects."""
serializer = Serializer()
it = ET.iterparse(StringIO(serialized_data))
for _, el in it:
_, _, el.tag = el.tag.rpartition("}")
root = it.root
deserialized_objects = [serializer.deserialize(psobject) for psobject in root.findall("Obj")].pop()
return deserialized_objects
def main() -> None:
# Find the PowerShell DLL
powershell_dll_path = find_powershell_dll()
# Add DLL path to sys.path
add_dll_path_to_sys(powershell_dll_path)
# Initialize PowerShell
initialize_powershell_automation()
# Invoke the PowerShell command
output, stdout = invoke_powershell_command(
"Get-ChildItem", **{"Path": r"HKLM:\Software\Microsoft\Windows\CurrentVersion\\Uninstall"}
)
# Serialize the output to XML
serialized_data = serialize_output_to_xml(output)
# Parse and deserialize the XML data
deserialized_objects = parse_xml_data(serialized_data)
# Print the deserialized objects
print(deserialized_objects)
print(f"Human readable output: {stdout}")
if __name__ == "__main__":
main()