InvalidComObjectException on Disconnect

Mar 11, 2009 at 5:45 AM
Kudos to dblock -- this is a very nice wrapper for the underlying COM.

I am getting some some exceptions when the Finalizer runs (and Disconnect is called). This happens when an exception causes the VMWareVirtualHost to be finalized.
For example, if I give some bad credentials when calling virtualMachine.Login, I get a COM error like this:


System.Runtime.InteropServices.InvalidComObjectException was unhandled
  Message="COM object that has been separated from its underlying RCW cannot be used."
  Source="Interop.VixCOM"
  StackTrace:
       at VixCOM.IHost.Disconnect()
       at Vestris.VMWareLib.VMWareVirtualHost.Disconnect()
       at Vestris.VMWareLib.VMWareVirtualHost.Finalize()
  InnerException:



If I comment out the _handle.Disconnect(); line in VMWareVirtualHost, the COM exception is not thrown, and I get the correct VMWareException instead.

The actual code is just a simple VS2008 MSTest run:


       [TestMethod]
        public void TestRunInGuest()
        {
           VMWareVirtualHost virtualHost = new VMWareVirtualHost();
            // connect to a remove (VMWare ESX) virtual machine
            virtualHost.ConnectToVMWareVIServer("server, username, password);
            // open an existing virtual machine
            VMWareVirtualMachine virtualMachine = virtualHost.Open(vmx);
            virtualMachine.LoginInGuest(guestuser,guestpass);
            // run notepad
            virtualMachine.RunProgramInGuest("notepad.exe", string.Empty);
         }



Any ideas? Do you suppose the cleanup is happening in the wrong order, and the COM object is being released before disconnect can be called?

Mar 11, 2009 at 7:07 AM
An update:

I found that not calling disconnect causes another error, like this one.

So, I've instead commented out the calling of Disconnet in the Finalizer/deconstructor, and call disconnect manually. For example


       [TestMethod]
        public void TestRunInGuest()
        {
           VMWareVirtualHost virtualHost = new VMWareVirtualHost();
           try
           {
               // connect to a remove (VMWare ESX) virtual machine
               virtualHost.ConnectToVMWareVIServer("server, username, password);
               // open an existing virtual machine
               VMWareVirtualMachine virtualMachine = virtualHost.Open(vmx);
               virtualMachine.LoginInGuest(guestuser,guestpass);
               // run notepad
               virtualMachine.RunProgramInGuest("notepad.exe", string.Empty);
           }
           finally
           {
              virtualHost.Disconnect();
           }
         }


This appears to work without either of the errors I've seen previously.
Coordinator
Mar 11, 2009 at 1:58 PM
This is caused by a bug in VixCOM discussed in this post. I really hope someone at VMWare fixes it soon, but they are a big company, so they take their time :)
You have the correct implementation. You can use the fact that virtual host is disposable and avoid a try/finally. Disconnect will be called automatically.

using(VMWareVirtualHost virtualHost = new VMWareVirtualHost())
{
    // connect to a remove (VMWare ESX) virtual machine
    virtualHost.ConnectToVMWareVIServer("server, username, password);
    // open an existing virtual machine
    VMWareVirtualMachine virtualMachine = virtualHost.Open(vmx);
    virtualMachine.LoginInGuest(guestuser,guestpass);
    // run notepad
    virtualMachine.RunProgramInGuest("notepad.exe", string.Empty);
}
Mar 11, 2009 at 11:43 PM
Thanks for your reply.

Good tip with the 'using' - I'll stick with that approach for now.