.NET CF-Anwendung ruft Unadvise on com Connection Points 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 dem Quell Verbindungspunkt herstellt, den Fokus verliert.

Original Version des Produkts:   Microsoft .NET Compact Framework 3,5
Ursprüngliche KB-Nummer:   2300221

Symptom

Eine .NET Compact Framework-Anwendung erstellt ein COM-Objekt und stellt eine Verbindung mit dem Quell Verbindungspfad her. Das .NET-Objekt empfängt jetzt 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 auf IConnectionPoint .

Lösung

Es gibt zwei mögliche Problemumgehungen:

  • Dieses Problem tritt nur auf .NET Compact Framework 3,5. Anwendungen verhalten sich weiterhin wie erwartet unter .NET Compact Framework 2,0. 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 so geschrieben werden, dass eine manuelle Verbindung mit der vom COM-Objekt verfügbar gemachten Quellschnittstelle hergestellt wird. Beispielcode, um dies zu erreichen, wird unten bereitgestellt.

Im folgenden finden Sie ein kurzes Beispiel dafür, wie eine Verbindung mit einer Quellschnittstelle, die von einem COM-Objekt verfügbar gemacht wird, manuell hergestellt werden kann, ohne dass die .net-Funktion dazu verwendet wird.

Angenommen, wir haben ein COM-Objekt mit dem Namen EventGeneratorLibimportiert. Definieren Sie zunächst die Schnittstelle, die vom COM-Objekt als Quellschnittstelle verfügbar gemacht wird. In diesem Beispiel wird die Schnittstelle geerbt IDispatch 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 Gründen der Kürze weggelassen.