Имя: Пароль:
1C
1С v8
NetObjectToIDispatch45
0 San4opa
 
17.04.20
07:02
Добрый день

Хочу подключиться к веб сервису через оболочку "NetObjectToIDispatch45".
То есть не могу нигде найти аналог кода через NetObjectToIDispatch45 типа:

Определение = Новый WSОпределения(Объект.АдресСервера);
Прокси = Новый WSПрокси(Определение, Сервис.URIПространстваИмен,Сервис.Имя,Сервис.ТочкиПодключения[0].Имя);
1 oleg_km
 
17.04.20
14:10
Мне кажется ты не понял концепцию. Ты должен сделать промежуточную сборку на .NET с объектами прослойками используя мастер .NET, а потом используя NetObjectToIDispatch45 пользовать это в 1С
2 Serginio1
 
17.04.20
14:41
Олег привет!
В свое время писал что где и как API IE из 1с 7.7
3 Garykom
 
гуру
17.04.20
14:48
(2) Подскажи есть ли где то пример ВК 1С на чистом C (без классов C++ с их эмуляцией на C)
4 Serginio1
 
17.04.20
15:11
(2) Я особо то и не заморачивался. Брал их примеры. Но по большому то счету можно и самому сделать массив ссылок на методы типа VMT и передавать первым полем ссылку на неё. Там это несложно сделать.
5 Garykom
 
гуру
17.04.20
15:17
(4) Несложно это если C++ отлично знаешь как и C.

А я пытаюсь это на Golang через CGO, который может c-shared dll.
https://habr.com/ru/company/mailru/blog/324250/
6 Serginio1
 
17.04.20
15:45
Понятно https://ru.wikipedia.org/wiki/Таблица_виртуальных_методов
class IInitDoneBase
{
public:
    virtual ~IInitDoneBase() {}
    /// Initializes component
    /**
     *  @param disp - 1C:Enterpise interface
     *  @return the result of
     */
    virtual bool ADDIN_API Init(void* disp) = 0;
    /// Sets the memory manager
    /*
     * @param mem - pointer to memory manager interface.
     *  @return the result of
     */
    virtual bool ADDIN_API setMemManager(void* mem) = 0;

    /// Returns component version
    /**
     *  @return - component version (2000 - version 2)
     */
    virtual long ADDIN_API GetInfo() = 0;

    /// Uninitializes component
    /**
     *  Component here should release all consumed resources.
     */
    virtual void ADDIN_API Done() = 0;



};

Я же не помню первым идет адрес деструктора,потом адрес Init.


https://habr.com/ru/post/409565/
7 Garykom
 
гуру
17.04.20
16:19
(6) О спасибо, особенно за ссылочку на хабр про VMT
8 Serginio1
 
17.04.20
16:34
9 v77
 
17.04.20
16:56
(3) На инфостарте лет 5 валяются примеры на паскале. Только учти, что надо делать вариант для GCC (Linux) и для VC++(Windows). У GCC и VC++ оно там по разному устроено.
10 Serginio1
 
17.04.20
17:14
11 Serginio1
 
17.04.20
17:37
Ну и там же посмотри bindings.inc и init.inc
12 Serginio1
 
17.04.20
17:38
13 Garykom
 
гуру
17.04.20
17:49
(9) (10) Варианты на паскале я видел но нифига из них не понял.
Точнее понял что через перечислимые типы, записи и указатели на все это дело эмулируют VMT для C++.
Но как это повторить на чистом C не понял.
14 Garykom
 
гуру
17.04.20
17:50
(9) Каким то образом на Lazarus один код для NativeAPI и для Win и для Lin.
15 Serginio1
 
