Имя: Пароль:
1C
1С v8
Кроссплатформенное использование классов .Net в 1С через Native ВК.
0 Serginio1
 
04.07.16
13:58
Или замена COM на Linux
Выложил статью http://catalog.mista.ru/public/534901/
С выходом .Net Core CLR стало возможным использование классов .Net не только на Windows, но и других операционных системах.
Это особенно важно в разрезе импортозамещения. И главное - это аналог COM под Linux.
Сейчас под Linux для расширения возможностей 1С используются Web сервисы. Данная разработка позволит использовать не только сборки входящие в состав .Net Core, но и пользовательские портативные сборки.
Являясь автором v8: v8: Использование сборок .NET в 1С 7.x и 8.x и Создание внешних Компонент, я часто слышал в свой адрес, что это все туфта, ибо не кроссплатформенна.  Кроме того, под Windows полно готовых COM библиотек и несложно сделать свои COM библиотеки на разных языках. Для Linux ситуация сложнее. Там нет COM, а технология .Native API не слишком-то и дружелюбна.

Выводы о недостатках 1С реализации Технологии Внешних Компонент.

1. Абсолютно не нужны методы FindMethod, FindProp, IsPropReadable, IsPropWritable, GetNParams, HasRetVal, GetParamDefValue

Так как у методов

bool CallAsProc

bool CallAsFunc

bool SetPropVal и bool GetPropVal есть возвращаемое значение об успешном выполнении

Информация об ошибке возвращается через AddError.

Да и вызов по индексу это анахронизм от IDiapatch, где было описание диспинтерфейсов для увеличения скорости вызова.

2. При возвращении методами SetPropVal и GetPropVal исключение не вызывается

3. Зачем-то происходит установка свойств там, где в коде этого не требуется.

4. Вызывается метод как функция там, где метод вызывается как процедура.

5. Один из основных - это нельзя вернуть и передать экземпляр ВК из методов ВК.

Я лично не вижу никаких проблем. Определить значение для такого типа и установить ссылку в поле pInterfaceVal.

Подсчет ссылок происходит на стороне 1С. Передавать можно в том числе и объекты 1С только на время вызова метода.

В дальнейшем можно развить до использования событий объектов .Net в 1С по примеру Динамическая компиляция для использования .Net событий в 1С

Использовать асинхронные вызовы по примеру .Net в 1С. Парсинг сайтов, multipart/form-data, gzip итд

Вообще интеграция .Net есть в Microsoft Dynamics AX ClrObject.

Используя кроссплатформенный Core Clr, можно интегрировать в 1С. Особенно это актуально для Linux как импортозамещения.

Пока проверил, работает на Windows 7,10. Linux и IOS пока нет, но в скором проверю на виртуальной машине. .Net Core CLR можно скачать здесь

С чем я бы с удовольствием помог 1С. Есть огромный опыт использования классов .Net в 1С.
84 oleg_km
 
05.07.16
11:59
(82) Ты не понял самого главного. Если мне нужно задействовать в 1С объект дотнет с десятком методов, то по твоему способу мне придется тупо в своей ВК продублировать все эти десятки методов. А используя как Сергей рефлексию мне ничего этого делать не надо. Я ни сточки не меняю в dll, практически все изменения на стороне 1С.
85 Это_mike
 
05.07.16
12:00
Честно говоря, я нипанимаю, ап чём ср@ч?
чувак дал возможность. использовать ее или нет - дело каждого.
Да, смешно, когда он толкает в каждую дырку свой .Нет, но это всяко лучше эфирокачков...
86 Кирпич
 
05.07.16
12:02
(84)  "тупо в своей ВК продублировать все эти десятки методов"
да не нужно это. обычно хватает пары методов типа. не обязательно в код 1с пихоть всё. достаточно сделать ВК с парой функций, а остальное варится в ВК. Я за такой метод.
87 Кирпич
 
05.07.16
12:03
(85) это ср@ч ради ср@ча
88 Это_mike
 
05.07.16
12:03
(87) тады ой.
89 Кирпич
 
05.07.16
12:04
(88) популяризируем решения микрософта. импортозамещение же.
90 Это_mike
 
05.07.16
12:06
(89) "попу ляризируете"? Это как? Это наказуемо, или похвально?
91 Кирпич
 
05.07.16
12:06
(90) решай сам
92 Serginio1
 
05.07.16
12:07
(86) Так сделай человеку. Ты уже больше 2 минут пишешь в этой ветке.
(83) То есть в итоге идея хорошая, но реализована не тем человеком. И этот человек отстой, ибо ...
(87) Меня конечно поражает, то что главное ср@ча, вместо продуктивной критики.

Еще раз про ВК. Я не писал ни одной строчки, а вот тебе придется определить классы, методы итд. И 10 строчками там не обойтись
93 Кирпич
 
05.07.16
12:10
(92) " Я не писал ни одной строчки" а кто тогда писал? тот чувак?
94 Serginio1
 
05.07.16
12:12
95 Кирпич
 
05.07.16
12:12
(92)"Так сделай человеку. Ты уже больше 2 минут пишешь в этой ветке."
ну возьми сам и сделай. или покажи чего ты ему написал за 2 минуты. хотя ты не писал.
96 Serginio1
 
05.07.16
12:13
94+ добавить ссылку на службу. И классы генерятся автоматически в VS.
97 Кирпич
 
05.07.16
12:14
(96) а после того как классы сгенерятся ничего писать в 1С не нужно? оно сразу работает?
98 Serginio1
 
05.07.16
12:14
Кирпич ты меня удивляешь. Вроде же с .Net знаком и WCF клиентом тоже. Ты либо придуряешься либо ...
99 Кирпич
 
05.07.16
12:16
(98) я хочу увидеть что ты в 1с ниписал
100 Serginio1
 
05.07.16
12:16
(97) Ничего писать в ВК не надо. Писать в 1С придется не зависимо от того на чем написана компонента. На Com, ВК или чистом .Net.
Мы говорим о простоте написания ВК
101 Serginio1
 
05.07.16
12:17
102 Serginio1
 
05.07.16
12:17
(99) Ты с вэб сервисами не работал? То же самое
103 Кирпич
 
05.07.16
12:20
(102) ну покажи ваш код, который работает. чего ты стесняешься.
104 Кирпич
 
