Имя: Пароль:
1C
1С v8
Внешняя компонента. Метод объекта не обнаружен.
0 alexkozin
 
16.10.15
10:06
Коллеги, приветствую!
Встал в ступор. По шаблону "накатал" внешнюю компоненту. Инициализируется нормально, никаких проблем, IInitDone отрабатывается нормально, но вот беда - ни одного определенного мной метода 1С не видит.
То есть в компоненте есть мой метод methTest, но 1С при вызове метода ВК.methTest() пишет "Метод объекта не обнаружен".
Компонента зарегистрирована через regasm и инициализирована в 1С без ошибок. Платформа 1с 8.2.14.533
Куда копать?
Заранее спасибо!
1 alexkozin
 
19.10.15
08:49
Уп))
2 Кирпич
 
19.10.15
08:53
(0) смотреть на свой код пока не вскочишь и воскликнешь: "о боже! неужели это я мог допустить такую глупую ошибку!"
3 alexkozin
 
19.10.15
08:55
(2) Дык вроде как всё просмотрел таки..... Всё прям по фен шую
4 Кирпич
 
19.10.15
09:00
(3) ну тогда выкладывай код. добрый дядя тебе найдет твой косяк.
5 alexkozin
 
19.10.15
19:17
Imports System.Runtime.InteropServices
Imports System.Windows.Forms

'Сгенерируйте уникальный идентификатор компоненты (меню Tools - Create GUID)  
'Укажите ProgID компоненты (по этому имени ее будет находить 1С).
'Пример регистрации компоненты в системном реестре, чтобы ее смогла найти 1С:
'regasm.exe vk_XmlTextReaderWriter.dll /codebase


<ComVisible(True), Guid("ACA5E6E0-DA61-4a05-8024-F0002D0E9616"), ProgId("AddIn.vk_OLE")> _
Public Class vk_OLE

    Implements IInitDone
    Implements ILanguageExtender
    Const c_AddinName As String = "vk_OLE"

#Region "IInitDone implementation"
    '/////////////////////////////////////////////////////////////////////////////////
    Public Sub New() ' Обязательно для COM инициализации
        'Вызывается при начале работы внешней компоненты (2 раза)

    End Sub

    '/////////////////////////////////////////////////////////////////////////////////
    Private Sub Init(<MarshalAs(UnmanagedType.IDispatch)> ByVal pConnection As Object) Implements IInitDone.Init
        'Вызывается при начале работы внешней компоненты (2 раза)
        V7Data.V7Object = pConnection
    End Sub

    '/////////////////////////////////////////////////////////////////////////////////
    Private Sub Done() Implements IInitDone.Done
        'Вызывается при завершении работы внешней компоненты (2 раза)

        MessageBox.Show("Завершение работы ВК")

        obj1C = Nothing
        V7Data.V7Object = Nothing
        GC.Collect()
        GC.WaitForPendingFinalizers()
    End Sub

    '/////////////////////////////////////////////////////////////////////////////////
    Private Sub GetInfo(ByRef pInfo() As Object) Implements IInitDone.GetInfo
        pInfo.SetValue("2000", 0)
    End Sub

    '/////////////////////////////////////////////////////////////////////////////////
    Sub RegisterExtensionAs(ByRef bstrExtensionName As String) Implements ILanguageExtender.RegisterExtensionAs
        bstrExtensionName = c_AddinName
    End Sub
#End Region

#Region "Переменные"
    Dim obj1C As Object 'Объект 1С
    Dim g_flagInit As Boolean 'Признак, что инициализация obj1C уже прошла
    '<MarshalAs(UnmanagedType.IDispatch)> Dim g_var As Object
    Dim g_var As Object

#End Region

#Region "Свойства"
    '/////////////////////////////////////////////////////////////////////////////////
    Enum Props
        'Числовые идентификаторы свойств внешней компоненты
        LastProp = 0
    End Enum

    '/////////////////////////////////////////////////////////////////////////////////
    Sub GetNProps(ByRef plProps As Integer) Implements ILanguageExtender.GetNProps
        'Здесь 1С получает количество доступных из ВК свойств
        plProps = Props.LastProp
    End Sub

    '/////////////////////////////////////////////////////////////////////////////////
    Sub FindProp(ByVal bstrPropName As String, ByRef plPropNum As Integer) Implements ILanguageExtender.FindProp
        'Здесь 1С ищет числовой идентификатор свойства по его текстовому имени

        Select Case bstrPropName
        End Select
    End Sub

    '/////////////////////////////////////////////////////////////////////////////////
    Sub GetPropName(ByVal lPropNum As Integer, ByVal lPropAlias As Integer, ByRef pbstrPropName As String) Implements ILanguageExtender.GetPropName
        'Здесь 1С (теоретически) узнает имя свойства по его идентификатору. lPropAlias - номер псевдонима

        pbstrPropName = ""
    End Sub



    '/////////////////////////////////////////////////////////////////////////////////
    'Функция генерирует исключение в 1С
    Sub Raise1CException(ByVal s As String)

        Dim ei As ExcepInfo
        ei.wCode = 1004 'Вид пиктограммы
        '1000 - нет значка
        '1001 - обычный значок
        '1002 - красный значок !
        '1003 - красный значок !!
        '1004 - красный значок !!!
        '1005 - зеленый значок i
        '1006 - красный значок err
        '1007 - Окно предупреждения "Внимание"
        '1008 - Окно предупреждения "Информация"
        '1009 - Окно предупреждения "Ошибка"

        ei.scode = 1 'Генерируем ошибку времени исполнения
        ei.bstrDescription = s 'Сообщение
        ei.bstrSource = c_AddinName

        V7Data.ErrorLog.AddError(c_AddinName, ei)

    End Sub


    '/////////////////////////////////////////////////////////////////////////////////
    Sub GetPropVal(ByVal lPropNum As Integer, ByRef pvarPropVal As Object) Implements ILanguageExtender.GetPropVal
        'Здесь 1С узнает значения свойств

        Try
            pvarPropVal = Nothing
            Select Case lPropNum

            End Select
        Catch ex As Exception 'Обработчик исключительных ситуаций (ошибок)
            Raise1CException(ex.Message)
        End Try
    End Sub

    '/////////////////////////////////////////////////////////////////////////////////
    Sub SetPropVal(ByVal lPropNum As Integer, ByRef varPropVal As Object) Implements ILanguageExtender.SetPropVal
        'Здесь 1С изменяет значения свойств
        Select Case lPropNum

            '/////////////////////////////////////////////////////////
            'Реализуем изменение свойства "Отступ"
        End Select
    End Sub

    '/////////////////////////////////////////////////////////////////////////////////
    Sub IsPropReadable(ByVal lPropNum As Integer, ByRef pboolPropRead As Boolean) Implements ILanguageExtender.IsPropReadable
        'Здесь 1С узнает, какие свойства доступны для чтения
        pboolPropRead = True ' Все свойства доступны для чтения
    End Sub

    '/////////////////////////////////////////////////////////////////////////////////
    Sub IsPropWritable(ByVal lPropNum As Integer, ByRef pboolPropWrite As Boolean) Implements ILanguageExtender.IsPropWritable
        'Здесь 1С узнает, какие свойства доступны для записи
        pboolPropWrite = True ' Все свойства доступны для записи
    End Sub

#End Region

#Region "Методы"

    '/////////////////////////////////////////////////////////////////////////////////
    Enum Methods
        'Числовые идентификаторы методов (процедур или функций) внешней компоненты
        methTest = 0
        methGetValue = 1
        methSetValue = 2
        methClose = 3
        LastMethod = 4
    End Enum


    '/////////////////////////////////////////////////////////////////////////////////
    Sub GetNMethods(ByRef plMethods As Integer) Implements ILanguageExtender.GetNMethods
        plMethods = Methods.LastMethod
    End Sub


    '/////////////////////////////////////////////////////////////////////////////////
    Sub FindMethod(ByVal bstrMethodName As String, ByRef plMethodNum As Integer) Implements ILanguageExtender.FindMethod
        'Здесь 1С получает числовой идентификатор метода (процедуры или функции) по имени (названию) процедуры или функции

        plMethodNum = -1
        Select Case bstrMethodName
            Case "Test", "Тест"
                plMethodNum = Methods.methTest
            Case "GetValue", "ПолучитьЗначение"
                plMethodNum = Methods.methGetValue
            Case "SetValue", "УстановитьЗначение"
                plMethodNum = Methods.methSetValue
            Case "Close", "Закрыть"
                plMethodNum = Methods.methClose
        End Select
    End Sub

    '/////////////////////////////////////////////////////////////////////////////////
    Sub GetMethodName(ByVal lMethodNum As Integer, ByVal lMethodAlias As Integer, ByRef pbstrMethodName As String) Implements ILanguageExtender.GetMethodName
        'Здесь 1С (теоретически) получает имя метода по его идентификатору. lMethodAlias - номер синонима.
        pbstrMethodName = ""
    End Sub

    '/////////////////////////////////////////////////////////////////////////////////
    Sub GetNParams(ByVal lMethodNum As Integer, ByRef plParams As Integer) Implements ILanguageExtender.GetNParams
        'Здесь 1С получает количество параметров у метода (процедуры или функции)

        Select Case lMethodNum
            Case Methods.methTest
                plParams = 0
            Case Methods.methGetValue
                plParams = 0
            Case Methods.methSetValue
                plParams = 1
            Case Methods.methClose
                plParams = 0
        End Select

    End Sub

    '/////////////////////////////////////////////////////////////////////////////////
    Sub GetParamDefValue(ByVal lMethodNum As Integer, ByVal lParamNum As Integer, ByRef pvarParamDefValue As Object) Implements ILanguageExtender.GetParamDefValue
        'Здесь 1С получает значения параметров процедуры или функции по умолчанию
        pvarParamDefValue = Nothing 'Нет значений по умолчанию
    End Sub

    '/////////////////////////////////////////////////////////////////////////////////
    Sub HasRetVal(ByVal lMethodNum As Integer, ByRef pboolRetValue As Boolean) Implements ILanguageExtender.HasRetVal
        'Здесь 1С узнает, возвращает ли метод значение (т.е. является процедурой или функцией)
        pboolRetValue = True  'Все методы у нас будут функциями (т.е. будут возвращать значение).
    End Sub

    '/////////////////////////////////////////////////////////////////////////////////
    Sub CallAsProc(ByVal lMethodNum As Integer, ByRef paParams As System.Array) Implements ILanguageExtender.CallAsProc
        'Здесь внешняя компонента выполняет код процедур. А процедур у нас нет.
    End Sub


    '/////////////////////////////////////////////////////////////////////////////////
    Sub CallAsFunc(ByVal lMethodNum As Integer, _
     ByRef pvarRetValue As Object, _
     <MarshalAs(UnmanagedType.IDispatch)> ByRef paParams As System.Array) _
    Implements ILanguageExtender.CallAsFunc

        'Здесь внешняя компонента выполняет код функций.

        Try
            pvarRetValue = 0 'Возвращаемое значение метода для 1С
            Select Case lMethodNum 'Порядковый номер метода
                '//////////////////////////////////////////////////////////
            Case Methods.methTest  'Реализуем метод для тестирования доступа к 1С
                    If g_flagInit = False Then
                        obj1C = V7Data.V7Object.AppDispatch
                        Marshal.Release(Marshal.GetIDispatchForObject(obj1C))
                        g_flagInit = True
                    End If



                    Dim obj0 As Object

                    obj0 = obj1C.CreateObject("Справочник.Товары")
                    obj0.ВыбратьЭлементы()
                    obj0.ПолучитьЭлемент()
                    System.Windows.Forms.MessageBox.Show("Товар: " + obj0.Наименование)


                    obj0 = Nothing
                    GC.Collect()
                    GC.WaitForPendingFinalizers()

                Case Methods.methSetValue
                    'Реализуем метод для установки значения из 1С в внешнюю компоненту
                    g_var = paParams.GetValue(0)

                Case Methods.methGetValue
                    'Реализуем метод для чтения значения в 1С из внешней компоненты

                    pvarRetValue = g_var

                Case Methods.methClose

                    'Реализуем метод для очистки переменной (иначе 1С зависает в памяти)

                    'Marshal.Release(Marshal.GetIDispatchForObject(g_var))
                    g_var = Nothing
                    GC.Collect()
                    GC.WaitForPendingFinalizers()

            End Select

        Catch ex As Exception 'Обрабатываем исключение (ошибку)
            Raise1CException(ex.Message)
        End Try


    End Sub

#End Region
End Class
6 alexkozin
 
19.10.15
19:19
Собсно вот класс.... Абсолютно как в книжке))

Вот форма:
Процедура ПриОткрытии()

    ИмяВК="AddIn.vk_OLE";
        
    ок=ПодключитьВнешнююКомпоненту(ИмяВК);
    Если ок=0 Тогда
        Сообщить("Не удалось подключить компоненту "+ИмяВК);
    КонецЕсли;
    ВК = Новый COMОбъект(ИмяВК);
            
КонецПроцедуры

    
Процедура КнопкаВыполнитьНажатие(Кнопка)
    
       Сообщить(ВК.methTest());
    
КонецПроцедуры
7 alexkozin
 
19.10.15
19:20
А вот ошибка:
{Форма.Форма.Форма(8)}: Метод объекта не обнаружен (methTest)
    Сообщить(ВК.methTest());