17.04.20
17:58
Давай по порядку
TAddInDefBaseVTable = record

    _Destructor: procedure(This: PAddInDefBase); cdecl;

    AddError: function (This: PAddInDefBase; wcode: cushort; const source: PWideChar; const descr: PWideChar; scode: clong): cbool; stdcall;

    Read: function (This: PAddInDefBase; wszPropName: PWideChar; pVal: P1CVariant; pErrCode: pculong; errDescriptor: PPWideChar): cbool; stdcall;

    Write: function (This: PAddInDefBase; wszPropName: PWideChar; pVar: P1CVariant): cbool; stdcall;

    RegisterProfileAs: function (This: PAddInDefBase; wszProfileName: PWideChar): cbool; stdcall;

    SetEventBufferDepth: function (This: PAddInDefBase; lDepth: clong): cbool; stdcall;

    GetEventBufferDepth: function (This: PAddInDefBase): clong; stdcall;

    ExternalEvent: function (This: PAddInDefBase; wszSource: PWideChar; wszMessage: PWideChar; wszData: PWideChar): cbool; stdcall;

    CleanEventBuffer: procedure (This: PAddInDefBase); stdcall;

    SetStatusLine: function (This: PAddInDefBase; wszStatusLine: PWideChar): cbool; stdcall;

    ResetStatusLine: procedure (This: PAddInDefBase); stdcall;

  end;

это на самом деле struct где каждое поле это указатель на функцию определенного типа
16 v77
 
17.04.20
18:10
(13) Ну прочитай книжку про Си и поймешь. За тебя никто этой ерундой заниматься всё равно не будет. Так что дерзай.
17 v77
 
17.04.20
18:13
18 San4opa
 
17.04.20
19:21
(1) А как сборку сделать?
19 Serginio1
 
17.04.20
19:37
20 San4opa
 
18.04.20
00:20
(19) Сборку сделал, дальше я так понимаю нужно подключиться к сервису типа:

врап=новый COMОбъект("NetObjectToIDispatch45");

    Service=Врап.ПолучитьТипИзСборки("???",ПутьКСборке);    
    // Create a webrequest with the specified URL.
    client = Врап.СоздатьОбъект(Service);
    client.Url = "???.svc";;

    cookieContainer = Врап.СоздатьОбъект("System.Net.CookieContainer");
            client.CookieContainer = cookieContainer;

Но я не совсем понимаю что вставлять в места где вопросы.
21 DES
 
18.04.20
10:11
Вот кусок кода рабочего (ну может внес ошибки при затирании личной инфы)


Результат = Неопределено;
    
    ФайлВрап = "NetObjectToIDispatch45";
    Попытка
        Врап = Новый COMОбъект(ФайлВрап);
        Врап.ВыводитьСообщениеОбОшибке = Ложь;
        Assembly = Врап.ТипКакОбъект(Врап.ПолучитьТип(ФайлВрап + ".GlobalContext1C")).Assembly;
    Исключение
        Assembly = Неопределено;
    КонецПопытки;
    Если НЕ Assembly=Неопределено Тогда
        ФайлВрап = Новый Файл(Assembly.Location);
        ПутьКФайлам = ФайлВрап.Путь;
        
        ИмяФайлаСборки = "Service_ТВОЯ.dll";
        ПространствоИмен = "Service_ТВОЯ.ServiceReference.";
        ИмяФайлаСборки = ПутьКФайлам + ИмяФайлаСборки;
        ФайлСборки = Новый Файл(ИмяФайлаСборки);
        Сборка_API = ФайлСборки.Существует();
        Если Сборка_API Тогда
            Попытка
                Тип_ServiceClient = Врап.ПолучитьТипИзСборки(ПространствоИмен + "ServiceClient", ФайлСборки.ПолноеИмя);
            Исключение
                Тип_ServiceClient = Неопределено;
            КонецПопытки;
        КонецЕсли;
        
        Если Тип_ServiceClient=Неопределено Тогда
            EF.ОбработкаОшибкиСlientE("Сервис API недоступен");
            Возврат Неопределено;
        Иначе
            Если ТипЗнч(_ПараметрыФункции)=Тип("Структура") Тогда
                #Область Сlient                            
                UserName = "НАМЕ";
                PassWord = "ПАСВОРД";  
                Http = "Http";
                BasicHttpBinding = Врап.ПолучитьТипИзСборки("System.ServiceModel.Basic" + Http + "Binding", "System.ServiceModel.dll");
                Binding = Врап.СоздатьОбъект(BasicHttpBinding, Врап.ПолучитьТип("System.ServiceModel.Basic" + Http + "SecurityMode").TransportWithMessageCredential);
                Binding.MaxBufferPoolSize = 1024 * 1024 * 2;
                Binding.MaxBufferSize = 1024 * 1024 * 1;
                Binding.MaxReceivedMessageSize = 1024 * 1024 * 1;
                Address = Врап.СоздатьОбъект("System.ServiceModel.EndpointAddress", "https://ТВОЙ.АДРЕС.РУ";);
                Попытка
                    СlientE = Врап.СоздатьОбъект(Тип_ServiceClient, Binding, Address);    
                    СlientE.ClientCredentials.UserName.UserName = ?(ПустаяСтрока(_UserName), UserName, _UserName);
                    СlientE.ClientCredentials.UserName.Password =  ?(ПустаяСтрока(_Password), PassWord, _Password);
                Исключение
                    EF.ОбработкаОшибкиСlientE(Врап.ПоследняяОшибка);
                    СlientE = Неопределено;
                КонецПопытки;
                #КонецОбласти            
                Если НЕ СlientE=Неопределено Тогда
                    EF.ОбработкаОшибкиСlientE(_ИмяФункции, УровеньЖурналаРегистрации.Информация);