05.07.16
12:21
+(103) я хочу увидеть этого горбатого крокодила
105 Кирпич
 
05.07.16
12:22
блин. глянул. у нас всего два зрителя. чего я так разоряюсь тут :(
106 Serginio1
 
05.07.16
12:31
(105) А если бы 1С интегрировала, то этим бы пользовалась куча 1С ников. Только и всего.
107 Кирпич
 
05.07.16
12:46
(106) да не будет там кучи одинесников. у среднестатистического одинесника раз в год может появится какая нибудь задача типа молдавских фактур и он её решит любым способом, который ему доступен.
Кстати, а 1с умеет генерить код для вебсервисов как VS? Может забабахаешь такую генерилку?
108 Serginio1
 
05.07.16
12:56
(107) Та WsСсылка это оно и есть.
Там решать сложно. Там верификация подписи итд.
А решение через .Net 2 минуты без единого строчки кода. А на 1С количество кода даже будет меньше, чем при использовании родных WSОпределение, прокси итд
109 Serginio1
 
05.07.16
16:05
Кстати по новой методе стало возможным работать  с динамическими классами, через https://github.com/ekonbenefits/dynamitey/wiki/UsageReallyLateBinding#introduction

Например с популярной библиотекой Newtonsoft.Json
http://www.newtonsoft.com/json/help/html/QueryJsonDynamic.htm

В том числе с DynamicObject и ExpandoObject.
Можно использовать методы расширения, Generic методы, где типы определяются по параметрам.
Можно задавать русские имена для методов определенных типов.
110 Serginio1
 
07.07.16
15:58
Добавил поддержку объектов с поддержкой IDynamicMetaObjectProvider

Для теста создад ExpandoObject

  public object ПолучитьExpandoObject()
        {

            dynamic res = new ExpandoObject();
            res.Имя = "Тест ExpandoObject";
            res.Число = 456;
            res.ВСтроку = (Func<string>)(() => res.Имя);
            res.Сумма = (Func<int, int, int>)((x, y) => x + y);

            return res;
        }




И наследника DynamicObject

class TestDynamicObject : DynamicObject
    {

        public override bool TrySetMember(SetMemberBinder binder, object value)
        {

            return true;
        }
        // получение свойства
        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            result = binder.Name;
            return true;
        }
        // вызов метода
        public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
        {
            var res = new StringBuilder("{0}(");
            var param = new object[args.Length + 1];
            param[0] = binder.Name;
            if (args.Length > 0)
            {
                Array.Copy(args, 0, param, 1, args.Length);
                for (int i = 0; i < args.Length; i++)
                {
                    res.AppendFormat("{{{0}}},", i + 1);

                }

                res.Remove(res.Length - 1, 1);

            }
            res.Append(")");

            result = String.Format(res.ToString(), param);
            return true;


        }
    }




Теперь можно вызвать на 1С

Тестовый=ъТип("TestDllForCoreClr.Тестовый, TestDllForCoreClr, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null");
    Тест=ъ(Врап.Новый(Тестовый.ПолучитьСсылку()," Свойство из Конструктора"));
    
    // Это аналог структуры, но с поддержкой методов
    РасширяемыйОбъект=ъ(Тест.ПолучитьExpandoObject());
    
    Сообщить("ВСтроку="+РасширяемыйОбъект.ВСтроку());
    Сообщить("Сумма=" + РасширяемыйОбъект.Сумма(1, 2));
    
    Сообщить(РасширяемыйОбъект.Имя);
    Сообщить(РасширяемыйОбъект.Число);
    
    РасширяемыйОбъект.Имя="Новое Имя";
    РасширяемыйОбъект.Число=768;
    // Добавим новое свойство
    РасширяемыйОбъект.НовоеСвойство="Новое Свойство";
    
    Сообщить(РасширяемыйОбъект.Имя);
    Сообщить(РасширяемыйОбъект.Число);
    Сообщить(РасширяемыйОбъект.НовоеСвойство);
    
    НовыйРеквизит=ъ(Врап.Новый("System.Dynamic.ExpandoObject, System.Dynamic.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"));
    
    НовыйРеквизит.Имя="Новый Реквизит";
    НовыйРеквизит.Значение=123;
    
    
    РасширяемыйОбъект.НовыйРквизит=НовыйРеквизит.ПолучитьСсылку();
    Сообщить(ъ(РасширяемыйОбъект.НовыйРквизит).Имя);
    
    
    TestDynamicObject=ъТип("TestDllForCoreClr.TestDynamicObject, TestDllForCoreClr, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null");
    
    ДинамикОбъект=ъНовый(TestDynamicObject.ПолучитьСсылку());
    ДинамикОбъект.УстановимЛюбоеСвойство="Чего то там";
    Сообщить( ДинамикОбъект.ПолучитТоЧтоПередали);
    Сообщить(ДинамикОбъект.ПолучитТоЧтоПередалиСПараметрами(1,3.45,ТекущаяДата()));





Это удобно при работе с различными парсерами
111 Serginio1
 
13.07.16
15:43
Добави вывод типов для дженерик методов
Теперь можно не выводить отдельно метод


// public T ДженерикМетод<V, T>(V param1, T param2, V param3)
Сообщить(Тест.ДженерикМетод(1,"Привет",3));
//

//public V ДженерикМетод2<K, V>(Dictionary<K, V> param1, K param2, V param3)
Словарь= ъНовый("System.Collections.Generic.Dictionary`2[System.Int32,System.String]");
Сообщить(Тест.ДженерикМетод2(Словарь.ПолучитьСсылку(),3,"Привет2"));

// public K ДженерикМетод3<K>(IList<K> param1, int param2, K param3)
List=ъНовый("System.Collections.Generic.List`1[System.String]");
Сообщить(Тест.ДженерикМетод3(List.ПолучитьСсылку(),3,"Привет3"));
112 Serginio1
 
19.07.16
14:45
Сделал поддержку внешнего события
В классе создадим пле типа Action<string, string, string>

