Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В этой статье показано, как обойти проблему, в которой события не получены из объекта "Объектная модель компонента" (COM), когда приложение .NET Compact Framework, создающее COM-объект и подключающееся к исходной точке подключения, теряет фокус.
Исходная версия продукта: Microsoft .NET Compact Framework 3.5
Исходный номер базы знаний: 2300221
Симптом
Приложение .NET Compact Framework создает COM-объект и подключается к исходной точке подключения. Объект .NET теперь успешно получает события, отправляемые com-объектом. Однако, когда приложение .NET Compact Framework теряет фокус, дальнейшие события не получаются от COM-объекта, даже после того, как приложение снова получает фокус.
Причина
Когда приложение теряет фокус, платформа .NET Compact Framework ошибочно вызывает Unadvise
метод в интерфейсе COM-объекта IConnectionPoint
.
Резолюция
Существует два возможных обходных решения:
- Эта проблема возникает только в .NET Compact Framework 3.5. Приложения будут продолжать работать должным образом в .NET Compact Framework 2.0. Это возможное обходное решение, если это возможно.
- Вместо того чтобы полагаться на встроенную поддержку точек COM-соединений в .NET Compact Framework, можно написать код для ручного подключения и отключения к исходному интерфейсу, предоставляемому объектом COM. Ниже приведен пример кода для выполнения этой задачи.
Ниже приведен краткий пример того, как можно вручную подключиться к исходному интерфейсу, предоставляемому com-объектом без использования объекта .NET для этого.
Предположим, что мы импортировали COM-объект с именем EventGeneratorLib. Сначала определите интерфейс, предоставляемый в качестве исходного интерфейса объектом COM. В этом примере интерфейс наследуется от IDispatch
одного метода.
[ComImport, Guid("<GUID of COM object's source interface>"), InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface _ISampleEvents
{
[DispId(1)]
void FireEvent();
}
Теперь определите класс для реализации интерфейса.
[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
}
Приведенный выше код предоставляется только в качестве примера. Обработка ошибок была опущена для краткости.