La aplicación .NET CF llama a Unadvise en el punto de conexión COM cuando el formulario pierde el foco

Este artículo le ayuda a solucionar el problema en el que no se reciben eventos desde el objeto del modelo de objetos componentes (COM) cuando la aplicación .NET Compact Framework que crea un objeto COM y se conecta a su punto de conexión de origen pierde el foco.

Versión del producto original:   Microsoft .NET Compact Framework 3.5
Número KB original:   2300221

Síntoma

Una aplicación .NET Compact Framework crea un objeto COM y se conecta a su punto de conexión de origen. El objeto .NET ahora recibe correctamente eventos que envía el objeto COM. Sin embargo, cuando la aplicación .NET Compact Framework pierde el foco, no se reciben más eventos del objeto COM, incluso después de que la aplicación vuelva a recibir el foco.

Causa

Cuando la aplicación pierde el foco, .NET Compact Framework llama erróneamente al Unadvise método en la interfaz del objeto IConnectionPoint COM.

Solución

Hay dos soluciones alternativas posibles:

  • Este problema solo se produce en .NET Compact Framework 3.5. Las aplicaciones seguirán comportando el comportamiento esperado en .NET Compact Framework 2.0. Esta es una posible solución alternativa si es viable.
  • En lugar de depender de la compatibilidad integrada con puntos de conexión COM en .NET Compact Framework, se puede escribir el código para conectarse y desconectar manualmente a la interfaz de origen expuesta por el objeto COM. A continuación se proporciona código de ejemplo para realizar esto.

A continuación se muestra un breve ejemplo de cómo se puede conectar manualmente a una interfaz de origen expuesta por un objeto COM sin usar la instalación .NET para hacerlo.

Supongamos que hemos importado un objeto COM denominado EventGeneratorLib. En primer lugar, defina la interfaz expuesta como interfaz de origen por el objeto COM. En este ejemplo, la interfaz se hereda de IDispatch y contiene un único método.

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

Ahora defina una clase para implementar la interfaz.

[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
}

El código anterior solo se proporciona como ejemplo. Se ha omitido el control de errores por brevedad.