public class Тестовый
    {
      public Action<string, string, string>

ВнешнееСобытие1С;

// И сделаем эмуляцию события.

public async void TestВнешнегоСобытия()
        {

            for(int i=0;i<100; i++)
            {
                var значение = i.ToString();
                Task.Run(async() =>
                {
                   await Task.Delay(1000).ConfigureAwait(false);
                   this?.ВнешнееСобытие1С("Тестовый", "ТестовоеСообщение", значение);
                });

                await Task.Delay(50).ConfigureAwait(false);
            }

        }

В 1С.

Процедура ВнешнееСобытие(Источник, Событие, Данные)
    // Вставить содержимое обработчика.
    
    Сообщить("Источник="+Источник);
    Сообщить("Событие="+Событие);
    Сообщить("Данные="+Данные);
КонецПроцедуры

Процедура ТестВнешнегоСобытияНажатие(Элемент)
    // Вставить содержимое обработчика.
    Тестовый=ъТип("TestDllForCoreClr.Тестовый, TestDllForCoreClr, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null");
Тест=ъ(Врап.Новый(Тестовый.ПолучитьСсылку()," Свойство из Конструктора"));

Делегат=Ъ(Врап.ПолучитьДелегатВнешнегоСобытия1C());
Тест.ВнешнееСобытие1С=Делегат.ПолучитьСсылку();
Тест.TestВнешнегоСобытия();
КонецПроцедуры

И не забыть в Переменных модуля установить
Перем   Тест;
113 Serginio1
 
19.07.16
14:50
Интересное заключается в том, что например если установить
static IMemoryManager *Current_IMemoryManager = nullptr;

Из одного объекта
Current_IMemoryManager = self->m_iMemory;

А вызывать из другого, то попадаем на ошибку памяти.
Поэтому

Приходится устанавливать текущий объект
void BaseNetObjectToNative::SetMemoryManager()
    {
        // Установим в статическое поле текущий объект для вызова
        // GetMem и AddError
        pCurrentObject=this;
    }


и вызов

void * LoaderCLR::GetMem(long ByteCount)
    {
        byte* res = 0;
            

        auto rez= BaseNetObjectToNative::pCurrentObject->m_iMemory->AllocMemory((void**)&res, ByteCount);
    //    auto rez = Current_IMemoryManager->AllocMemory((void**)&res, ByteCount);
            if (rez) memset(res,0, ByteCount);

        return (void*)res;
    }
114 Serginio1
 
19.07.16
14:52
И соответственно при вызове внешнего события используется менеджер памяти последнего объекта у которого был вызван метод.
115 Serginio1
 
21.07.16
14:46
В VS 2015 апдейт 3 появилась возможность создавать библиотеки и приложения под .Net Core
Вкладка
Шаблоны->Windows->.Net Core

Такой проект отличается от портативного.
В тестах добавил пример создания JObject и сериализации его в Json
116 Serginio1
 
21.07.16
15:03
Про установку SDK и прочее можно посмотреть здесь
http://metanit.com/sharp/aspnet5/1.2.php
117 Serginio1
 
22.07.16
15:01
Понял почему свойства присваиваются

Например
Функция Ъ(знач Ссылка)
    
    // Создаем объект по ссылке полученной из методов .Net классов
    //Физически это строка ёЁ<Ьъ>№_%)Э?&2 содержащее 12 символов для отделения их от других строк
    //и индекс в спике исполуемых объектов на стороне .Net

    рез = Новый("AddIn.NetObjectToNative.NetObjectToNative");
    // И установим ссылку
    рез.УстановитьСсылку(Ссылка);    
    возврат  рез
КонецФункции // СоздатьОбъектПоСсылке()


И если вызвать без Знач
Зазача=ъ(Список.Current);

То 1С предполагает, что Список.Current может измениться внутри метода и присваивает значение, так как по ссылке не может передать.

Или же делать так, если методы изменить нельзя

Стр=Список.Current;
Зазача=ъ(Стр);
118 Serginio1
 
27.07.16
15:16
Добавил поддержку параметров по умолчанию

// Тест вызова метода с параметрами по умолчанию
    
    //public static int OptionalParam(int x, int y, int z = 5, int s = 4,string str="Привет")
    //       {
    //           return x + y + z + s;
    //       }
    

    //public static int OptionalParam(int x, int y, int z = 5, int s = 4,string str="Привет")
    Сообщить("OptionalParam(int x, int y)="+Тестовый.OptionalParam(1,2));
    Сообщить("OptionalParam(int x, int y, int z = 5)="+Тестовый.OptionalParam(1,2,3));
    Сообщить("OptionalParam(int x, int y, int z = 5, int s,string str)="+Тестовый.OptionalParam(1,2,3,4,"ХаХа"));
119 _stay true_
 
25.08.16
10:44
(118) А можно пример кода по подключению к другой базе и выполнения прямого запроса?
120 Garykom
 
гуру
25.08.16
10:57
(119) Уточни какой базе и каким образом подключения если другая база без сервера и ни одной копии предприятия другой базы не запущено?
121 _stay true_
 
25.08.16
10:59
(120) База клиент-серверная, вертится на PostgreSQL на линухе. Один её экземпляр запущен всегда(робот обмена).
122 _stay true_
 
25.08.16
11:01
(121) Либо можно сразу прямой запрос к SQL. Так вытаскиваем данные из СБИСа и Аксапты
123 Garykom
 
гуру
25.08.16
11:02
(122) ты изобрел 1С++ и прямые запросы для 77
124 _stay true_
 
25.08.16
11:06
(123) Неа))

Просто реально интересно возможно ли с помощью данной разработке выполнить аналогичный код:
СтрокаПодключения =
"Provider=SQLOLEDB.1;
|User ID=com1c;
|Pwd=********;
|Data Source=Имя_сервера_SQL;
|Initial Catalog= testDB";//наша database

Connection  = Новый COMОбъект("ADODB.Connection");
Command  = Новый COMОбъект("ADODB.Command");
RecordSet  = Новый COMОбъект("ADODB.RecordSet");

Попытка
  Connection.Open(СокрЛП(СтрокаПодключения));
  Command.ActiveConnection   = Connection;
  //Проверка на наличие нашей database
  Command.CommandText = "select * from database'";
  RecordSet = Command.Execute();
  
  Если RecordSet.EOF() Тогда
   //наш обработчик;
  
  КонецЕсли;
125 Garykom
 