8 Serginio1
 
19.10.15
20:36
А зачем тебе ВК?
посмотри http://catalog.mista.ru/public/238584/
Там кстати реализована ВК для получения глобального контекста и интерфейсов
9 hhhh
 
19.10.15
21:59
(7) в процедуду ПриОткрытии() попадает вообще? В отладчике смотрел?
10 alexkozin
 
20.10.15
06:59
(9) Здарова!
Да, попадает и загрузка и выгрузка компоненты робит отлично. IInitDone отрабатывает без проблем.
11 alexkozin
 
20.10.15
07:00
(8) дык научиться хочу)) Кстати, спс за ссылку, обязательно ознакомлюсь, но для начала хотелось бы разобраться с ВК.
12 Serginio1
 
20.10.15
08:21
Так для того, что бы научиться, нужно посмотреть на уже существующие решения. Там есть и реализация ВК
13 Кирпич
 
20.10.15
08:25
Sub GetMethodName(ByVal lMethodNum As Integer, ByVal lMethodAlias As Integer, ByRef pbstrMethodName As String) Implements ILanguageExtender.GetMethodName

        pbstrMethodName = ""
    End Sub

это что за фигня?
здесь ты должен возвращать имя метода по его номеру
14 Маратыч
 
20.10.15
08:27
Погодь, у тебя FindMethod что искать пытается, посмотри. Ты ей пихаешь methTest, а у нее в Case такого нет, есть только Test. Плюс (13) еще.
15 Serginio1
 
20.10.15
08:32
16 Serginio1
 
20.10.15
11:08
14 Ну и в отладчике посмотри
FindMethod
CallAsFunc
17 alexkozin
 
20.10.15
21:17
(16) приколюха в том что в отладчике да данных функций почему-то не доходит. Последний отрабатываемый метод это ILanguageExtender-овский RegisterExtensionAs

  Sub RegisterExtensionAs(ByRef bstrExtensionName As String) Implements ILanguageExtender.RegisterExtensionAs
        bstrExtensionName = c_AddinName
    End Sub

и усё.... даьше как будто выходит из отладчика
18 alexkozin
 
20.10.15
21:20
(14) вписал таки
'/////////////////////////////////////////////////////////////////////////////////
    Sub FindMethod(ByVal bstrMethodName As String, ByRef plMethodNum As Integer) Implements ILanguageExtender.FindMethod
        'Здесь 1С получает числовой идентификатор метода (процедуры или функции) по имени (названию) процедуры или функции

        plMethodNum = -1
        Select Case bstrMethodName
            Case "methTest", "Тест"
                plMethodNum = Methods.methTest
            Case "methGetValue", "ПолучитьЗначение"
                plMethodNum = Methods.methGetValue
            Case "methSetValue", "УстановитьЗначение"
                plMethodNum = Methods.methSetValue
            Case "methClose", "Закрыть"
                plMethodNum = Methods.methClose
        End Select
    End Sub
(13) доделал, но один фиг толку 0
  '/////////////////////////////////////////////////////////////////////////////////
    Sub GetMethodName(ByVal lMethodNum As Integer, ByVal lMethodAlias As Integer, ByRef pbstrMethodName As String) Implements ILanguageExtender.GetMethodName
        'Здесь 1С (теоретически) получает имя метода по его идентификатору. lMethodAlias - номер синонима.
        pbstrMethodName = ""
        Select Case lMethodNum
            Case Methods.methTest
                pbstrMethodName = "methTest"
        End Select
    End Sub
19 alexkozin
 
20.10.15
21:21
Хожу отладчиком. Короче почему-то не заходит в методы FindMethod и т.д. В общем ооладчик не хотит ходить по методом интерфейса ILanguageExtender :(
20 ProgAL
 
20.10.15
21:28
У тебя ГУИД ком объекта ILanguageExtender должен быть точно таким как в шаблоек внешних компонент в примерах на диске ИТС. И у интерфейса IInitDone, IAsyncEvent, IStatusLine тоже.
21 ProgAL
 
20.10.15
21:29
Вероятно, причина именно в этом. 1с просто не видит твои интерфейсы, т к тыкается через кваериинтерфейс в предопределенные значения ГУИДов, а твои ГУИДы другие.
22 alexkozin
 
20.10.15
21:40
(21) Клянуся ГУИД как надо именно такой, с другим даже компонента не регится AB634003-F13D-11d0-A459-004095E1DAEA
:(
23 alexkozin
 
20.10.15
21:47
(21) + в метод RegisterExtensionAs-то нормально заходит.
24 alexkozin
 
20.10.15
21:49
Чудеса, ребята :(
25 Serginio1
 
20.10.15
21:55
А c_AddinName="vk_OLE"
26 Serginio1
 
20.10.15
21:56
ВК = Новый(ИмяВК);
27 Serginio1
 
20.10.15
21:58
Бери примеры и не мучайся.
28 alexkozin
 
20.10.15
21:59
(26) Ага, так и делаю. Создается нормально, отладчиком нормально ходит по интерфейсу IInitDone и по первому методу интерфейса ILanguageExtender "RegisterExtensionAs", но вот в остальные методы отладчик не идет почему-то. Осталось с помощью коллег выяснить почему)
(27) Будешь смеяться, но это пример))
29 alexkozin
 
