COM и C# #662575


#0 by oleg_km
Написал на C# два COM-объекта, оба в одной dll в одном проекте. Хочу в метод одного передавать ссылку на объект второго, чтобы метод первого дернул метод второго. Пробовал разные варианты: 1) В параметрах нужного метода первого объекта просто указал интерфейс второго: при вызове выскочило Неизвестная ошибка 2) В параметрах нужного метода первого объекта указал object, в теле метода попытался следать приведение и через и через as, ругается: Нет такого интерфейса 3) В параметрах нужного метода первого объекта указал dynamic, все заработало, но мне так не нравится: нет типизации, нужен .Net 4, нужно на компьютер пользователя устанавливать доп. сборку Примерный код: namespace TestCOM {    [Guid("E5B23F96-411D-4A67-AFBA-B3DF6B3B0ACB")]    public interface ITestCOM    {        [DispId]        void TestOCX(ITestActiveX oTest); // 1-й вариант        void TestOCX(object oTest); // 2-й вариант        void TestOCX(dynamic oTest); // 3-й вариант    }    [ProgId("TestCOM.Test"),    ClassInterface(ClassInterfaceType.None),    Guid("1BD846DC-63F2-4070-AF23-8AECD6C158CC")]    public class CTestCOM : ITestCOM    {        public void TestOCX(ITestActiveX oTest) // 1-й        {            oTest.ShowEvent("Test parameter");        }        public void TestOCX(object oTest) // 2-й        {            ITestActiveX ot = (ITestActiveX) oTest;            ot.ShowEvent("Test parameter");        }        public void TestOCX(dynamic oTest) // 3-й        {            oTest.ShowEvent("Test parameter");        }    }   [Guid("D783DC48-8FB0-4fe9-BDC2-0CEE3F5E8921")]    [InterfaceType(ComInterfaceType.InterfaceIsDual)]    public interface ITestActiveX    {        [DispId]        void ShowEvent(string msg);    }    [Guid("A94CEA0F-1CD3-4829-A75E-B8A81A1EE56D")]    [ProgId("TestCOM.TestActiveX")]    [ComDefaultInterface(typeof(ITestActiveX))]    [ClassInterface(ClassInterfaceType.None)]    public class TestActiveX : UserControl, ITestActiveX    {        public void ShowEvent(string msg)        {            MessageBox.Show(msg);        }    } } Очень хочу первый вариант, если что готов и на второй
#1 by Rie
Так а где сам вызов-то?
#2 by Serginio1
[ClassInterface(ClassInterfaceType.AutoDual), ComVisible(true), Guid("A94CEA0F-1CD3-4829-A75E-B8A81A1EE56D"), ProgId("TestCOM.TestActiveX")]
#3 by ptrtss
Незнаю, может поможет
#4 by oleg_km
TestOCX в интерфейсе ITestCOM, ну в 1С примерно так: об1 = Новый COMОбъект("TestCOM.Test"); об2 = Новый COMОбъект("TestCOM.TestActiveX"); об1.TestOCX(об2); Имеется ввиду AutoDual вместо None? Только что попробовал, тоже самое.
#5 by oleg_km
Так это вроде соответствует второму варианту. вызов метода идет, но не проходит приведение типа. Ругается что интерфейс D783DC48-8FB0-4fe9-BDC2-0CEE3F5E8921 (ITestActiveX) не отдается QueryInterface
#6 by Serginio1
У тебя не получится второй вызвать. Можно в  interface ITestCOM Создать метод который создает экземпляр класса TestActiveX.
#7 by Serginio1
Например ITestActiveX ПолучитьОббъектTestActiveX;
#8 by Serginio1
Об2=Об1.ПолучитьОббъектTestActiveX;
#9 by oleg_km
Подожди, в 3-м варианте через dynamic получается же. Код из в третьем варианте нормально работает, просто мне само использование dynamic не нравится.
#10 by Serginio1
Замени void TestOCX(ITestActiveX oTest); На void TestOCX(IDispoatch oTest); это будет вариант с оbject и dynamic. Просто получается разные соклассы.
#11 by oleg_km
Вот так: void TestOCX([MarshalAs(UnmanagedType.IUnknown)] object oTest); Пробовал, тоже не получилось
#12 by Serginio1
IUnknown<>IDispatch
#13 by Serginio1
Ты лучше скажи Об2=Об1.ПолучитьОббъектTestActiveX; об1.TestOCX(об2); работает?
#14 by oleg_km
И с IDispatch тоже пробовал.
#15 by oleg_km
Дело в том что объекты создаются независимо. но я сейчас попробовал наоборот во второй объект передать первый и все прошло нормально. Надо аккуратно все пересобрать
#16 by Serginio1
Первый это основной coClass. Поэтому я и предложил попробовать 13
#17 by Ковычки
Вы написали не ком
#18 by oleg_km
Первый это основной coClass Как ты это понял, вообще-то это просто два разных КОМа, просто в одном проекте. Если быть точным один просто ком, второй активикс: CTestCOM : ITestCOM  - просто ком TestActiveX : UserControl, ITestActiveX - активикс, я просто выкинул всякие события прочее А как тогда его дергает 1С? 1С напрямую научилось подключаться к .NET?
#19 by oleg_km
Первый это основной coClass Вот смотрю в библиотеке типов: у каждого свой кокласс
#20 by Serginio1
Есть такая функция dllgetclassobject которая находит нужный DLL И обычно вторым параметром передаетя IDispatch. Но проблема скорее всего в [ComVisible(true), ClassInterface(ClassInterfaceType.AutoDispatch)] public class ContainerControl : ScrollableControl, IContainerControl ComVisible(true), Designer("System.Windows.Forms.Design.ControlDesigner, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"), DefaultEvent("Load"), DesignerCategory("UserControl"), ClassInterface(ClassInterfaceType.AutoDispatch), Designer("System.Windows.Forms.Design.UserControlDocumentDesigner, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(IRootDesigner))] public class UserControl : ContainerControl То есть UserControl сам реализует IDispatch. Возможно в этом проблема
#21 by Serginio1
Кстати ты 13 не пробовал?
#22 by Serginio1
Посмотри Но там [ComVisible(true)]    [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] Да и для    [ProgId("TestCOM.Test"),    ClassInterface(ClassInterfaceType.None),    Guid("1BD846DC-63F2-4070-AF23-8AECD6C158CC")]    public class CTestCOM : ITestCOM  [InterfaceType(ComInterfaceType.InterfaceIsDual)]
#23 by oleg_km
Решил проблему. Дело в том что когда я написал пример вызывающего кода: об1 = Новый COMОбъект("TestCOM.Test"); об2 = Новый COMОбъект("TestCOM.TestActiveX"); об1.TestOCX(об2); я немножко слукавил - только один объект создается конструкцией CreateObject, второй то сажается на форму как ActiveX. Среда 1С дает мне доступ к этому объекту как ссылку на элемент формы и судя по всему это какой-то контейнер. Т.е. когда я вызываю методы своего объекта, на самом деле я дергаю контейнер, а контейнер уже дергает мой объект, а когда я передаю ссылку в другой объект, он пытается привести тип в соответствие с указанным типом моего параметра и обнаруживает, что тип (тип контейнера) у него отсутствует. Я просто в ActiveX добавил метод, который возвращает указатель на себя, приведенный к типу своего интерфейса:            public ITestOCX1 GetThis            {                return (ITestOCX1)this;            } И вызов теперь выглядит: обТест = Новый COMОбъект("TestCOM.TestCOM1"); обТест.CallTest(ЭлементыФормы.TestOCX1.GetThis); Если это коряво, то как делать правильно?
#24 by Serginio1
Это нормально, об этом я тебе и писал в 22 (просто идет расширение  GetsIDOfNames и Invoke ), но мало чем отличается от того, что я предлагал тебе в 13.
#25 by oleg_km
Я теперь понял в чем заключался совет: ссылку для дальнейшей работы в .NET нужно получать не от 1С, а от .NET
#26 by Serginio1
Я тебе в 20 писал как получает 1С IDispatch через dllgetclassobject . TestActiveX  по сути реализует два IDispatch,но расширяет он методы UserControl котрый ничего не знает об ITestCOM. Но в Net могли бы и переопределить QueryInterface, но почему то они этого не сделали.
Тэги:
Ответить:
Комментарии доступны только авторизированным пользователям

В этой группе 1С