гуру
25.08.16
11:10
(124) Легко
126 _stay true_
 
25.08.16
11:11
(125) Можете привести конкретный пример 1С-ного кода?
127 Garykom
 
гуру
25.08.16
11:23
128 Garykom
 
гуру
25.08.16
11:24
(127)+ штука ТС из (0) позволяет переписать код на 1С с ВК
129 _stay true_
 
25.08.16
11:40
(128) Спасибо за на водку:)
130 Serginio1
 
25.08.16
11:45
(124) Сейчас в другой ветке спрашивали. Можно

Вот SQL запрос к MS SQL




    СборкаSqlClient=ъ(Врап.Сборка("System.Data.SqlClient.dll"));
    SqlConnection=ъ(СборкаSqlClient.GetType("System.Data.SqlClient.SqlConnection"));
    SqlCommand=ъ(СборкаSqlClient.GetType("System.Data.SqlClient.SqlCommand"));
    
    connection =ъ(Врап.Новый(SqlConnection.ПолучитьСсылку(),ConnectionString));
    connection.Open();
    
    ТекстЗапроса = "Select Номенклатура.DESCR Наименование  From sc84 Номенклатура where DESCR Like '%'+@Строка+'%'
    |order by Номенклатура.DESCR";
    
    
    command = ъ(Врап.Новый(SqlCommand.ПолучитьСсылку(),ТекстЗапроса,connection.ПолучитьСсылку()));
    
    Parameters=ъ(command.Parameters);
    Parameters.AddWithValue("@Строка", "ДСП");
    dr = ъ(command.ExecuteReader());
    
    Пока dr.Read() Цикл
        Сообщить(dr.get_Item("Наименование"));
    КонецЦикла;
131 Serginio1
 
25.08.16
11:47
Кроме того есть EF и отдельные пакеты например
https://github.com/SapientGuardian/mysql-connector-net-netstandard

http://www.npgsql.org/doc/coreclr.html
132 hitodom
 
25.08.16
11:50
(130) а нельзя сраз0у возвращить из нет, результат функции Ъ
133 Serginio1
 
25.08.16
12:13
Я в шапке и в первом сообщении описал почему
1С Linux. Что не хватает по сравнению с Windows?

Так как в Native API нельзя возвращать и передавать объекты то приходится передавать и возвращать строку. А оборачивать объект через функцию ъ (аналог $ в JQuery) и передавать строку используя метод ПолучитьСтроку().
134 _stay true_
 
25.08.16
13:01
(130) Прошу прощения за блондинистость. Только начал изучать эту тему и вашу разработку. Если я всё правильно понял, мне нужно скачать .NetCore, Ваши файлы с яндекс диска и сделать обработку с представленным Вами кодом?
135 Serginio1
 
25.08.16
13:07
(134) В файлах есть и .Net Core он в папке bin
136 Serginio1
 
25.08.16
13:09
Пути учитывают местоположение отчетов и относительно него передают нужные пути при создании ВК

Процедура ПриОткрытии()
    
    // Установим отчет рядом с  AddInNetObjectToNative.dll
    // NetObjectToNative.dll
    // и библиотеками  Microsoft.NETCore.App\1.0.0\    
    // Так как нужны 32 разрядные так как клиент 1С 32 разрядный
    // Скачать можно здесь https://github.com/dotnet/cli
    // На сервере можно использовать 64 разрядную Core Clr
    
    Файл=Новый Файл(ЭтотОбъект.ИспользуемоеИмяФайла);  
    КаталогОтчета=Файл.Путь;    
    
    ИмяФайла=КаталогОтчета+"\AddInNetObjectToNative.dll";
    
    ПодключитьВнешнююКомпоненту(ИмяФайла, "NetObjectToNative",ТипВнешнейКомпоненты.Native);
    Врап = Новый("AddIn.NetObjectToNative.LoaderCLR");
    CoreClrDir=КаталогОтчета+"\bin\";
    ДиректорияNetObjectToNative=КаталогОтчета;
    
    СсылкаНаДомен=Врап.СоздатьОбертку(CoreClrDir,ДиректорияNetObjectToNative,"");
    Врап.ЗагрузитьDLL(ИмяФайла);
    
    
КонецПроцедуры
137 _stay true_
 
25.08.16
13:11
(136) Спасибо Вам большое за пояснения! Пойду разбираться :)
138 romix
 
25.08.16
22:31
(136) Вопрос наверное к ув. Serginio1, хочу все-таки доразобраться со своими ВК, а то я забросил свою тему и так ее и не добил...
Хочу найти образец внешней компоненты с событиями для управляемых форм 8.3
139 Torquader
 
26.08.16
00:08
Вы лучше скажите - в типах внешних компонент есть такое определение:
enum AddInComponentType
{
    eAddInCom = 1,
    eAddInNative,
    eAddInJava,
    eAddInvalid = -1
};
Что предполагает, что внешние компоненты могут быть написаны на Java - это как - только мечта или есть какие-то сподвижки ?
140 Serginio1
 
26.08.16
00:13
(139) Native API только натив. Но можно сделать порт, аналогичный COM. То есть доступ к статическим методам.
141 Torquader
 
26.08.16
00:21
Просто, в описании Native API и структуры VARIANT есть заготовка под интерфейс - есть подозрение, что можно попробовать передать объект.
142 Serginio1
 
26.08.16
00:26
(141) Пробовал. Плохой тип переменной.
143 Serginio1
 
26.08.16
00:27
Даже Двоичные данные ты можешь вернуть, а вот передать в параметрах - нет
144 Jija Grenkov
 
26.08.16
00:29
Читал, что на java можно запилить ком объект. http://www.rgagnon.com/javadetails/java-0045.html
На как по мне профита от ком объекта мало учитывая заморочки с регистрацией. Если бы была возможность писать native vk
145 Torquader
 
26.08.16
00:36
(144) COM-объект никак не соотносится с 1С.
Готовый объект мы также можем дёргать из 1С, но передать ему объекты 1С невозможно.
146 Torquader
 
26.08.16
00:38
Кстати, написано, что события на сервере не поддерживаются - а тогда зачем вообще внешняя компонента нужна ?
147 Serginio1
 
