Search code examples
vb.netinteropcom-interopinfopathinfragistics

Infopath COM object that has been separated from its underlying RCW cannot be used


I've run into an issue that I just cannot seem to find the answer to anywhere on the internet. I have an application that hosts an Infopath.FormControl inside of a Windows Form. Each of the InfoPath forms have 5 views that they have to display, and using Infragistics UI v11.1 controls, we have each of the views on a separate tab in the application.

The application is able to display the first four views that you choose correctly, and it doesn't matter what order you pick them (eg 1,5,4,2 or 1,2,3,4), but after the the fourth one, it will always come up with the error "COM object that has been separated from its underlying RCW cannot be used."

Private Sub utForm_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles utForm.Click

    lastTabClicked = Me.utForm.SelectedTab.Text
    Me.OHeader1.Focus()
    ' If Me.formIsReadOnly Then
    If Me.fcInfoPath Is Nothing Or wasPrinted Then
        If Not Me.utForm.SelectedTab Is Nothing Then
            processReadOnlyTabChange(Me.utForm.SelectedTab.Text)
            Exit Sub
        End If
    End If

    'This is the line of code that will get the exception, but by the time we get
    'here, the COM object has already been released.
    Me.fcInfoPath.XmlForm.CurrentView.ForceUpdate()

    'Failed Ideas to stop the Com object from separating from it's wrapper (RCW)
    'Dim test As IntPtr = Marshal.GetIUnknownForObject(Me.fcInfoPath)
    'Marshal.AddRef(test)
    'GC.SuppressFinalize(Me.fcInfoPath)
    'SyncLock fcInfoPath for duration of event

    If Not Me.utForm.SelectedTab Is Nothing Then
        processTabChange(Me.utForm.SelectedTab.Key)
    End If
End Sub 

I've looked deeper into the code, and it never calls a Marshal.ReleaseComObject or any dispose methods. I also did a GC.SuppressFinalize on the FormControl object, and added a SyncLock around the code that updates the view, in case there was a threading issue. I even manually added hundreds of references to the COM object as a last ditch effort, as the COM object is supposed to be released only after the last reference has been removed. None of these things has had any effect. Always after the fourth view change, it comes up with that error, and following every line of code gets me nowhere. It always loses the COM object sometime between setting the fourth view and hitting the above event. There is no code executing during this time that I know of, so I've become stuck on this issue.

EDIT: I should also add that this is an application being upgraded from .Net 2 to .Net 4, and this worked perfectly before, when it was using InfoPath 2007. Right now, it's using InfoPath 2010 x64 (I did not choose the office version), and I'm thinking it might be possible that the 64-bit version of InfoPath could have some issues that might cause this.

EDIT 2: This is not an issue with the 64-bit version. I switched out my version of Office and recompiled with Office 2010 x86, and I still get the same error as before.


Solution

  • I am not familiar with the COM interface to InfoPath, but in every other COM application that I have used from .Net (Office objects such as Excel, Word, etc...), that error:

    "COM object that has been separated from its underlying RCW cannot be used."

    Always means that the Application Object had exited, usually because it threw an unhandled error in its hosted VBA engine.

    AFAIK, you cannot stop the Application Object from exiting using .Net code/calls. I'd check your code-behind, if you have any.


    Actually looking at your code again:

    If Me.fcInfoPath Is Nothing Or wasPrinted Then
        ...
    End If
    
    'This is the line of code that will get the exception, but by the time we get
    'here, the COM object has already been released.
    Me.fcInfoPath.XmlForm.CurrentView.ForceUpdate()
    
        ...
    

    In all likelihood, the Application was already exited even before you got to the Me.fcInforPath Is Nothing .. test. That's an annoying problem when dealing with the .net/COM wrappers, even when the COM object is long gone, the .Net wrapper object persists, so it passes these "Is Nothing" tests, and then only fails when you actually try to use it.