using System; using System.Reflection; using System.Runtime.InteropServices; using System.Windows.Forms; using System.Threading; using VirtualBox; namespace ConsoleApplication1 { class ProgramRun { public static VBoxXPCOM VBoxXPCOM { get; private set; } Object WaitingForProgress = null; public int Run(string[] args) { IVirtualBox vb; ISession sess; if (Environment.OSVersion.Platform == PlatformID.Unix) { VBoxXPCOM = new VBoxXPCOM(); vb = VBoxXPCOM.VirtualBox; sess = VBoxXPCOM.Session; } else { VBoxCOMInit(out vb, out sess); } Console.WriteLine("VirtualBox version={0} revision={1}", vb.Version, vb.Revision); Console.WriteLine("VirtualBox HomeFolder={0}", vb.HomeFolder); if (args.Length < 1) { Console.Error.WriteLine("Usage: {0} machine-name-or-id", Assembly.GetExecutingAssembly().Location); return 1; } IMachine m; m = vb.FindMachine(args[0]); Console.WriteLine("Lock machine"); m.LockMachine((Session)sess, LockType.LockType_Write); try { Framebuffer fb = new Framebuffer(); sess.Console.Display.SetFramebuffer(0, fb); Console.WriteLine("Start GUI thread"); Display disp = new Display(sess.Console, fb); Console.WriteLine("Power up..."); //MonitorAndProcessEventsUntilCompleted(sess.Console.PowerUpPaused()); try { disp.MonitorUntilCompleted(sess.Console.PowerUpPaused()); //Console.WriteLine("Resume"); //sess.Console.Resume(); Application.Run(disp); } finally { if (VBoxXPCOM != null) VBoxXPCOM.EventQueue.ProcessPendingEvents(); switch (sess.Console.State) { case MachineState.MachineState_PoweredOff: case MachineState.MachineState_Saved: case MachineState.MachineState_Aborted: break; default: Console.WriteLine("Power down"); WaitingForProgress = null; ThreadPool.QueueUserWorkItem(delegate(Object state) { Console.WriteLine("Requesting SaveState"); IProgress p = sess.Console.SaveState(); Console.WriteLine("Waiting for SaveState completion"); WaitingForProgress = p; VBoxWaitComplete(p); }); ProcessEventsUntilCompleted(); break; } } } finally { Console.WriteLine("Unlock machine"); sess.UnlockMachine(); if (VBoxXPCOM != null) VBoxXPCOM.EventQueue.ProcessPendingEvents(); } return 0; } void VBoxCOMInit(out IVirtualBox vb, out ISession sess) { //vb = (IVirtualBox)Activator.CreateInstance(Type.GetTypeFromProgID("VirtualBox.VirtualBox")); //vb = (IVirtualBox)Activator.CreateInstance(typeof(VirtualBoxClass)); //vb = (IVirtualBox)Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid("B1A7A4F2-47B9-4A1E-82B2-07CCD5323C3F"))); vb = new VirtualBox.VirtualBoxClass(); sess = new VirtualBox.SessionClass(); } public void VBoxWaitComplete(IProgress p) { uint prev = 0; while (p.Completed == 0) { if (p.Percent != prev) Console.Write("{0}% ", p.Percent); prev = p.Percent; p.WaitForCompletion(100); } if (p.ResultCode == 0) { Console.WriteLine("done"); } else { Console.WriteLine("Error {0} {1}", p.ErrorInfo.ResultCode, p.ErrorInfo.Text); throw new COMException(p.ErrorInfo.Text, p.ErrorInfo.ResultCode); } } public void MonitorAndProcessEventsUntilCompleted(IProgress p) { MonitorProgressAsync(p); ProcessEventsUntilCompleted(p); } public void MonitorProgressAsync(IProgress p) { ThreadPool.QueueUserWorkItem(delegate(Object state) { try { VBoxWaitComplete(p); } catch (Exception ex) { Console.WriteLine(ex.ToString()); } }); } public void ProcessEventsUntilCompleted(IProgress p) { do { if (VBoxXPCOM != null) VBoxXPCOM.EventQueue.ProcessPendingEvents(); Thread.Sleep(100); } while (p.Canceled == 0 && p.Completed == 0); Console.WriteLine("Event processing completed"); } public void ProcessEventsUntilCompleted() { Console.WriteLine("Processing COM events..."); do { if (VBoxXPCOM != null) VBoxXPCOM.EventQueue.ProcessPendingEvents(); Thread.Sleep(100); } while (WaitingForProgress == null || ((WaitingForProgress as IProgress).Canceled == 0 && (WaitingForProgress as IProgress).Completed == 0)); Console.WriteLine("COM Event processing completed"); } } }