26.08.16
00:42
(145) В COM объект мы можем передавать любые объекты 1С.
http://catalog.mista.ru/public/466196/
внизу заполнение ТаблицыЗначений в объектн на C#.

http://catalog.mista.ru/public/457898/
ВК мы можем передать ссылку на модуль и вызвать его методы
148 MM
 
26.08.16
08:56
(143) Обещают исправить.
Изменения в технологии внешних компонент NativeAPI
https://wonderland.v8.1c.ru/blog/rasshirenie-funktsionalnosti-raboty-s-dvoichnymi-dannymi/
149 Serginio1
 
26.08.16
11:04
(148) Спасибо. Самое смешное, что все это можно делать через .Net через COM. Для кроссплатформенного нужно сделать возможность передачу в параметрах ВК и возврат ВК. И все необходимые вещи уже там есть.
Мне очень жаль мою разработку. Это мой ребенок. Очень не хочется, что бы он умирал.
150 _stay true_
 
26.08.16
13:39
(149) Пока есть те, кто хотят уйти на линух целиком и полностью - будет жить:)
151 Serginio1
 
26.08.16
14:42
(150) Так и это все есть
1С, Linux, Excel, Word, OpenXML,ADO и Net Core
https://habrahabr.ru/post/308216/

Просто для того, что бы избавиться от ъ нужно немного модифицировать Native API
152 _stay true_
 
29.08.16
09:33
(136) Снова вопрос к Вам или "Возвращение блондинки":)

Почитал статьи, поизучал обработки(скачал ваш архив с ЯД), попробовал  написать свою обработку на УФ, на "базе одной из Ваших, которая бы подрубалась к SQL напрямую и выполняла запрос. Строку подключения и запрос взял из аналогичной виндовой обработки, работоспособность запроса и строки подключения 100%(самописный робот обмена вертится 24/7). Тестирую на чистой клиент-серверной базе(на сервере на базе WinSrv 2012 R2, MS SQL 2012 R2 под админом по РДП). Полный код обработки:




Перем   Врап,СсылкаНаДомен,ИмяСборкиAngleSharp;
Перем String,ExpandoObject,Environment;
Перем Cell,SharedString;
Перем ШаблонКолонки,ШаблонСтроки;
Перем NewLine,Таб;

&НаСервере
Процедура прочитатьSQLНаСервере()
СборкаSqlClient=ъ(Врап.Сборка("System.Data.SqlClient.dll"));
SqlConnection=ъ(СборкаSqlClient.GetType("System.Data.SqlClient.SqlConnection"));
SqlCommand=ъ(СборкаSqlClient.GetType("System.Data.SqlClient.SqlCommand"));
ConnectionString = "DRIVER={SQL Server};SERVER=server2k,1521;DATABASE=axapta;UID=sa;PWD=sa";
connection =ъ(Врап.Новый(SqlConnection.ПолучитьСсылку(),ConnectionString));
connection.Open();
    
