COM Error

Jun 3, 2010 at 4:41 PM

Hi,

I am calling your C# Wrapper from a COM and receiving this error

 Unable to cast COM object of type 'VixCOM.VixLibClass' to interface type 'VixCOM.IVixLib'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{94EAA428-2460-470D-8F66-2A4270AFF20A}' failed due to the following error: The application called an interface that was marshalled for a different thread. (Exception from HRESULT: 0x8001010E (RPC_E_WRONG_THREAD))

Looks like the VixCom is created on the Main Thread and when the main thread is launching another thread to execute it this error is thrown. I can get it to work first time, but this occurs when i run the code second time from my GUI.

Looks like I have to set [STAThread] for some methods or set ThreadingModel for vixCom to Apartment.

Coordinator
Jun 3, 2010 at 4:49 PM

This is explained in http://support.microsoft.com/kb/172314. I believe this is a VixCOM limitation (it's apartment-threaded), you should ask the VixCOM forum about a possible work-around. You may want to set your application's main to [STAThread].

Jun 4, 2010 at 5:46 PM

Hi dblock,

We have a GUI which is written in VCL. When you click on Run it creates a new thread inside the running process.

This thread on which my C# Wrapper runs is created by COM and its Apartment is set to STA. Would this cause this issue?

Jun 4, 2010 at 6:25 PM

Hi drlock,

I think i got the handle on what is the issue.  Looks like VMWareTasks is using Multi-Threaded event model, and my application is running as single threaded application. I am seeing a lot of use of Job Wait function which is not allowed for Single Threaded model.

 

Multi-Threaded Event Model

The multi-threaded event model is the default model for Vix clients. Its use is described in detail in the section above called Callback Functions. This model is the easiest to use, if your client code is thread-safe.

Using this model, the Vix library creates worker threads as needed to process asynchronous operations in parallel. Callback functions are invoked on the worker threads under the control of the Vix library.

Single-Threaded Event Model

Using the single-threaded model, all asynchronous processing and all event reporting is deferred until the thread calls Vix_PumpEvents(). Each call to Vix_PumpEvents() does more work on an asynchronous operation. At appropriate times during the operation, control is transferred to the callback routine, if one was specified in the call to the asynchronous function that began the operation.

The single-threaded event model is useful for clients that are not thread safe, or that depend on libraries that are not thread-safe. All processing is done in a single thread. You have to write extra code for a polling loop, but you need not be concerned with synchronizing multiple threads.

Using a Callback Function in a Single-Threaded Client

Single-threaded clients also have the option to use callback functions that handle completion. Because the callback has to share the single thread, it cannot happen asynchronously. As with the polling method of completion described in Polling for Completion in a Single-Threaded Client, the client cannot call VixJob_Wait().

In the single-threaded client, processing takes place only during calls to Vix_PumpEvents(). Each call does more work on the operation. If a callback was specified in the call to the asynchronous function that began the operation, the Vix library invokes the callback function during one of the calls to Vix_PumpEvents().

The code to use this method looks like the following example. The main function initiates a host connection operation (specifying a callback function) and then enters a loop to pump events. When the operation has completed, the callback function returns a handle to the host (or an invalid value in case of failure).

Coordinator
Jun 4, 2010 at 6:40 PM

Yes, it's all wait-based. Sounds like the only way to fix it is to pass VIX_HOSTOPTION_USE_EVENT_PUMP into Connect and replace wait-s by completion checks?

It shouldn't be too hard to do this in the current library as an optional behavior, since all the waits happen in the same code. Maybe you can attempt it and send patches?

 

Jun 4, 2010 at 8:04 PM

Hi dblock,

Can you please give me one simple example of this one in Connect and OpenVM method?

I will take over from that and apply that through out the library.

 

private void Connect(ServiceProviderType serviceProviderType,
            string hostName, int hostPort, string username, string password, int timeout)
        {
            int serviceProvider = (int)serviceProviderType;
            VMWareJobCallback callback = new VMWareJobCallback();
            using (VMWareJob job = new VMWareJob(VMWareInterop.Instance.Connect(
                Constants.VIX_API_VERSION, serviceProvider, hostName, hostPort,
                username, password, 0, null, callback), callback))
            {
                _handle = job.Wait<IHost>(Constants.VIX_PROPERTY_JOB_RESULT_HANDLE, timeout);
            }
            _serviceProviderType = serviceProviderType;
        }

 

  public VMWareVirtualMachine Open(string fileName, int timeoutInSeconds)
        {
            if (_handle == null)
            {
                throw new InvalidOperationException("No connection established");
            }

            VMWareJobCallback callback = new VMWareJobCallback();
            using (VMWareJob job = new VMWareJob(_handle.OpenVM(fileName, callback), callback))
            {
                return new VMWareVirtualMachine(job.Wait<IVM2>(
                    Constants.VIX_PROPERTY_JOB_RESULT_HANDLE,
                    timeoutInSeconds));
            }
        }

Coordinator
Jun 5, 2010 at 6:20 PM

If I wrote a sample, I'd be done :) I'll see if I have time for this, but no promises.

Jun 8, 2010 at 10:39 PM
Edited Jun 8, 2010 at 10:40 PM

Hi dblock,

I have actually found the solution. The root cause is VMWareInterop.Instance, as it is static. As my COM application creates STA Apartment thread when clicked on Run button , that worked for the first thread but when i click on run button second time it threw the bottom error. I think because vixLibrary is created on the first thread and when the second thread tries to call the Connect method it throws the bottom error.

Unable to cast COM object of type 'VixCOM.VixLibClass' to interface type 'VixCOM.IVixLib'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{94EAA428-2460-470D-8F66-2A4270AFF20A}' failed due to the following error: The application called an interface that was marshalled for a different thread. (Exception from HRESULT: 0x8001010E (RPC_E_WRONG_THREAD))

Now I am creating a local instance of VixLibrary and assigning it to VMWareInterop.Instance.

 

Code Change

-------------------

 private void Connect(ServiceProviderType serviceProviderType,
            string hostName, int hostPort, string username, string password, int timeout)
        {
            VixLib lib = new VixLib();
            VMWareTimeouts tOut = new VMWareTimeouts();
            VMWareInterop.Instance = lib;
            VMWareInterop.Timeouts = tOut;
            int serviceProvider = (int)serviceProviderType;
            VMWareJobCallback callback = new VMWareJobCallback();
            using (VMWareJob job = new VMWareJob(VMWareInterop.Instance.Connect(
                Constants.VIX_API_VERSION, serviceProvider, hostName, hostPort,
                username, password, 0, null, callback), callback))
            {
                _handle = job.Wait<IHost>(Constants.VIX_PROPERTY_JOB_RESULT_HANDLE, timeout);
            }
            _serviceProviderType = serviceProviderType;
        }

Coordinator
Jun 8, 2010 at 11:38 PM

Do you think you could create a small repro application, file a bug here and attach a zip with it?

Coordinator
Jun 12, 2010 at 2:05 AM

Ok, I wrote a repro, it was pretty easy. I made changes in the lines of what you have suggested. Give 1.5 beta a try. Let me know if it works.