20.10.15
22:00
(27) мне критично именно на VB.NET, а это как раз пример VB.NET
30 Serginio1
 
20.10.15
22:04
(29) А в чем разница? Можешь код сконвертировать.
31 Кирпич
 
20.10.15
22:15
(24) какие нафиг чудеса?! Просто понятия нет никпкого. Когда будет понятие, сам свои ошибки видеть будешь, а не искать их через мисту методом тыка.
32 Serginio1
 
20.10.15
22:16
30+ Берешь ILSpy выбираешь свой любимый VB и декомпилируешь.
33 Serginio1
 
20.10.15
22:18
28 Разницу видишь
ВК = Новый COMОбъект(ИмяВК);
и
ВК = Новый(ИмяВК);
34 Serginio1
 
20.10.15
22:20
(28) Не работающий вариант. А на будущее проще использовать 15. В ближайшем будущем прикручу автоматическую компиляцию врапера для обертки нетовских событий в комовские.
35 Кирпич
 
20.10.15
22:27
(33)не видит он.
36 Serginio1
 
20.10.15
22:49
(35) Да уж 5 дней уже страдает.
37 Сияющий в темноте
 
20.10.15
23:41
да
птсатель прозаек
сскачал шаблон а заполнить не смог
38 Сияющий в темноте
 
20.10.15
23:47
он там ещё и встр неправильно формирует
его нужно создавать а не копировпть
39 alexkozin
 
21.10.15
07:12
(31) у меня сейчас единственный вопрос остался, суть которого в следующем "почему отладчик не видит методов интерфейса ILanguageExtender кроме единственного 'RegisterExtensionAs'"
(37) По делу что-то будет сказано или забить уже мне?
(33) В примере от 1С был верхний вариант. В чем разница кроме того что написано по-разному?
40 Serginio1
 
21.10.15
08:13
(39) Потому, что 33. Разница большая
При ВК = Новый COMОбъект(ИмяВК) создается COMОбъект
А при ВК = Новый(ИмяВК)
Ищется ВК с зарегистрированным RegisterExtensionAs

Один вызов твоей ВК делается при ПодключитьВнешнююКомпоненту(ИмяВК);
41 alexkozin
 
21.10.15
08:27
(40) При ВК = Новый(ИмяВК) 1С вот такое говорит:
vk_OLE : Общий член "CreateObject" для типа "_ComObject" не найден..

При чем говорит при вызове метода. Инициализируется без ошибок.
42 Serginio1
 
21.10.15
08:46
Имя Вк должно быть
AddIn.vk_OLE
43 Serginio1
 
21.10.15
08:56
Чему у тебя равен c_AddinName
44 alexkozin
 
21.10.15
08:59
(43) Const c_AddinName As String = "vk_OLE"
45 Serginio1
 
21.10.15
09:00
А ИмяВК?
Вообще возьми любой рабочий пример и потихоньку его изменяй
46 alexkozin
 
21.10.15
09:03
(45) Имя ВК тоже такое же vk_OLE.
Фигня в том что на VB.NET нигде не могу найти нормального рабочего примера. Изначально именно так и хотел поступить, но куда ни ткнусь - везде облом.
47 MM
 
21.10.15
09:18
(34) А можно будет выкладывать проект на какой-нибудь бесплатный ресурс? А то, стармани не безграничные (
48 Serginio1
 
21.10.15
10:57
Да мне не жалко. Просто никому это не нужно. Я всегда кто попросит отправляю на поччту
49 Serginio1
 
21.10.15
10:59
(45) Берешь в руки ILSpy и декомпилируешь сборку в VB.
Проблемы невозможно решaть нa том же уровне компетентности, нa котором они возникaют. Альберт Эйнштейн