Embedding PowerShell in IronPython and vice versa -- “two great tastes that taste great together”
PowerShell and Python may both be scripting languages, but their strengths are in different areas. One place where PowerShell excels is in getting prettily formatted text output out of your windows system calls, and making a lot of standard queries without having to go to all the hassle that diving into the System.Management namespace often involves (writing your own WQL queries and the like).
So, why not embed the one script inside the other?
import clr
import System.Collections
clr.AddReference("System.Management.Automation")
from System.Management.Automation import *
from System.Management.Automation.Runspaces import *
import System.IO
def RunScript(script):
runspace = RunspaceFactory.CreateRunspace()
runspace.Open()
pipeline = runspace.CreatePipeline()
cache = System.IO.Path.GetTempFileName()
pipeline.Commands.AddScript(script)
## flatten at the PowerShell level from collection
## of PSObjects to the PowerShell displayed form
## if that is all that is required.
pipeline.Commands.Add("Out-String")
results = pipeline.Invoke()
pickled = []
for thing in results:
pickled.append(thing.ToString())
return pickled
if __name__ == '__main__':
pickled = RunScript("Get-Process")
for thing in pickled:
print thing
In the example, we get a single pretty-printed list of all the processes. If we hadn't added the Out-String, we would have a collection of System.Diagnostics.Process objects that we could work with as .Net objects in their own right. And objects can be passed in via runspace.SessionStateProxy.SetVariable("variableName", theObject) and picked up as $variableName in the PowerShell script.
As IronPython can be embedded in .Net, it can of course be embedded in PowerShell, like this (for 1.x)
[reflection.assembly]::LoadFrom("C:\IronPython-1.1\IronPython.dll")
$pythonEngine = New-Object -TypeName "IronPython.Hosting.PythonEngine"
$pythonEngine.Execute("print 'Hello World!'")
The 2.0 code is similar in spirit, but different in detail:
[reflection.assembly]::LoadFrom("C:\IronPython-2.0A7\IronPython.dll")
$pythonEngine = [ironpython.hosting.pythonengine]::CurrentEngine
$pythonEngine.Execute("print 'Hello World!'")
H/t CodeProject




1 comments:
I'd experimented with something like this (check http://metadeveloper.blogspot.com/2007/11/web-shell-prototype-ironpython.html) and had some limited success. I'll see if I can get it to work with the approach you are using. I had a hard time keeping a "context" with the shell versus just a command at a time.
Post a Comment