22 San4opa
 
18.04.20
17:30
(21) Не могу понять какое пространство имен указывать, при сборке я указал пространство имен ServiceSpark,сама dll - Spark, то есть должно быть вот так:

Тип_ServiceClient = Врап.ПолучитьТипИзСборки("Spark.ServiceSpark.ServiceClient", ПутьКСборке);

Пробовал и в других вариациях, но везде пишет нет такого типа.
23 oleg_km
 
18.04.20
18:02
Наверное вот этот тип ServiceSpark.ServiceClient. Приведи namespace из исходников твоей сборки
24 San4opa
 
18.04.20
18:40
(23) Не подходит.

[System.ServiceModel.ServiceContractAttribute(Namespace="http://interfax.ru/ifax";, ConfigurationName="ServiceSpark.iFaxWebServiceSoap")]
25 Сияющий в темноте
 
18.04.20
19:33
таблица виртуальных функций-это просто указатель в начале обьекта и ее можно рассматртвать как void*
в ней каждая запись-это указатель на функцию,то есть тоже void*
типы и параметры функций определяются уже из описания класса или интерфейса
по совести говоря,в Си ++ нет интерфейсов,а есть только классы.
для обьектов со сложным наследованием в классе может быть несколько таблиц по одной для каждого класса.
на самом деле,сложное наследование-вещь в себе,так как для возможности приведения обьекта к родительским-задача не тривиальная,так как одно и то же поле может быть у разных родителей-в это случае,компиллятор также должен вместо поля размещать ссылкк на него в разных местах обьекта.
26 Сияющий в темноте
 
18.04.20
19:40
и вызов виртупльной функции обьекта-это очень просто:
((ObjectRefVar->lpVtbl)(ObjectVtblRef*))->pFunction(Object,Parameters...);
27 Serginio1
 
18.04.20
19:45
(24) Смотри наверху файла. Типа  
namespace xxx.ServiceSpark {
Твой класс скорее всего и будет xxx.ServiceSpark.iFaxWebServiceSoap  если конечно xxx. существует
28 oleg_km
 
18.04.20
22:52
(24) Namespace="http://interfax.ru/ifax";; - это совсем не то
29 San4opa
 
19.04.20
04:27
(28) другого нет
30 San4opa
 
19.04.20
04:34
(27) ServiceSpark.iFaxWebServiceSoap вроде тип нашел но при создании Объекта ошибка

Произошла исключительная ситуация (mscorlib): Конструктор для типа "ServiceSpark.iFaxWebServiceSoap" не найден.

в сборке что-то не так сделал?
31 Serginio1
 
19.04.20
13:51
Тебе Des там кучу кода предоставил

Для начала, стоит почитать http://catalog.mista.ru/public/448668/
что бы создать тип нужно сначала загрузить сборку  

Сборк= врап.ЗагрузитьСборку(ПутьКТвоейDll);
    
  Тип_iFaxWebServiceSoap = Сборка.GetType("ServiceSpark.iFaxWebServiceSoap");

либо
Тип_iFaxWebServiceSoap = Врап.ПолучитьТипИзСборки("ServiceSpark.iFaxWebServiceSoap", ПутьКТвоейDll);
32 Serginio1
 
19.04.20
13:59
Ну и если у тебя в конструкторе прописан адрес и биндинг можешь создать
Сlient = Врап.СоздатьОбъект(Тип_ServiceClient);

Можешь по биндигу и адресу
client = Врап.СоздатьОбъект(Тип_ServiceClient, Binding, Address);  


client = Врап.СоздатьОбъект(Тип_ServiceClient);
client.Url = url;
CookieContainer= Врап.ПолучитьТипИзСборки("System.Net.CookieContainer", "System.dll");
client.CookieContainer =  Врап.СоздатьОбъект(CookieContainer());
// Авторизация на сервисе. (должны быть включены cookies)
result = client.Authmethod(login, password);
33 Serginio1
 
19.04.20
14:02
Куки вроде можно просто создать Врап.СоздатьОбъект("System.Net.CookieContainer");
34 San4opa
 
19.04.20
17:58
(31) (33) Этот код я заметил ранее, спасибо.
client = Врап.СоздатьОбъект(Тип_ServiceClient); на этом месте ошибка.
Произошла исключительная ситуация (mscorlib): Конструктор для типа "ServiceSpark.iFaxWebServiceSoap" не найден.
С адресом, биндингом то же самое.
35 San4opa
 
19.04.20
18:14
(34) Такая ошибка если получать тип из сборки
SparkService = врап.ПолучитьТипИзСборки("ServiceSpark.iFaxWebServiceSoap",ПутьКСборке);

а если получать через загрузки сборки Сборка = врап.загрузитьСборку(ПутьКСборке); то пишет Произошла исключительная ситуация (NetObjetToIDispatch45): Ссылка на объект не указывает на экземпляр объекта.
36 Serginio1
 
19.04.20
18:46
То есть сборка неопределено?
Вообще положи сборку рядом с NetObjectToIDispatch45.dll
А вообще путь то валидный,
ФайлСборки = Новый Файл(ИмяФайлаСборки);

        Сборка_API = ФайлСборки.Существует();
37 Serginio1
 
19.04.20
18:49
Кинь кудани будь свою dll и дай ссылку
38 San4opa
 
19.04.20
19:19
39 Serginio1
 
19.04.20
20:06
ServiceSpark.iFaxWebServiceSoapClient
40 Serginio1
 
19.04.20
20:08
ServiceSpark.iFaxWebServiceSoap это интерфейс который реализует класс ServiceSpark.iFaxWebServiceSoapClient

client= врап.ПолучитьТипИзСборки("ServiceSpark.iFaxWebServiceSoapClient",ПутьКСборке);
41 San4opa
 
19.04.20
21:57
(40) ServiceSpark.iFaxWebServiceSoapClient: Произошла исключительная ситуация (mscorlib): Данное имя сборки или база кода недействительны. (Исключение из HRESULT: 0x80131047)
42 Serginio1
 
19.04.20
22:20
А вот здесь скорее всего проблема в том, что  NetObjectToIDispatch45.dll скомпилирована под .Net 4.6.1 а твоя сборка под .NETCoreApp,Version=v3.1

Проще выбрать проект "библиотека  классов .Net Framework"  и следующим шагом выбрать платформа 4.6.1
43 Serginio1
 
19.04.20
22:30
При поиске шаблона выбрать Язык-C# Платформа-Windows Тип проекта библиотеак

Выбрать Библиотека классов (.Net Framework)
44 Serginio1
 
19.04.20
22:36
Или в проекте Целевая Рабочая среда поменять на
.Net Framework 4.6.1
https://docs.microsoft.com/ru-ru/visualstudio/ide/visual-studio-multi-targeting-overview?view=vs-2019
45 San4opa
 
20.04.20
01:50
(44) Пересоздал, но пока все равно ошибка

Если пишу так

SparkService = врап.ПолучитьТипИзСборки("SparkObmen.ServiceSpark.iFaxWebServiceSoapClient",ПутьКСборке);
client = Врап.СоздатьОбъект(SparkService);

пишет Произошла исключительная ситуация (mscorlib): Адресат вызова создал исключение.

Если так

