Solid Edge ST7 SDK
Handling 'Application is Busy' and 'Call was Rejected By Callee' errors

If you automate Solid Edge from an external (out-of-proc) application, you may receive one of the following errors:

These errors occur due to threading contention issues between automation clients and Solid Edge. They can be handled by implementing the OleMessageFilter error handlers in your automation application. Once you have the code in place, simply call OleMessageFilter.Register() before you make any calls to COM clients and OleMessageFilter.Revoke() at the end of your program.

In order for OleMessageFilter to work, you must ensure that Thread.GetApartmentState method returns STA. In Windows Forms applications, this is the default. In Console applications, it is not the default. You will need to specify the STAThreadAttribute on your Main() function.
OleMessageFilter for Visual Basic .NET

In Console applications, you must decorate your Sub Main() function with STAThreadAttribute.

VB.NET example usage
Copy Code
<STAThread()> _
Sub Main()
  OleMessageFilter.Register()
  ' Make COM calls.
  OleMessageFilter.Revoke()
End Sub

In your Visual Basic .NET project, create a new class and name it OleMessageFilter.vb. Copy this example code and paste it into the new class.

VB.NET implementation of OleMessageFilter
Copy Code
Imports System.Runtime.InteropServices
Imports System.Threading

Public Class OleMessageFilter
    Implements IOleMessageFilter

    Public Shared Sub Register()
        Dim newFilter As IOleMessageFilter = New OleMessageFilter()
        Dim oldFilter As IOleMessageFilter = Nothing
        Dim iRetVal As Integer

        If (Thread.CurrentThread.GetApartmentState() = ApartmentState.STA) Then
            iRetVal = CoRegisterMessageFilter(newFilter, oldFilter)
        Else
            Throw New COMException("Unable to register message filter because the current thread apartment state is not STA.")
        End If

    End Sub

    Public Shared Sub Revoke()
        Dim oldFilter As IOleMessageFilter = Nothing
        CoRegisterMessageFilter(Nothing, oldFilter)
    End Sub

    Private Function HandleInComingCall(ByVal dwCallType As Integer, _
                                        ByVal hTaskCaller As System.IntPtr, _
                                        ByVal dwTickCount As Integer, _
                                        ByVal lpInterfaceInfo As System.IntPtr) _
                                        As Integer Implements IOleMessageFilter.HandleInComingCall

        Return SERVERCALL.SERVERCALL_ISHANDLED
    End Function

    Private Function RetryRejectedCall(ByVal hTaskCallee As System.IntPtr, _
                                       ByVal dwTickCount As Integer, _
                                       ByVal dwRejectType As Integer) _
                                       As Integer Implements IOleMessageFilter.RetryRejectedCall

        If dwRejectType = SERVERCALL.SERVERCALL_RETRYLATER Then
            Return 99
        End If

        Return -1
    End Function

    Private Function MessagePending(ByVal hTaskCallee As System.IntPtr, _
                                    ByVal dwTickCount As Integer, _
                                    ByVal dwPendingType As Integer) _
                                    As Integer Implements IOleMessageFilter.MessagePending

        Return PENDINGMSG.PENDINGMSG_WAITDEFPROCESS
    End Function

    <DllImport("Ole32.dll")> _
    Private Shared Function CoRegisterMessageFilter(ByVal newFilter As IOleMessageFilter, _
                                                    ByRef oldFilter As IOleMessageFilter) _
                                                    As Integer
    End Function
End Class

Enum SERVERCALL
    SERVERCALL_ISHANDLED = 0
    SERVERCALL_REJECTED = 1
    SERVERCALL_RETRYLATER = 2
End Enum

Enum PENDINGMSG
    PENDINGMSG_CANCELCALL = 0
    PENDINGMSG_WAITNOPROCESS = 1
    PENDINGMSG_WAITDEFPROCESS = 2
End Enum

<ComImport(), _
Guid("00000016-0000-0000-C000-000000000046"), _
InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)> _
Interface IOleMessageFilter
    <PreserveSig()> _
    Function HandleInComingCall(ByVal dwCallType As Integer, _
                                ByVal hTaskCaller As IntPtr, _
                                ByVal dwTickCount As Integer, _
                                ByVal lpInterfaceInfo As IntPtr) _
                                As Integer

    <PreserveSig()> _
    Function RetryRejectedCall(ByVal hTaskCallee As IntPtr, _
                               ByVal dwTickCount As Integer, _
                               ByVal dwRejectType As Integer) _
                               As Integer

    <PreserveSig()> _
    Function MessagePending(ByVal hTaskCallee As IntPtr, _
                            ByVal dwTickCount As Integer, _
                            ByVal dwPendingType As Integer) _
                            As Integer
End Interface
OleMessageFilter for Visual C#

In Console applications, you must decorate your Main() function with STAThreadAttribute.

C# example usage
Copy Code
[STAThread]
static void Main(string[] args)
{
  OleMessageFilter.Register();
  // Make COM calls.
  OleMessageFilter.Revoke();
}               

In your Visual C# project, create a new class and name it OleMessageFilter.cs. Copy this example code and paste it into the new class. You will want to modify the namespace of the example code to match your own namespace.

C# implementation of OleMessageFilter
Copy Code
using System;
using System.Runtime.InteropServices;
using System.Threading;

namespace SolidEdge.SDK
{
    class OleMessageFilter : IOleMessageFilter
    {
        public static void Register()
        {
            IOleMessageFilter newFilter = new OleMessageFilter();
            IOleMessageFilter oldFilter = null;

            if (Thread.CurrentThread.GetApartmentState() == ApartmentState.STA)
            {
                CoRegisterMessageFilter(newFilter, out oldFilter);
            }
            else
            {
                throw new COMException("Unable to register message filter because the current thread apartment state is not STA.");
            }
        }

        public static void Revoke()
        {
            IOleMessageFilter oldFilter = null;
            CoRegisterMessageFilter(null, out oldFilter);
        }

        int IOleMessageFilter.HandleInComingCall(
            int dwCallType,
            System.IntPtr hTaskCaller,
            int dwTickCount,
            System.IntPtr lpInterfaceInfo)
        {
            return (int)SERVERCALL.SERVERCALL_ISHANDLED;
        }

        int IOleMessageFilter.RetryRejectedCall(
            System.IntPtr hTaskCallee,
            int dwTickCount,
            int dwRejectType)
        {
            if (dwRejectType == (int)SERVERCALL.SERVERCALL_RETRYLATER)
            {
                return 99;
            }

            return -1;
        }

        int IOleMessageFilter.MessagePending(
            System.IntPtr hTaskCallee,
            int dwTickCount,
            int dwPendingType)
        {
            return (int)PENDINGMSG.PENDINGMSG_WAITDEFPROCESS;
        }

        [DllImport("Ole32.dll")]
        private static extern int CoRegisterMessageFilter(
            IOleMessageFilter newFilter,
            out IOleMessageFilter oldFilter);
    }

    enum SERVERCALL
    {
        SERVERCALL_ISHANDLED = 0,
        SERVERCALL_REJECTED = 1,
        SERVERCALL_RETRYLATER = 2
    }

    enum PENDINGMSG
    {
        PENDINGMSG_CANCELCALL = 0,
        PENDINGMSG_WAITNOPROCESS = 1,
        PENDINGMSG_WAITDEFPROCESS = 2
    }

    [ComImport(), Guid("00000016-0000-0000-C000-000000000046"),
    InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
    interface IOleMessageFilter
    {
        [PreserveSig]
        int HandleInComingCall(
            int dwCallType,
            IntPtr hTaskCaller,
            int dwTickCount,
            IntPtr lpInterfaceInfo);

        [PreserveSig]
        int RetryRejectedCall(
            IntPtr hTaskCallee,
            int dwTickCount,
            int dwRejectType);

        [PreserveSig]
        int MessagePending(
            IntPtr hTaskCallee,
            int dwTickCount,
            int dwPendingType);
    }
}