Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Последние темы форума

Показать новые сообщения »

Почтовая рассылка

Подписчиков: 11656
Последний выпуск: 19.06.2015

Вызов unmanaged-методов в COM-компоненте

48K
27 июня 2010 года
ZeroDivision
18 / / 14.08.2009
Есть код COM-компоненты:

Код:
// MyComponent.cs
// compile csc /t:library MyComponent.cs
// post-build command: regasm MyComponent.dll /codebase

using System;
using System.Runtime.InteropServices;
using System.Timers;
using System.Windows.Forms;

namespace AddIn
{
    [Guid(@"AB634001-F13D-11D0-A459-004095E1DAEA"),
     InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IInitDone
    {
        void Init([MarshalAs(UnmanagedType.IDispatch)] Object pConnection);
        void Done();
        void GetInfo([MarshalAs(UnmanagedType.SafeArray,
                SafeArraySubType = VarEnum.VT_VARIANT)] ref Object[] pInfo);
    }

    [Guid("AB634004-F13D-11D0-A459-004095E1DAEA"),
     InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IAsyncEvent
    {
        void SetEventBufferDepth(Int32 depth);
        void GetEventBufferDepth(ref Int32 depth);
        void ExternalEvent([MarshalAs(UnmanagedType.BStr)] String source,
                           [MarshalAs(UnmanagedType.BStr)] String message,
                           [MarshalAs(UnmanagedType.BStr)] String data);
        void CleanBuffer();
    }

    /* Component implementation */
    [ComVisible(true),
     ProgId(@"AddIn.MyComponent"),
     Guid(@"73d61140-e6b2-47df-9d8c-6a2f788d0a53"),
     ClassInterface(ClassInterfaceType.AutoDispatch)]
    public class MyComponent : IInitDone
    {
        private static IAsyncEvent eventDispatcher;
        private static Object application;
        private static System.Timers.Timer eventTimer;

        public MyComponent()
        {
            /* Constructor */
        }
        public void Init([MarshalAs(UnmanagedType.IDispatch)] Object pConnection)
        {
            try
            {
                application = pConnection;
                eventDispatcher = (IAsyncEvent)pConnection;
               
                /* Setup timer */
                eventTimer = new System.Timers.Timer();
                eventTimer.Elapsed += new ElapsedEventHandler(OnEventTimer);
                eventTimer.Interval = 10000;  // Every ten seconds
                eventTimer.Enabled = true;

                eventDispatcher.ExternalEvent("AddIn", "Type", "Usual Event");
            }
            catch
            {
                throw new COMException(@"Unknown object context");
            }
        }

        public void Done()
        {
            application = null;
            eventDispatcher = null;
        }

        public void GetInfo([MarshalAs(UnmanagedType.SafeArray,
                             SafeArraySubType = VarEnum.VT_VARIANT)] ref Object[] pInfo)
        {
            pInfo[0] = @"2000"; // Required
        }

        private static void OnEventTimer(object source, ElapsedEventArgs e)
        {
            try
            {
                eventDispatcher.ExternalEvent("AddIn", "Type", "Thread Event");
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
    }
}


Это внешняя компонента (ВК) к 1С, отсюда и наследование интерфейса IInitDone.
Отправка сообщения в 1С осуществляется с помощью метода ExternalEvent интерфейса IAsyncEvent. Из основного потока отправка осуществляется нормально, а вот при попытке отправки из потока таймера вылетает исключение:

 
Код:
Unable to cast COM object of type 'System.__ComObject' to interface type 'AddIn.IAsyncEvent'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{GUID}' failed due to the follow error: No such interface supported


Что-то мне подсказывает что дело в маршалинге, в том что он на другой поток не распространяется. Но что надо дописать и куда - понятия не имею. Кто имел дело с COM'ом и C# подскажите?
48K
15 июля 2010 года
ZeroDivision
18 / / 14.08.2009
Проблема была из-за регистрации компоненты в реестре. Необходимо регистрировать с ключом /tlb, а ключ /codebase вообще не нужен:
 
Код:
regasm MyComponent.dll /tlb

Знаете кого-то, кто может ответить? Поделитесь с ним ссылкой.

Ваш ответ

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог