To use the real power of IronPython, it is necessary to interact with the .NET framework.
The first step to allow the usage .NET assemblies in your IronPython code, is to import the clr-module.
This module can then be used to reference .NET assemblies and use the classes and methods contained in those: Listing 2.
After loading the assembly the namespaces that are part of it can be imported like regular Python modules using the import statement.
Listing 2. Referencing assemblies import clr
# Adding a reference to the System assembly clr.AddReference(“System”)
# Let’s see that the assembly is really referenced:
for assembly in clr.References:
print assembly
# [Out] mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
# [Out] System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
# [Out] (more)
A simple example: obtaining information about running processes
Now that the basics are working it is time to use IronPython in conjunction with other parts of the .NET framework.
Apart from moving files, most automation tasks on windows require the use of either WMI or Powershell to obtain required information or perform necessary actions (As long as you do not need to access information about Windows-specific parts, it is actually possible to use IronPython as a replacement for CPython by
utilizing the standard library modules like os, sys and others. With a little attention this will keep your script portable between IronPython and CPython.).
To demonstrate the interaction between IronPython and Powershell (the emerging standard for Windows
administration), the following example will obtain information about currently running processes and output the acquired information to the console. The information is obtained by calling the Powershell Get-Process-cmdlet.
First we need to be able to access Powershell from IronPython: as Powershell runs on the .NET framework we can use it after the following steps:
• add a reference to System.Management.Automation,
• import RunspaceInvoke,
• Invoke() the desired cmdlet on the acquired runspace (Listing 3)
Listing 3. A context manager for accessing Powershell import clr
import contextlib
clr.AddReference(“System.Management.Automation”)
from System.Management.Automation import RunspaceInvoke
@contextlib.contextmanager def powershell():
“””This function is a context-manager for using a powershell process to execute cmdlets.
“””
runspace = RunspaceInvoke() yield runspace
runspace.Dispose()
Listing 4. A snippet to get all currently running processes and output information about them def get_processes_sorted_by(sort_prop):
“””This function returns a collection of currently running processes, sorted according to the passed property.
– `sort_prop`: the property to sort the process list by.
– Returns: a collection of PSObjects wrapping Process objects.
“””
with powershell() as ps:
# Obtain a list of all running processes:
processes = ps.Invoke(“Get-Process”) # sort the list
sorted_processes = sorted(processes, key=lambda p:
getattr(p.BaseObject, sort_prop), reverse=True)
return sorted_processes
processes_sorted_by_working_set = get_processes_sorted_by(“WorkingSet”) except WindowsError:
# Access to the process / property was denied for the # user running this script
pass
#[Out] Name | Memory | CPU
#[Out] ipy | 79433728 | 00:00:07.6810448
#[Out] explorer | 32190464 | 00:00:06.0687264
#[Out] taskmgr | 9347072 | 00:00:07.0501376
#[Out] taskhost | 5664768 | 00:00:00.2002880
#[Out] conhost | 4304896 | 00:00:01.9127504
#[Out] VBoxTray | 3645440 | 00:00:00.0100144
#[Out] dwm | 3162112 | 00:00:00.0300432
When running a cmdlet, it will return PSObjects. These objects are a wrapper around the actual objects that are normally needed and are accessible via the BaseObject property.
Now on to obtaining a list of all running processes and ordering it by used memory per process (just add the code to the same file, you put the Powershell snippet in): Listing 4.
As it’s easy to see IronPython even maps methods like getattr to the equivalent methods on the .NET objects.
However, anyone who has worked with the Get-Process cmdlet has probably realized that the obtained information are somewhat limited and some properties seem to be missing. A prominent example of one such missing property is the CommandLine that started the process: this can be useful if you start multiple scripts and only want to kill one script that you can identify by its commandline arguments.
The following trivial script shall act as an example: as soon as you start it with the sleep commandline argument it will never exit: Listing 5.
Listing 5. A long running process we need to kill import sys
import time
if len(sys.argv) > 1 and sys.argv[1] == “sleep”:
print “Being evil”
while True:
print “Sleeping”
time.sleep(2) else:
print “Being nice: Bye”
To obtain information about the CommandLine it is necessary to use WMI. To query WMI (using Windows Query Language (WQL) you have to reference the System.Management assembly and use either a
ManagementObject or a ManagementObjectSearcher to perform the queries:
• the ManagementObject can only return one management object,
• the ManagementObjectSearcher can return a collection of management objects that can be accessed by calling
Get() on the result of the query (Listing 6).
Listing 6. Using WMI via WQL import clr
clr.AddReference(“System.Management”)
from System.Management import ManagementObjectSearcher query = “SELECT * FROM Win32_Process”
query_result = ManagementObjectSearcher(query) wmi_processes = query_result.Get()
enumerator = wmi_processes.GetEnumerator() if enumerator.MoveNext():
process = enumerator.Current for prop in process.Properties:
print “%s – %s” % (prop.Name, prop.Value) for process in wmi_processes:
if “ipy” in process[“Name”]:
if “sleep” in process[“CommandLine”]:
print “Found evil process: will delete it!”
process.Delete()
As soon as you know the property that you need (using the REPL to find it is a good idea) you can access it via object[“<property>”], instead of iterating and printing all properties. This is shown at the end of the script where we destroy the sleeping script as soon as we find it – and not the ipy process that runs the termination-script (just make sure that you started the sleep-termination-script in another shell).
In conjunction with basic Python modules like os, sys and glob, this should be enough information to get started scripting Windows while using IronPython.