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 por el que no se recibe ningún evento del objeto 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 original del producto: 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 recibe ningún evento adicional 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 IConnectionPoint objeto COM.

Solución

Hay dos posibles soluciones alternativas:

  • Este problema solo se produce en .NET Compact Framework 3.5. Las aplicaciones seguirán comportándose según lo esperado en .NET Compact Framework 2.0. Esta es una posible solución alternativa si es factible.
  • En lugar de basarse en la compatibilidad integrada con puntos de conexión COM en .NET Compact Framework, se puede escribir el código para conectarse y desconectarse manualmente a la interfaz de origen expuesta por el objeto COM. A continuación se proporciona código de ejemplo para lograr 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 de .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. El control de errores se ha omitido por brevedad.