System.Runtime.InteropServices.InvalidComObjectException in Unit tests

May 12, 2010 at 8:09 AM
Edited May 12, 2010 at 8:11 AM

When I use Vestris.VMWareLib in multiple Unit tests, I always get the follwing exception:

TestClass.TestMethod : Failed

Test method TestClass.TestMethod threw exception:  System.Runtime.InteropServices.InvalidComObjectException: COM object that has been separated from its underlying RCW cannot be used..
at Interop.VixCOM.VixLibClass.Connect(Int32 apiVersionInt32 hostTypeString hostNameInt32 hostPortString userNameString passwordInt32 optionsIVixHandle propertyListICallback jobDoneCallback)
at Vestris.VMWareLib.VMWareVirtualHost.Connect(ServiceProviderType serviceProviderTypeString hostNameInt32 hostPortString usernameString passwordInt32 timeout)
at Vestris.VMWareLib.VMWareVirtualHost.ConnectToVMWareWorkstation()
The exception doesn't occur, when I run a single test (runing them one by one). But when running all tests the exception will be thrown!
The code of TestMethod is:
        public void TestMethod()
            using (var virtualHost = new VMWareVirtualHost())
                using (var virtualMachine = virtualHost.Open(ConfigurationManager.AppSettings["PathToVirtualMachine"]))

                    var shell = new Shell(virtualMachine);
                    virtualMachine.GuestEnvironmentVariables["tmp"] = @"C:\Temp";
                    Shell.ShellOutput output = shell.RunCommandInGuest(String.Format(@"cmd.exe /C ""{0}"" ListApps",



May 12, 2010 at 8:43 AM

I've found a solution. The problem is, that VMWareTask can't be used in multi thread mode. MSTest by default runs tests in multi thread mode. To run in single mode, add <ExecutionThread apartmentState="1" /> to *.testrunconfig.

May 12, 2010 at 12:50 PM

This makes the COM apartment state STA instead of MTA. VixCOM should be able to do both properly, so this means that a COM object is crossing threads (maybe during garbage collection). That might be a bug in your code, VMWareTasks or VixCOM.

I only see one problem - Shell is IDisposable, so it needs a using ( ) around it as well. I would try to strip the inside of the second using (everything from PowerOn and try that first too.