Die .NET CF-Anwendung ruft Unadvise on COM connection point auf, wenn das Formular den Fokus verliert

In diesem Artikel können Sie das Problem umgehen, bei dem keine Ereignisse vom COM-Objekt (Component Object Model) empfangen werden, wenn die .NET Compact Framework-Anwendung, die ein COM-Objekt erstellt und eine Verbindung mit seinem Quellverbindungspunkt herstellt, den Fokus verliert.

Ursprüngliche Produktversion: Microsoft .NET Compact Framework 3.5
Ursprüngliche KB-Nummer: 2300221

Problembeschreibung

Eine .NET Compact Framework-Anwendung erstellt ein COM-Objekt und stellt eine Verbindung mit dem zugehörigen Quellverbindungspunkt her. Das .NET-Objekt empfängt nun erfolgreich Ereignisse, die vom COM-Objekt gesendet werden. Wenn die .NET Compact Framework-Anwendung jedoch den Fokus verliert, werden keine weiteren Ereignisse vom COM-Objekt empfangen, auch wenn die Anwendung den Fokus erneut erhält.

Ursache

Wenn die Anwendung den Fokus verliert, ruft .NET Compact Framework fälschlicherweise die Unadvise -Methode in der Schnittstelle des COM-Objekts IConnectionPoint auf.

Lösung

Es gibt zwei mögliche Problemumgehungen:

  • Dieses Problem tritt nur unter .NET Compact Framework 3.5 auf. Anwendungen verhalten sich unter .NET Compact Framework 2.0 weiterhin wie erwartet. Dies ist eine mögliche Problemumgehung, wenn möglich.
  • Anstatt sich auf die integrierte Unterstützung für COM-Verbindungspunkte in .NET Compact Framework zu verlassen, kann der Code geschrieben werden, um eine manuelle Verbindung mit der vom COM-Objekt verfügbar gemachten Quellschnittstelle herzustellen und diese zu trennen. Im Folgenden finden Sie Beispielcode, um dies zu erreichen.

Es folgt ein kurzes Beispiel dafür, wie sie manuell eine Verbindung mit einer Quellschnittstelle herstellen können, die von einem COM-Objekt verfügbar gemacht wird, ohne hierfür die .NET-Funktion zu verwenden.

Angenommen, wir haben ein COM-Objekt namens EventGeneratorLib importiert. Definieren Sie zunächst die Schnittstelle, die vom COM-Objekt als Quellschnittstelle verfügbar gemacht wird. In diesem Beispiel wird die Schnittstelle von IDispatch geerbt und enthält eine einzelne Methode.

[ComImport, Guid("<GUID of COM object's source interface>"), InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface _ISampleEvents
{
    [DispId(1)]
    void FireEvent();
}

Definieren Sie nun eine Klasse, um die -Schnittstelle zu implementieren.

[ComVisible(true), ClassInterface(ClassInterfaceType.None)]
public class SampleEvents : IDisposable, _ISampleEvents
{
    // COM object
    private EventGeneratorLib.EventGenerator _oEventGenerator;

    private bool _disposed = false;
    private IConnectionPoint _cp = null;
    private int _dwCookie = 0;

    public SampleEvents()
    {
        // Instantiate the COM object
        _oEventGenerator = new EventGeneratorLib.EventGenerator();

        // Set up callback
        if (_oEventGenerator != null)
        {
            // Query the object for an IConnectionPointContainer interface
            IConnectionPointContainer cpc = (IConnectionPointContainer)_oEventGenerator;

            IConnectionPoint cp = null;

            Guid cpGuid = new Guid("<GUID of source interface as defined by COM object>");
            int dwCookie = 0;

            // Find the connection point
            cpc.FindConnectionPoint(ref cpGuid, out cp);

            // Call advise to start receiving events from the COM object
            cp.Advise((_ISampleEvents)this, out dwCookie);

            // Save the cookie and the ConnectionPoint interface pointer
            _dwCookie = dwCookie;
            _cp = cp;
        }
    }

    ~SampleEvents()
    {
    Dispose(false);
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
        return;
    }

    private void Dispose(bool disposing)
    {
        // Check to see if Dispose has already been called.
        if (!this._disposed)
        {
            if (disposing)
            {
                // No code required here
            }

            // See if we created the COM object
            if (_oEventGenerator != null)
            {
                // Tear down the connection point
                if (_cp != null)
                {
                    _cp.Unadvise(_dwCookie);
                    _cp = null;
                }
                Marshal.ReleaseComObject(_oEventGenerator);
                 _oEventGenerator = null;
            }
        }
    _disposed = true;
    }

    #region _ISampleEvents Members

    // This is the definition of the interface that the COM object
    // calls back into.
    void _ISampleEvents.FireEvent()
    {
        // Do something here with event from COM object
    }
    #endregion
}

Der obige Code wird nur als Beispiel bereitgestellt. Die Fehlerbehandlung wurde aus Platzgründen ausgelassen.