    BasicHttpBinding = Врап.ПолучитьТипИзСборки("System.ServiceModel.BasicHttpBinding", "System.ServiceModel.dll");
    Binding = Врап.СоздатьОбъект(BasicHttpBinding, Врап.ПолучитьТип("System.ServiceModel.BasicHttpSecurityMode").TransportWithMessageCredential);
    Address = Врап.СоздатьОбъект("System.ServiceModel.EndpointAddress","http://sparkgatetest.interfax.ru/iFaxWebService/iFaxWebService.asmx";);     
    client = Врап.СоздатьОбъект(SparkService, Binding, Address);    
        client.Authmethod(Объект.Логин,Объект.Пароль);

То пишет вот что: https://drive.google.com/file/d/1e9QMgqJ8ixfN-4-5k5SYywAeiVQlX3nB/view?usp=sharing
46 San4opa
 
20.04.20
01:54
47 Serginio1
 
20.04.20
11:23
врап=новый COMОбъект("NetObjectToIDispatch45");
SparkService = врап.ПолучитьТипИзСборки("SparkObmen.ServiceSpark.iFaxWebServiceSoapClient",ПутьКСборке);
BasicHttpBinding = Врап.ПолучитьТипИзСборки("System.ServiceModel.BasicHttpBinding", "System.ServiceModel.dll");

    Binding = Врап.СоздатьОбъект(BasicHttpBinding);

    Address = Врап.СоздатьОбъект("System.ServiceModel.EndpointAddress","http://sparkgatetest.interfax.ru/iFaxWebService/iFaxWebService.asmx";);    

    client = Врап.СоздатьОбъект(SparkService,Binding,Address);
48 San4opa
 
20.04.20
16:23
(47) Всё получилось спасиба!!!
49 DES
 
20.04.20
18:10
(48) 47+ и от меня тоже. ;)
50 Serginio1
 
20.04.20
18:20
На здоровье! И вам спасибо, что мои труды не пропадают
51 San4opa
 
01.06.20
23:43
(50) Добрый день

Подскажите еще пожалуйста вопрос есть:

пробую отправить запрос на сервер с Basic auth

Написал код, но сервер ничего не отвечает, мне кажется с авторизацией что-то не так делаю.

        uriSources = Объект.АдресСервера+"/score/sync";
    requestUri = "";
    
    NetObject = Новый COMОбъект("NetObjectToIDispatch45");
    HttpClient = NetObject.ПолучитьТипИзСборки("System.Net.Http.HttpClient","System.Net.Http.dll");
    HttpClientHandler = NetObject.ПолучитьТип("System.Net.Http.HttpClientHandler");
    handler = NetObject.СоздатьОбъект(HttpClientHandler);
    
    NetworkCredential = NetObject.СоздатьОбъект("System.Net.NetworkCredential");
    NetworkCredential.UserName = Объект.Логин;
    NetworkCredential.Password = Объект.Пароль;
    
    handler.Credentials = NetworkCredential;
    handler.UseDefaultCredentials = Истина;
    Client = NetObject.СоздатьОбъект(HttpClient,handler);
    
    uri = NetObject.СоздатьОбъект("System.Uri",uriSources);
    Client.BaseAddress = uri;
    Данные = Новый Структура();
    
    Данные.Вставить("inn","6140038703");
    
    СтрокаJSON = Плейн_РаботаСHTTP.ПолучитьСтрокуJSON(Данные);
    ПараметрыЗапросаNetObject = NetObject.ОбернутьЛюбойОбъект(СтрокаJSON);

    StringContent = NetObject.ПолучитьТип("System.Net.Http.StringContent");
    Контент = NetObject.СоздатьОбъект(StringContent,ПараметрыЗапросаNetObject);

    Результат = Client.PostAsync(requestUri,Контент).Result;    
    //Result = Результат.Content.ReadAsStringAsync().Result;
Кaк может человек ожидaть, что его мольбaм о снисхождении ответит тот, кто превыше, когдa сaм он откaзывaет в милосердии тем, кто ниже его? Петр Трубецкой