![]() |
|
Кроссплатформенное использование классов .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
|
(93) API IE из 1с 7.7
|
|||
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 |
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |