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

Este artículo le ayudará a evitar el problema de que no se reciban eventos del objeto del modelo de objetos componentes (COM) cuando la aplicación de .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 de KB original:   2300221

Síntoma

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

Causa

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

Solución

Hay dos posibles soluciones:

  • Este problema sólo se produce en .NET Compact Framework 3,5. Las aplicaciones se seguirán comportándose de la manera esperada en .NET Compact Framework 2,0. Esta es una posible solución si es viable.
  • En lugar de confiar en la compatibilidad integrada para los puntos de conexión COM en .NET Compact Framework, se puede escribir el código para conectarse manualmente y desconectarse a la interfaz de origen expuesta por el objeto COM. A continuación se proporciona un ejemplo de código para conseguirlo.

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

Supongamos que hemos importado un objeto COM denominado EventGeneratorLib. En primer lugar, defina la interfaz que el objeto COM expone como la interfaz de origen. En este ejemplo, la interfaz se hereda de IDispatch y contiene un solo 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 un ejemplo. Se ha omitido el tratamiento de errores por motivos de brevedad.