Mono and XPCOM: Scripting VirtualBox

by Miguel de Icaza

A few weeks ago Thomas introduced me to Achim Hasenmueller from Innotek, the makers of VirtualBox, an open source virtual machine system (similar to VMware and VirtualPC).

It turns out that much of the functionality of VirtualBox is exposed through COM interfaces and at least on Unix they use Mozilla's XPCOM as their COM layer.

Achim wanted to use Mono to script and control VirtualBox through its XPCOM interfaces.

The good news is that for the past few months, Jonathan Chambers has been working on adding COM support to Mono. Jonathan has some software that exposes COM interfaces, and wants to be able to control it from Mono, instantiate COM classes from Mono, consume COM interfaces from Mono and export Mono objects to COM applications.

Jonathan's initial goal was to support COM on Windows, but as the recent testing showed, Mono can use Mozilla's XPCOM to script VirtualBox.

Last time I talked to Jonathan he was putting together a tool that can import type libraries from XPCOM and generate the C# stubs that are necessary to get access to all the APIs exposed by XPCOM instead of having to manually bind each interface.

Hopefully Jonathan will post his sample code for folks that might be interested in using COM with Mono on Unix.

Here is a C# sample that he emailed me recently (for VirtualBox):

        static void listVMs(IVirtualBox virtualBox)
	{
	    IMachineCollection collection;
	    IMachineEnumerator enumerator = null;
	    collection = virtualBox.Machines;

	    if (collection == null) return;
	    enumerator = collection.Enumerate();
	    if (enumerator == null) return;

	    while (enumerator.HasMore)
	    {
	    	IMachine machine = enumerator.Next;
            	if (machine != null){
		    IntPtr ptr;
                    string machineName;
                    ptr = machine.Name;
                    machineName = Marshal.PtrToStringUni(ptr);
                    Console.WriteLine ("\tName:        {0}\n", machineName);
		}
	    }	    
	}
	
	static int Main (string[] args)
	{
                int hr = 0;
                nsIServiceManager sm;
                hr = NativeMethods.NS_InitXPCOM2 (out sm, IntPtr.Zero, IntPtr.Zero);
                IntPtr ptr;

                nsIComponentRegistrar cr = (nsIComponentRegistrar)sm;
                Guid kEventQueueServiceCID = new Guid("be761f00-a3b0-11d2-996c-0080c7cb1080");
                sm.getService(kEventQueueServiceCID, typeof(nsIEventQueueService).GUID, out ptr);

                nsIComponentManager cm = (nsIComponentManager)sm;
                string NS_VIRTUALBOX_CONTRACTID = "@virtualbox.org/VirtualBox;1";
                IVirtualBox virtualBox = (IVirtualBox)cm.createInstanceByContractID(
			NS_VIRTUALBOX_CONTRACTID, null, typeof(IVirtualBox).GUID);

                listVMs(virtualBox);

                Marshal.ReleaseComObject (virtualBox);
                
                NativeMethods.NS_ShutdownXPCOM(sm);
                return 0;
        }

	

The code above would also automatically work with any other .NET language (for scripting purposes, IronPython, and one day IronRuby).

COM on Unix

COM does not exist on Unix as a service that applications can depend on. Developers today have a choice between using Mainsoft's COM runtime or embedding a variation of Mozilla's XPCOM in their application.

For example, VirtualBox today bundles a copy of XPCOM in its source code distribution.

Some folks have a lot of code that has been built with COM in mind and this should open the doors for folks to take advantage of it on Unix with Mono.

Posted on 28 Aug 2007