ТекстЗапроса = "select b.invoiceid, b.documentdate, b.invoiceamount, b.invoiceaccount, r.rcontractnumber, b.dimension4_ as status, c.salespoolid as poolid, ed.dimension4 as serialstatus, (case when e.inventcompanyid <> b.dataareaid then 1 else 0 end) as commission,
|t.itemid, t.fullname, d.inventserialid, f.FacturedQty_RU as qty,
|case when f.FacturedQty_RU <> 0 then (f.lineamount+f.lineamounttax)/f.FacturedQty_RU else 0 end as price,
|sp.PurchasingPriceTax as PurchasingPrice,'' as DirectDeliveryName,
|f.lineamount, g.taxitemgroup, f.lineamounttax, d.inventgtdid_ru, v.name as gtdcounrty, g.inventrefid, h.INN_RU as INN, h.INN_Main
|, 0 as transtype, case when f.lineamount < 0 then 0 else 1 end as statusissue, case when f.lineamount < 0 then 1 else 0 end as statusreceipt
|,t.vital, t.qtyaccounting, t.stronggroup, h.accountnum, 0 as vend, h.phone, h.address, f.dimension, f.dimension2_, f.dimension3_, f.dimension4_, f.dimension5_, f.dimension6_, f.dimension7_, i.haggle as  haggle
|,k.externalnumber as externalnum, k.externaldate, h.KPP_RU as KPP
|,case when f.lineamount < 0 then g.inventrefid else NULL end as refinvoiceid
|,case when f.lineamount < 0 then (select top 1 documentdate from custinvoicejour where dataareaid IN ('тк') and invoiceid = g.inventrefid) else null end as refinvoicedate,
|case when h.AdditionCompany = 'FMS' then 'FMS' else case when h.AdditionCompany = 'CTR' then 'CTR' else case when h.AdditionCompany = 'YUG' then 'YUG' else '' end end end as OrgUTII,
|h.AdditionCompanyDate as DateAddOrgUTII,
|case when (c.purchorderformnum<>'' and c.purchorderformnum is not null) and (c.customerref<>'' and c.customerref is not null) then '1' else '0' end as DirectDelivery,
|sp.taxitemgroup as Purchasing_taxitemgroup, rcta.startdate as StartDateUGII, vei.DeliveryDate as DirectDeliveryDate,
|vcase when f.FacturedQty_RU > 0 then isnull((select max(ct.additioncompany) from CustClaimDrugstore ccd, custtable ct where ccd.DrugstoreSrc<>'' and ccd.DrugstoreSrc = ct.accountnum and ccd.SalesIdRef = c.salesid and ccd.dataareaid = 'тк' and ct.dataareaid = 'zgc'),0) else
|isnull((select max(ct.additioncompany) from CustClaimDrugstore ccd, custtable ct where ccd.DrugstoreDst<>'' and ccd.DrugstoreDst = ct.accountnum and ccd.ReturnIdRef = c.salesid and ccd.dataareaid = 'тк' and ct.dataareaid = 'zgc'),0) end as OrgUTIIDst
|from custinvoicejour b
|left join externalnumline j    on j.invoiceid = b.invoiceid and j.dataareaid = 'zgc'
|left join externalnumjournal k on k.dataareaid = 'zgc' and k.dataarea IN ('тк') and k.recid = j.refrecid
|join custinvoicetrans f on f.salesid = b.salesid and f.invoiceid = b.invoiceid and f.invoicedate = b.invoicedate and f.numbersequencegroup = b.numbersequencegroup and f.dataareaid IN ('тк')
|join salesline g on g.inventtransid = f.inventtransid and g.dataareaid IN ('тк')
|join inventtable t on t.itemid = f.itemid and t.dataareaid = 'zgc'
|join salestable c on c.salesid = f.salesid and c.dataareaid IN ('тк')
|join salespool i on c.salespoolid = i.salespoolid and i.dataareaid = 'zgc'
|join custtable h on h.accountnum = c.custaccount and h.dataareaid = 'zgc'
|join inventdim d on d.inventdimid = f.inventdimid and d.dataareaid = 'zgc'
|join inventserial e on e.inventserialid = d.inventserialid and e.dataareaid = 'zgc'
|left join inventserialdetail ed on ed.inventserialid = e.inventserialid and ed.dataareaid = 'zgc'
|left join rcontracttable r on r.rcontractpartnertype = 0 and r.rcontractcode = c.rcontractcode and r.rcontractaccount = c.rcontractaccount and r.rcontractpartnercode = c.custaccount and r.dataareaid IN ('тк')
|left join country v on v.countryid = t.producercountry and v.dataareaid = 'zgc'
|left join salespricing sp on e.inventserialid = sp.inventserialid and sp.dataareaid = 'тк'
|left join rcontracttableadd rcta on rcta.vendaccount = sp.vendaccount and rcta.custaccount = b.invoiceaccount and rcta.dataareaid = 'тк'
|left join VendElectronicInvoice vei on vei.num = c.PurchOrderFormNum and vei.inn_ru = c.CustomerRef and year(vei.DeliveryDate)=year(c.DeliveryDate) and vei.dataareaid = 'тк'
|where b.dataareaid IN ('тк')
|and (t.itemtype = 0 or t.itemtype = 1) and b.documentdate = '2016-06-21' and b.dimension4_ = '1' and exists (select 'x' from returnactiondefaults m where m.returnactionid = g.returnactionid and m.module = 2 and m.dataareaid = b.dataareaid and m.export1c = 1)
|and (i.export1ctrade = 1)
|
|union all
|
|select b.invoiceid, b.documentdate, b.invoiceamount, b.invoiceaccount, r.rcontractnumber,b.dimension4_ as status, c.purchpoolid, ed.dimension4 as serialstatus, (case when e.inventcompanyid <> b.dataareaid then 1 else 0 end) as commission,
|t.itemid, t.fullname, d.inventserialid, f.FacturedQty_RU as qty,
|case when f.FacturedQty_RU <> 0 then (f.lineamount+f.lineamounttax)/f.FacturedQty_RU else 0 end as price,          
|sp.PurchasingPriceTax as PurchasingPrice, case when vei.DeliveryName != '' then vei.DeliveryName else b.deliveryName end as DirectDeliveryName,
|f.lineamount, g.taxitemgroup, f.lineamounttax, d.inventgtdid_ru, v.name as gtdcounrty, g.inventrefid, h.INN_RU as INN,  ''  as INN_Main
|, 3 as transtype, case when f.lineamount < 0 then 1 else 0 end as statusissue, case when f.lineamount < 0 then 0 else 1 end as statusreceipt
|,t.vital, t.qtyaccounting, t.stronggroup, h.accountnum, 1 as vend, h.phone, h.address, f.dimension, f.dimension2_, f.dimension3_, f.dimension4_, f.dimension5_, f.dimension6_, f.dimension7_, 0 as haggle, '' as externalnum, '' as externaldate , h.KPP_RU as KPP
|,case when f.lineamount < 0 then g.inventrefid else NULL end as refinvoice
|,case when f.lineamount < 0 then (select top 1 documentdate from vendinvoicejour where dataareaid IN ('тк') and invoiceid = g.inventrefid) else null end as refinvoicedate,
|case when ct.AdditionCompany = 'FMS' then 'FMS' else case when ct.AdditionCompany = 'CTR' then 'CTR' else case when ct.AdditionCompany = 'YUG' then 'YUG' else '' end end end as OrgUTII,
|ct.AdditionCompanyDate as DateAddOrgUTII,          
|case when (((vei.inn_ru <>'' and vei.inn_ru is not null) and (ct.accountnum <>'' and ct.accountnum is not null)) or (c.PurchPoolId = 'Immediate')) then '1' else '0' end as DirectDelivery,
|'' as Purchasing_taxitemgroup, rcta.startdate as StartDateUGII, vei.DeliveryDate as DirectDeliveryDate,'' as OrgUTIIDst
|from vendinvoicejour b
|join vendinvoicetrans f on f.purchid = b.purchid and f.invoiceid = b.invoiceid and f.invoicedate = b.invoicedate and f.numbersequencegroup = b.numbersequencegroup and f.internalinvoiceid = b.internalinvoiceid and f.dataareaid IN ('тк')
|join purchline g on g.inventtransid = f.inventtransid and g.dataareaid IN ('тк')
|join inventtable t on t.itemid = f.itemid and t.dataareaid = 'zgc'
|join purchtable c on c.purchid = f.purchid and c.dataareaid IN ('тк')
|join purchpool i on c.purchpoolid = i.purchpoolid and i.dataareaid = 'zgc'
|join vendtable h on h.accountnum = c.orderaccount and h.dataareaid = 'zgc'
|join inventdim d on d.inventdimid = f.inventdimid and d.dataareaid = 'zgc'
|join inventserial e on e.inventserialid = d.inventserialid and e.dataareaid = 'zgc'
|left join inventserialdetail ed on ed.inventserialid = e.inventserialid and ed.dataareaid = 'zgc'
|left join rcontracttable r on r.rcontractpartnertype = 0 and r.rcontractcode = c.rcontractcode and r.rcontractaccount = c.rcontractaccount and r.rcontractpartnercode = c.orderaccount and r.dataareaid IN ('тк')
|left join country v on v.countryid = t.producercountry and v.dataareaid = 'zgc'
|left join salespricing sp on e.inventserialid = sp.inventserialid and sp.dataareaid = 'тк'
|left join VendElectronicInvoice vei on vei.num = b.INVOICEID and vei.inn_ru = h.inn_ru and vei.deliverydate = b.documentdate  and vei.dataareaid = 'тк'
|left join custtable ct on ((vei.deliveryname != '' and vei.deliveryname = ct.accountnum) or (b.deliveryname != '' and b.deliveryname = ct.accountnum))  and ct.additioncompany in ('FMS','CTR','YUG') and ct.dataareaid = 'zgc'
|  left join rcontracttableadd rcta on ((vei.orderaccount != '' and rcta.vendaccount = vei.orderaccount and rcta.custaccount = vei.deliveryname) or (h.accountnum != '' and rcta.vendaccount = h.accountnum and rcta.custaccount = b.deliveryname)) and rcta.dataareaid = 'тк'
|where b.dataareaid IN ('тк')
|and (t.itemtype = 0 or t.itemtype = 1) and b.documentdate = '2016-06-21' and b.dimension4_ = '1' and exists (select 'x' from returnactiondefaults m where m.returnactionid = g.returnactionid and m.module = 1 and m.dataareaid = b.dataareaid and m.export1c = 1)
|and (i.export1ctrade = 1)
|order by 4";
    
    command = ъ(Врап.Новый(SqlCommand.ПолучитьСсылку(),ТекстЗапроса,connection.ПолучитьСсылку()));
    
    //Parameters=ъ(command.Parameters);
    //Parameters.AddWithValue("@Строка", "ДСП");
    dr = ъ(command.ExecuteReader());
    
    Пока dr.Read() Цикл
        Сообщить(dr.get_Item("Наименование"));
    КонецЦикла;
КонецПроцедуры

&НаКлиенте
Процедура прочитатьSQL(Команда)
    прочитатьSQLНаСервере();
КонецПроцедуры

&НаКлиенте
Процедура ПриОткрытии(Отказ)
    ПриОткрытииНаСервере();
КонецПроцедуры

&НаСервере
Процедура ПриОткрытииНаСервере()
    // Вставить содержимое обработчика.    
    ИмяФайла="D:TestVK\AddInNetObjectToNative.dll";
    
    ПодключитьВнешнююКомпоненту(ИмяФайла, "NetObjectToNative",ТипВнешнейКомпоненты.Native);
    Врап = Новый("AddIn.NetObjectToNative.LoaderCLR");
    CoreClrDir="D:TestVK\bin\";
    ДиректорияNetObjectToNative="D:TestVK";
    
    
    ДиректорияNetObjectToNative="D:TestVK\NetObjectToNative\src\NetObjectToNative\bin\Debug\netstandard1.6\";
    
    СсылкаНаДомен=Врап.СоздатьОбертку(CoreClrDir,ДиректорияNetObjectToNative,"");
    Врап.ЗагрузитьDLL(ИмяФайла);
    
    String=ъТип("System.String");
    ExpandoObject=ъТип("System.Dynamic.ExpandoObject, System.Dynamic.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
    Environment=ъТип("System.Environment");
    NewLine=Environment.NewLine;
    Таб=Символы.Таб;
КонецПроцедуры

&НаСервере
Функция Ъ(знач Ссылка)
    
    Если не ЗначениеЗаполнено(Ссылка) Тогда
        Сообщить("Пустое значение")
        
        
    КонецЕсли;
    рез = Новый("AddIn.NetObjectToNative.NetObjectToNative");
    рез.УстановитьСсылку(Ссылка);    
    возврат  рез
КонецФункции // СоздатьОбъектПоСсылке()

&НаСервере
Функция ъНовый(знач стр)
    возврат ъ(Врап.Новый(стр));
КонецФункции

&НаСервере
Функция ъТип(знач стр,ИмяФайла="",ГлобальнаяСборка=ложь)
    //возврат ъ(Врап.ПолучитьТип(стр));
    возврат ъ(Врап.Тип(стр,ИмяФайла,ГлобальнаяСборка));
КонецФункции

&НаСервере
Функция ОписаниеСтроки()
    КвалификаторыСтроки = Новый КвалификаторыСтроки(0, ДопустимаяДлина.Переменная);
    возврат Новый ОписаниеТипов("Строка",,КвалификаторыСтроки);
КонецФункции

Компонента подключается, код отрабатывает, но на строке

СсылкаНаДомен=Врап.СоздатьОбертку(CoreClrDir,ДиректорияNetObjectToNative,"")

Получаею ошибку "Прекращена работа программы 1cv8c.exe", и, соответственно, програмуля закрывается.

Как бороться?
153 Serginio1
 
29.08.16
10:14
Для начала
1. Разархивируй каталог
2. Из этой директории запусти отчет. Там в отчете уже пути настроены.

3. Для запуска System.Data.SqlClient.dll нужны еще
3 библиотеки.

Разбирись с пунктами 1,2. Если все выйдет выложу библиотеки для работы с System.Data.SqlClient
154 Serginio1
 
29.08.16
10:16
На сервере данная сборка работать не будет. Она скомпилирована под 32 разрядную. Нужно давать ссылку на 64 разрядную CoreClr.
155 _stay true_
 
29.08.16
10:30
(154)
1. Было сделано;
2. Было сделано.

При запуске отчета TestVK на Win7 x64 так же валится на том же месте. Пути я сделал свои сам по аналогии, дабы адаптировать под УФ. Попробую в обед на win7 x32 ещё днём.

3. Для запуска System.Data.SqlClient.dll нужны еще 3 библиотеки. Можете выложить их вместе с x64 CoreCLR?

Пока тестим на винде, если всё получится - вечером даю команду админам предоставить мне комп с линухом, и будем тестить уже в полном объеме на кроссплатформенность.
156 Mauser
 
29.08.16
10:36
(155) Скажите, а просто прийти и взять вам не дают? Надо подчеркивать тонкость отдачи вами команды предоставить?
157 _stay true_
 
29.08.16
10:39
(156) Админы злые. К ним только по заявкам, подписанным и утвержденным руководителем IT-службы.

"Надо подчеркивать тонкость отдачи вами команды предоставить?"
Вы это к чему?
158 Serginio1
 
29.08.16
10:56
(155) Я то скомпилировать могу. А вот проверить то нет. У меня только локальные 8 ки.

Просто там смещения в структуре _tVariant могут быть другие. Нужно тестировать, а у меня не на чем.

Сделай пустую базу на простых формах и посмотри пойдет или нет. Я проверял у себя на 10 и 7 ке вроде шло. Но у меня и VS стоит или 10 ка
159 Serginio1
 
29.08.16
11:05
Я скомпилирую сначала exe шник посмотрю. И сообщу когда сделаю
160 Serginio1
 
29.08.16
11:08
Если установить 64 разрядную .Net Core то она лежит здесь
c:\Program Files\dotnet\shared\Microsoft.NETCore.App\1.0.0\

Скачать дистрибутивы можно здесь
https://www.microsoft.com/net/core#windows
или здесь
https://github.com/dotnet/cli
161 _stay true_
 
29.08.16
11:08
(159) окай. Спасибо вам большое ещё раз.
Если всё у нас получится с Линухом - готов сделать пожертвование в фонд развития проекта
162 Serginio1
 
29.08.16
11:27
(161) Большое спасибо за поддержку. Сейчас 64 разрядном exe шнике попробовал. Все работает.

Чуть позже скомпилирую ВК под 64 разрядную.
163 Serginio1
 
29.08.16
11:41
Кстати
long GetClassObject(const wchar_t* wsName, IComponentBase** pInterface)

long to 32 разрядный. При компиляции дает предупреждение.
164 Serginio1
 
29.08.16
11:45
Хотя для этого существует INT_PTR
165 orefkov
 
29.08.16
12:07
(164)
Для чего тут INT_PTR?
166 Serginio1
 
29.08.16
12:26
(165) Спасибо. Просто

long GetClassObject(const WCHAR_T * clsName, IComponentBase** pIntf)

Параметры:
•<clsName> Тип: const WCHAR_T *. Имя создаваемого объекта.
•< pIntf > Тип: IComponentBase**. Указатель на переменную, в которую нужно записать адрес вновь созданного объекта.

Возвращаемое значение:

•long – не нулевое значение сигнализирует о успешном создании объекта

Просто в шаблонах пишут

return (long)*pInterface;

Сделали бы просто bool

Сейчас у себя подправлю
167 Serginio1
 
29.08.16
14:33
Попробую на 8.3.9 64 разрядном клиенте
168 _stay true_
 
29.08.16
16:05
Так и не смог запустить на Win7 Professional x64 демо-пример из вашего архива. Как доходит до "СоздатьОбертку" - сразу валится. Visual Studio установлен, все фреймворки дотнет имеются. Винда с последними обновлениями. Что ей ещё нужно...
169 Maximich
 
29.08.16
16:50
Добрый день.

Подскажите, правильно ли я понимаю что если я внимательно прочитаю Ваши статьи то смогу связав 1С 7.7/8.3 и http://www.fluorinefx.com/ подключаться к web-сервисам по протоколу amf3 ?

Натолкните на кратчайший путь. Заранее благодарен.
170 _stay true_
 
30.08.16
09:47
И меня. Не хочет запускаться демо-пример ни на одной винде. Какие компоненты должны быть обазательно установлены?
171 Serginio1
 
30.08.16
10:49
(169) Да раз .Net есть
(168) Сейчас проверю на других компах.
Скачай отсюда https://yadi.sk/d/FBHUVl22suNwH
С++ приложение. Оно делает тоже самое только напрямую
172 Serginio1
 
30.08.16
10:51
Скомпилировал под 64 разрядное. Если запускать из экзешника
То все нормально. Но если из 64 разрядной 1С 8.3.9


Выдает ошибку
Необработанное исключение по адресу 0x00007FFD76FB8528 (ucrtbase.dll) в 1cv8.exe: Недопустимый параметр был передан функции, для которой недопустимые параметры вызывают неустранимую ошибку.

Вот экспортируемуе методы

typedef bool(STDMETHODCALLTYPE *ManagedCallAsFunc)(const __int32, const wchar_t*, tVariant* pvarRetValue, tVariant* paParams, const __int32  lSizeArray);
    typedef int(STDMETHODCALLTYPE *ManagedGetNParams)(const __int32, const wchar_t*);
    typedef bool(STDMETHODCALLTYPE *ManagedGetPropVal)(const __int32, const wchar_t*, tVariant*);
    typedef bool(STDMETHODCALLTYPE *ManagedSetPropVal)(const __int32, const wchar_t*, tVariant*);
    typedef void(STDMETHODCALLTYPE *ManagedSetDelegate)(void*(*) (long), void(*) (const wchar_t*), void(*) (wchar_t*, wchar_t*,wchar_t*));
    typedef void(STDMETHODCALLTYPE *ManagedDeleteObject)(const __int32);
    typedef void(STDMETHODCALLTYPE *ManagedSetPath)(const wchar_t*);
    typedef int(STDMETHODCALLTYPE *Managedtest)();
173 _stay true_
 
30.08.16
10:59
(172) Да мне бы хоть под 32-х разрядным клиентом заработало(((
И прямой запрос выполнился(((
174 Maximich
 
30.08.16
11:04
Serginio1, а откуда еще можно скачать NetObjectToIDispatch.zip кроме инфостарта ?
175 Serginio1
 
30.08.16
11:39
176 Maximich
 
30.08.16
11:42
Спасибо
177 Serginio1
 
30.08.16
12:23
(173) Можешь скинуть свою обработку?
Сейчас посмотрю, что с УФ на клиенте.
178 Serginio1
 
30.08.16
12:46
179 _stay true_
 
30.08.16
12:54
(177) Скиньте, если Вас не затруднит.
180 Serginio1
 
30.08.16
13:40
(179) После обеда.

По поводу ucrtbase.dll то MS провела рефакторинг в VC++ 2015

https://msdn.microsoft.com/ru-ru/library/bb531344.aspx
181 Maximich
 
30.08.16
15:19
Кстати, google mail Очень не понравился файл из (171). Упорно не давал его отправить по почте.
182 Serginio1
 
30.08.16
15:21
Да это проблема Гугла. Там Exe шник
183 Serginio1
 
30.08.16
17:08
Выложил https://yadi.sk/d/jRSHEA19svgrn
Там внутри TestVKУФ.epf тест подключения к БД.
Подправь строку подключения и запрос. У меня работает.
Добавил обработку исключений и вывод ошибки при подключении.

Указать путь к DLL