Использование классов .Net в 1С для новичков

Опубликовал Serginio в раздел Программирование - Практика программирования

Руководство для новичков. Написав статью http://infostart.ru/public/238584/, я понял, что многие не понимают того, что написано. Поэтому в этой статье постараюсь более подробно остановиться на азах и без кода на вражеском языке (C#)

В  .Net есть классы, структуры(Value типы), перечисления. С точки зрения 1С их можно рассматривать как классы. Каждый класс характеризуется типом.

По аналогии с 1С классы это справочники, документы и т.д.

У классов могут быть статические методы и свойства  и методы и свойства объекта. По аналогии с 1С статические методы это методы менеджера (НайтиПоКоду,НайтиПоНомеру), а методы объекта аналогичны методам объекта (Модифицированность, Удалить, Номер,Дата)

У каждого класса есть тип, через который мы и будем работать. Для упрощения класс и тип для нас будет одним и тем же.

Каждый класс характеризуется именем класса, пространством имен и сборкой (размещение Dll, Exe).

Рассмотрим класс String https://msdn.microsoft.com/ru-ru/library/system.string(v=vs.110).aspx

Представляет текст как последовательность знаков Юникода.

Исходный код .NET Framework для этого типа см. в указанном источнике.

Пространство имен:   System
Сборка:  mscorlib (в mscorlib.dll)

Начнем сразу на примерах. Итак, для начала создадим объект, который будет обертывать объекты .Net в COM объекты.

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

Теперь получим тип System

String=Врап.ПолучитьТип("System.String");

Для понимания правильнее будет так

ПространствоИмен="System.";
String=Врап.ПолучитьТип(ПространствоИмен+"String");

Кто работал с ФабрикаXDTO, то там тоже есть простанство имен и типы.

К типам, которые находятся в GAC, мы можем не указывать сборку, в которой она находится.

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

Теперь мы можем вызвать статические методы.

Например, аналог  1С функции ПустаяСтрока

Сообщить(String.IsNullOrWhiteSpace(неопределено));
Сообщить(String.IsNullOrWhiteSpace("  "));

Вернет Истина.

 

Статические методы в справке https://msdn.microsoft.com/ru-ru/library/system.string(v=vs.110).aspx

Помечаются  символом S.

К сожалению, есть проблемы с функциями, которые принимают параметры как массив params.

Например, у класса String  есть статическая функция Format

У неё есть множество перегрузок.

https://msdn.microsoft.com/ru-ru/library/b1csw23d(v=vs.110).aspx

public static string Format(

               string format,

               params object[] args

)

Которая вызывается, когда параметров больше 3

При объявлении  параметра как params object[] мы можем задавать параметры через запятую.

Сообщить(String.Format("загружено {0} из {1} байт. {2}  % complete...", 
        e.BytesReceived, 
        e.TotalBytesToReceive,
		e.ProgressPercentage,
        0));

Я добвил еще один неиспользуемый параметр 0, иначе последний параметр вывелся бы как System.Object[]

Для того, что бы исправлять такие ошибки я добавил  метод ВыполнитьМетод

Который принимает первым параметром тип или строковое представление типа ("System.String");

Вторым параметром имя метода, а дальше параметры для запрашиваемого метода

 

Сообщить(Врап.ВыполнитьМетод(String,"Format","загружено {0} из {1} байт. {2}  % complete...", 
        e.BytesReceived, 
        e.TotalBytesToReceive,
		e.ProgressPercentage));

Теперь перейдем с созданию объекта и вызову методов объекта.

Объект можно получить двумя способами

DateTime= Врап.ПолучитьТип("System.DateTime ");
Дата=Врап.СоздатьОбъект(DateTime,2015,1,2);

или

Дата=Врап.СоздатьОбъект("System.DateTime",2015,1,2);

Следует учесть, что в 1С числовые типы, дата строки, булево, массивы этих типов и Com объекты возвращаются как родные.

Поэтому если использовать объектные методы, например, String нужно обернуть его.

Например

ОбернутаяСтрока=Врап.ОбернутьЛюбойОбъект("Тестовая строка");

Теперь можно применить к ней объектные методы

Найдем первое вхождение строки "ст" начиная с 6 символа (Возвращает индекс с отсчетом от нуля первого вхождения значения указанной строки в данном экземпляре. Поиск начинается с указанной позиции знака.)

Сообщить(ОбернутаяСтрока.IndexOf("ст",5));

Вернет 9

В .Net есть дженерик типы, у которых используемые типы заданы неявно.

http://professorweb.ru/my/csharp/charp_theory/level11/11_1.php

 

Возьмем для примера System.Collections.Generic.List<T>

https://msdn.microsoft.com/ru-ru/library/6sh2ey19(v=vs.110).aspx

 

В C# Для того, чтобы создать список строк

var список = new List<String>();
Можно посмотреть строковое представление класса
Список.GetType().ToString()
Или
typeof(List<String>).ToString();

 

он выдаст System.Collections.Generic.List`1[System.String]

Теперь мы можем использовать его

Список=Врап.СоздатьОбъект("System.Collections.Generic.List`1[System.String]");
Для сч=1 По 10 Цикл
Список.Add(строка(сч));	
КонецЦикла; 

Для каждого стр Из Список Цикл
	 Сообщить(стр)
КонецЦикла;

Но тоже можно добиться другим способом

Узнав строковое представление typeof(List<>).ToString()

System.Collections.Generic.List`1[T]

Оно совпадает с названием класса, только добавляется `1 это говорит, что дженерик поддерживает 1 неопределенный тип.

ListT=Врап.ПолучитьТип("System.Collections.Generic.List`1");
ListT=Врап.ТипКакОбъект(ListT); 
Список=Врап.СоздатьОбъект(ListT.MakeGenericType(String));

Нужно отметить, для того, что бы у объекта полученного как  ПолучитьТип был доступ к методам класса Type нужно его преобразовать через метод ListT=Врап.ТипКакОбъект(ListT);

Так как в реализации обертки он отвечает за статические методы класса.

Аналогично можно создать и словарь Dyctionary, это типизированный аналог 1С Соответствие

Dictionary<String,int>

Словарь= Врап.СоздатьОбъект("System.Collections.Generic.Dictionary`2[System.String,System.Int32]");

Для сч=1 По 10 Цикл

Словарь.Add(строка(сч),сч);	

КонецЦикла; 

Для каждого стр Из Словарь Цикл
	 Сообщить(стр.Key+"="+стр.Value)
КонецЦикла; 

//Аналогично это можно достигнуть через
СловарьT=Врап.ПолучитьТип("System.Collections.Generic.Dictionary`2");
Int32=Врап.ПолучитьТип("System.Int32");
СловарьT=Врап.ТипКакОбъект(СловарьT);
Словарь=Врап.СоздатьОбъект(СловарьT.MakeGenericType(String,Int32));

Еще одна особенность работы с C# реализацией this[]

Например, в 1С мы не можем вызвать Список[0]. Доступ осуществляется через

get_Itemи set_Item

Список.set_Item(0,"1С+Net");
Сообщить(Список.get_Item(0));

Вот полный список классовSystem.Collections.Generic

https://msdn.microsoft.com/ru-ru/library/system.collections.generic(v=vs.110).aspx

Регулярные выражения тоже часто применяются для поиска замены.

http://professorweb.ru/my/csharp/charp_theory/level4/4_10.php

Я покажу, как их использовать на примерах

input = "Добро пожаловать в наш магазин, вот наши цены: 
 |1 кг. яблок - 20 руб. 
 |2 кг. апельсинов - 30 руб.
 |0.5 кг. орехов - 50 руб.";
 
 pattern = "\b(\d+\W?руб)";
 regex = Врап.СоздатьОбъект("System.Text.RegularExpressions.Regex",pattern);
  // Получаем совпадения в экземпляре класса Match
 matches = regex.Matches(input);
// отображаем все совпадения
Для Каждого match in matches Цикл
	 // Т.к. мы выделили в шаблоне одну группу (одни круглые скобки),
	 // ссылаемся на найденное значение через свойство Groups класса Match
	 Сообщить(match.Groups.get_Item(1).Value);
КонецЦикла

В статье многого не затронешь, но хочу показать быстродействие вызова методов .Net классов через обертку.

В 1С нет явного аналога StringBuilder Предоставляет изменяемую строку символов.

В этом тесте нужно собрать строку из маленьких фрагментов строк. В 1С для соединения строк есть неявный аналог ЗаписьXML ЗаписатьБезОбработки.

Для  замера времени используем Stopwatch который замеряет время до миллисекунды

https://msdn.microsoft.com/ru-ru/library/system.diagnostics.stopwatch(v=vs.110).aspx

Процедура ВывестиВремя(врап,stopWatch)
	ts = stopWatch.Elapsed;
	String=Врап.ПолучитьТип("System.String");
	// Format and display the TimeSpan value.
	elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
	ts.Hours, ts.Minutes, ts.Seconds,
	ts.Milliseconds / 10,0);
	Сообщить(elapsedTime);
КонецПроцедуры	
Процедура StringBuilderНажатие(Элемент)
	// Вставить содержимое обработчика.
	врап=новый COMОбъект("NetObjectToIDispatch45");

	КоличествоИтераций=200000;
	stopWatch = Врап.СоздатьОбъект("System.Diagnostics.Stopwatch");
	
	стр="";
	
	НачВремя=ТекущаяДата();
	stopWatch.Start();
	
	Для сч=1 по КоличествоИтераций Цикл
		стр=стр+Строка(сч);
	КонецЦикла;
	stopWatch.Stop();
	
	ВремяВыполнения=ТекущаяДата()-НачВремя;
	Сообщить("Конкатенация ="+ВремяВыполнения+" сек. ДлинаСтр="+СтрДлина(Стр));
	
	ВывестиВремя(врап,stopWatch);
	стр="";
	НачВремя=ТекущаяДата();
	stopWatch.Restart();
	SB =  врап.СоздатьОбъект("System.Text.StringBuilder");
	Для сч=1 по КоличествоИтераций Цикл
		SB.Append(Строка(сч));
	КонецЦикла;
	
	стр=SB.ToString();
	stopWatch.Stop();
	
	ВремяВыполнения=ТекущаяДата()-НачВремя;
	Сообщить("StringBuilder ="+ВремяВыполнения+" сек. ДлинаСтр="+СтрДлина(Стр));
	ВывестиВремя(врап,stopWatch);
	
	НачВремя=ТекущаяДата();
	stopWatch.Restart();
	ЗаписьXML = Новый ЗаписьXML;
	ЗаписьXML.УстановитьСтроку();
	
	Для сч = 1 по КоличествоИтераций Цикл
		ЗаписьXML.ЗаписатьБезОбработки(Строка(сч));
	КонецЦикла;
	Стр = ЗаписьXML.Закрыть();
	stopWatch.Stop();
	
	ВремяВыполнения=ТекущаяДата()-НачВремя;
	Сообщить("ЗаписьXML ="+ВремяВыполнения+" сек. ДлинаСтр="+СтрДлина(Стр));
	ВывестиВремя(врап,stopWatch);
	
//Конкатенация =96 сек. ДлинаСтр=1 287 896
//00:01:36.22
//StringBuilder =10 сек. ДлинаСтр=1 287 896
//00:00:09.91
//ЗаписьXML =4 сек. ДлинаСтр=1 287 896
//00:00:04.40



КонецПроцедуры

Как видно, скорость вызова .Net класса в 2.25 раза медленнее обычного метода. Это нужно учитывать при обработке больших массивов данных.

Используем информацию о культуре .

https://msdn.microsoft.com/ru-ru/library/system.globalization.cultureinfo(v=vs.110).aspx

Но часто нужно получать с данных без учета культуры

Целое   = 55333;
Дробное   = 66333.44;
Строка   = "абвгд";
Дата=ТекущаяДата();

CultureInfo=Врап.ПолучитьТип("System.Globalization.CultureInfo");
SB.AppendFormat(CultureInfo.InvariantCulture,"{0} {1} {2} {3}",Целое,Дробное,Строка,Дата,0);
Сообщить(SB.ToString());

Получаем

55333 66333.44 абвгд 01/26/2016 17:10:05

Стоит еще добавить приведение типа к Интерфейсу. На примере прохода по коллекции. Если в 1С можно пройтись через Для Каждого то для 7 ки этого сделать нельзя. Заодно понять как приводить к интерфейсу.

Так из документации мы знаем что List<T> поддерживает интерфейс IEnumerable

https://msdn.microsoft.com/ru-ru/library/system.collections.ienumerable(v=vs.100).aspx

 Перечислимый=Врап.ПолучитьИнтерфейс(Список,"IEnumerable");
 Перечислитель=Перечислимый.GetEnumerator();
 // На всякий случай приведем к Интерфейсу IEnumerator
 Перечислитель=Врап.ПолучитьИнтерфейс(Перечислитель,"IEnumerator");
 // Теперь можем пройтись по коллекции
 
Пока Перечислитель.MoveNext() Цикл
//  Врап.ВСтроку вывоит строковое представление всех типов в том числе числовые, строки, неопределено
	Сообщить(Врап.ВСтроку(Перечислитель.Current));

КонецЦикла; 
// Для того что бы получить методы объекта реализующего интерфейс можно
// спомощью метода  ОбновитьДанныеОметодахИСвойствах(object objOrig)


// Для того что бы получить массив String[] можно вызвать
Массив=Список.ToArray();
 Сообщить(Массив);

 // В 1С он будет определен как COMSafeArray VT_BSTR
 // Доступ к элементам массива также как и в COMSafeArray через  GetValue и SetValue
//https://msdn.microsoft.com/library/system.array(v=vs.100).aspx
// Создать массив можно через метод врапера СоздатьМассив(object type, int length)

Еще в .Net для асинхронного программирования используют await и методы возвращающие Task<>

Для того, чтобы получить результат, нужно обратиться к свойству Result, если нужно подождать, то вызвать метод Wait()

https://msdn.microsoft.com/ru-ru/library/dd321424(v=vs.118).aspx

// Следует отметить, что не все типы из GAC модно подгрузить
// Например  System.Net.Http.HttpClient который находится с System.Net.Http.dll
//Получить тип можно двумя способами
// По полному имени 
//Клиент=Врап.СоздатьОбъект("System.Net.Http.HttpClient, System.Net.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
//Либо просто указать имя библиотеку в котором находится класс без полного пути
//Тогда  ПолучитьТипИзСборки будет искать в катаорге GAC
HttpClient=Врап.ПолучитьТипИзСборки("System.Net.Http.HttpClient","System.Net.Http.dll");
Клиент=Врап.СоздатьОбъект(HttpClient);
ДанныеРесурса=Клиент.GetStringAsync("https://msdn.microsoft.com/ru-ru/library/hh551745(v=vs.118).aspx").Result;

Сообщить(Врап.ВСтроку(ДанныеРесурса));

Стоит вспомнить про вложенные типы на примере System.Environment.SpecialFolder 

Так для получения типа нужно разделять вложенный тип знаком плюс, а не точкой

 

Environment=Врап.ПолучитьТип("System.Environment");
	SpecialFolder=Врап.ПолучитьТип("System.Environment+SpecialFolder");
	Сообщить(Environment.GetFolderPath(SpecialFolder.CommonProgramFilesX86));
	Сообщить(Environment.GetFolderPath(SpecialFolder.Desktop));
	Сообщить(Environment.GetFolderPath(SpecialFolder.MyDocuments));
 

Используя System.IO.Path можно получить доступ к Temp директории

Path=Врап.ПолучитьТип("System.IO.Path");
Сообщить(Path.GetTempPath());

Там же много методов для манимулирования с наименованием файла, получение каталога, расширения, объединять строки в путь итд

Очень часто приходится использовать битовую операци OR

например 

 AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
 
или
 watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
           | NotifyFilters.FileName | NotifyFilters.DirectoryName;
 
Поэтому добавил метод OR. Теперь те же операции можно вызвать
 
DecompressionMethods= Врап.ПолучитьТип("System.Net.DecompressionMethods");
  handler.AutomaticDecompression=Врап.OR(DecompressionMethods.GZip,DecompressionMethods.Deflate) ;

или

NotifyFilters=врап.ПолучитьТип("System.IO.NotifyFilters");
    рез=Врап.OR(NotifyFilters.LastAccess,NotifyFilters.LastWrite,NotifyFilters.FileName,NotifyFilters.DirectoryName);
 

Надеюсь, данная статья поможет использовать классы .Net даже тем, кто не знает C#. Ничего сложного нет, но поможет сильно увеличить возможности 1С без написания COM объектов или ВК

См. также

Лучшие комментарии

13. Serginio 17.02.2016 14:34
(11) Как я писал в статье для таких случаев нужно использовать CultureInfo

Decimal=Врап.ПолучитьТип("System.Decimal");
   CultureInfo=Врап.ПолучитьТип("System.Globalization.CultureInfo");
   culture=CultureInfo.InvariantCulture;
   Число="0.000001";
   Сообщить(Decimal.Parse(Число, culture.NumberFormat));
...Показать Скрыть
+ 1 [ Ferroks; ]
# Ответить

Комментарии

1. Serginio 27.01.2016 17:43
Сейчас в .Net широко применяют оператор await. Он применяется к методам возвращающие Task или Task<TResult>.
Task это задача представляет асинхронную операцию. Доступ к результату осуществляется через свойство Result.
В 1С можно использовать либо синхронный вариант например
ДанныеРесурса=Клиент.GetStringAsync("https://msdn.microsoft.com/ru-ru/library/hh551745(v=vs.118).aspx").Result;


Но для того, что бы этот метод выполнить асинхронно я создал класс с помощью которого легко использовать эти методы асинхронно.

врап=новый COMОбъект("NetObjectToIDispatch45");
Выполнитель=Врап.ПолучитьАсинхронныйВыполнитель();
ДобавитьОбработчик Выполнитель.ПриОкончанииВыполненияЗадачи, ПриОкончанииВыполнения;

Обработчик события выглядит так
Процедура ПриОкончанииВыполнения(Задача,ДанныеКЗадаче)

    // Обязательно нужно отлавливать ошибку в 1С
    // Иначе она передается в .Net где обрабатывается там
    Попытка
Так как задача может завершиться с ошибкой
Мы должны проверить, и если ошибка нужно предпринять какие то действия
        Если (Задача.IsFaulted) Тогда  // Ошибка выполнения

            Сообщить("Ошибка "+Врап.ВСтроку(Задача.Exception));
            Сообщить("Данные к задаче "+Врап.ВСтроку(ДанныеКЗадаче));

        иначе
            Сообщить("=====Выполнена задача ====");
            Сообщить("Данные к задаче "+Врап.ВСтроку(ДанныеКЗадаче));
            Сообщить(Врап.ВСтроку(Задача.Result));


        КонецЕсли;

    Исключение
        Сообщить("Ошибка в процедуре");
        Сообщить(ОписаниеОшибки());
    КонецПопытки

КонецПроцедуры
...Показать Скрыть

Вызываем задачу так
HttpClient=Врап.ПолучитьТипИзСборки("System.Net.Http.HttpClient","System.Net.Http.dll");
    Клиент=Врап.СоздатьОбъект(HttpClient);
    Задача=Клиент.GetStringAsync("https://msdn.microsoft.com/ru-ru/library/hh551745(v=vs.118).aspx");
    Выполнитель.Выполнить(задача,ТекущаяДата());
...Показать Скрыть

Вторым параметром можно передавать любые данные, что бы понять какая задача выполнена и что с ней делать, так одновременно может работать множество задач

Например

АсинхМетоды = Врап.СоздатьОбъект(КлассДляТестаАсинхронныхМетодов);

    Для сч=1 по 10 Цикл
        задача=АсинхМетоды.ДолгаяЗадача(Строка("Задача "+сч));
        Выполнитель.Выполнить(задача,сч);
    КонецЦикла
...Показать Скрыть
# Ответить
2. kostyaomsk 28.01.2016 18:02
Интересная статья. Надо будет запомнить для задач интеграции. Жаль, что приводится то что не очень надо :( А хотелось бы иметь под рукой библиотеку функций допустим для работы с зависшими процессами (фоновыми задачами), многими функциями ОС итд.
Кстати насчет времени до миллисекунд вроде стандартная консоль запросов содержит строчку на JavaScript для записи текущего времени.
Ответили: (4) (7)
# Ответить
3. kostyaomsk 28.01.2016 18:05
Вернее автору статьи (и знающим людям) вопрос по-другому: я могу вызвать API-функции Винды смотря справочник через данные объекты просто смотря справочник, передавать в функции и принимать от них данные в формате винды (или в универсальном формате). Я когда-то давно начинал с делфи, даже на ассемблере чуток писал для аппаратуры, но сейчас это в прошлом. Тогда только через стандарные компоненты делфи работал.
Чтоб не было голословно приходилось писать только на досовском C++ Может навык пригодится для хотя бы понимания как обратиться к современным библиотекам на C# .net или что там
Ответили: (4)

Прикрепленные файлы:

CH.C
TEST.C
# Ответить
4. Serginio 28.01.2016 18:22
(2) Ну эта статья для начинающих. Посмотри мои другие статьи. Там много других примеров. Все написать невозможно. Показан принцип работы с классами .Net . Просто нужно найти нужный, а примеров в инете правда на C# полно.
(3) Не понял?
Ответили: (5)
# Ответить
5. kostyaomsk 28.01.2016 19:01
(4) Serginio, это большой плюс что Вы описали в двух словах "как запустить". Тем более я в этой технологии и есть "начинающий". Хотелось бы узнать кратно что можно и нужно делать через .net если:
1. Такой технологии НЕТ в 1С.
2. Стандартные методы сложны, глючны и малоэффективны.
На что в общем стоит обратить внимание.
Ответили: (6)
# Ответить
6. Serginio 28.01.2016 23:34
(5) Я бы посоветовал начать с азов. От простого к сложному.
http://metanit.com/sharp/general.php
http://professorweb.ru/my/csharp/charp_theory/level1/infonet.php

Для начала просмотреть, а уже на конкретных задачах углубляться.
# Ответить
7. Andris_infostart 03.02.2016 12:37
(2) kostyaomsk, ТекущаяУниверсальнаяДатаВМиллисекундах(), вполне подходит для получения мс
# Ответить
8. olbu 04.02.2016 14:51
Интересно!, а есть простые примерчики применения?
# Ответить
10. Ferroks 17.02.2016 13:32
Недавно столкнулся с преобразование типов, за 5 минут задачу решить не получилось)
Оставлю здесь подсказку.

Преобразовании типов 1С в типы Net

Г
УИД = СОКРЛП(Новый УникальныйИдентификатор());
UUU = Врап.ПолучитьТип("System.Guid").Parse(ГУИД);
Дата = ТекущаяДата();
	
	
ЧислоИНТ1 = Врап.ChangeType("System.Int32",-2147483648);
ЧислоИНТ2 = Врап.ChangeType("System.Int32",2147483647);
Десятичное1 = Врап.ChangeType("System.Decimal",7.9 * Pow(10,28));                              
Десятичное2 = Врап.ChangeType("System.Decimal",-7.9 * Pow(10,28));
Дробное1	=	Врап.ChangeType("System.Decimal","0.000001");
Дробное2 	= Врап.ChangeType("System.Decimal","-0.0000001");
...Показать Скрыть
# Ответить
11. Ferroks 17.02.2016 13:41
можно еще так преобразовать тип 1С в тип Net
ТипДесЧерезПарсе = Врап.ПолучитьТип("System.Decimal").Parse("0,000001");

бывает что получаешь ошибку "Неизвестная ошибка" или метод не найдет, проверьте параметр который передаете.
ТипДесЧерезПарсе = Врап.ПолучитьТип("System.Decimal").Parse("0,000001");
- так отрабатывает нормально.
а так выдает ошибку - ТипДесЧерезПарсе = Врап.ПолучитьТип("System.Decimal").Parse("0.000001");
Ответили: (13)
# Ответить
12. avz_1C 17.02.2016 14:28
Простите, а как узнать длину строки через свойство Length переменной типа String?

Я создал строку:

врап=новый COMОбъект("NetObjectToIDispatch45");
ПространствоИмен="System.";
String=врап.ПолучитьТип(ПространствоИмен+"String");
стр = String("abc");


Отработало нормально, в переменной стр находится "abc"

Теперь добавляю

ДлинаСтр = стр.Length;


и получаю ошибку:

"Значение не является значением объектного типа (Length)"
Ответили: (14)
# Ответить
13. Serginio 17.02.2016 14:34
(11) Как я писал в статье для таких случаев нужно использовать CultureInfo

Decimal=Врап.ПолучитьТип("System.Decimal");
   CultureInfo=Врап.ПолучитьТип("System.Globalization.CultureInfo");
   culture=CultureInfo.InvariantCulture;
   Число="0.000001";
   Сообщить(Decimal.Parse(Число, culture.NumberFormat));
...Показать Скрыть
+ 1 [ Ferroks; ]
# Ответить
14. Serginio 17.02.2016 14:36
(12) В статье писал про это

Следует учесть, что в 1С числовые типы, дата строки, булево, массивы этих типов и Com объекты возвращаются как родные.

Поэтому если использовать объектные методы, например, String нужно обернуть его.

Например
ОбернутаяСтрока=Врап.ОбернутьЛюбойОбъект("Тестовая строка");
ДлинаСтр =ОбернутаяСтрока.Length; 

...Показать Скрыть
# Ответить
15. avz_1C 17.02.2016 14:41
Получилось так:

врап = Новый COMОбъект("NetObjectToIDispatch45");
стр = врап.ОбернутьЛюбойОбъект("1СдотНЕТ");
ДлСтр = стр.Length;


В ДлСтр значение 8

При попытке посмотреть отладчиком 1С структуру объекта стр, система ругается на множество сборок.
# Ответить
16. avz_1C 17.02.2016 14:43
Не успел прочитать ответ, увидел в статье и тут же попробовал.
О результате сообщил постом выше.
Спасибо!
# Ответить
17. avz_1C 17.02.2016 14:46
Через МИСТА, по ссылке на яндекс-диск, получил проект (исходники) от NetObjectToIDispatch.dll версии 2.0

А можно ли где-то взять проект (исходники) NetObjectToIDispatch45.dll ?

Ну, очень интересная тема.
# Ответить
19. avz_1C 17.02.2016 16:20
Спасибо. Получил.
Если, вдруг, потребуются "соучастники" в проект, готов поработать.
Под Вашим руководством :-)
Ответили: (20)
# Ответить
20. Serginio 17.02.2016 16:48
(19) Спасибо. Буду иметь ввиду. Но самое лучшее это писать статьи как http://infostart.ru/public/434345/
# Ответить
21. avz_1C 17.02.2016 18:34
Буду пытаться. Благодарю Вас за совет.
Да и Вы, если вдруг захотите расширить аудиторию, милости
просим в авторы блога на сайт www.programmist1c.ru
Ответили: (22)
# Ответить
22. Serginio 18.02.2016 09:41
(21) Спасибо буду иметь ввиду
# Ответить
23. avz_1C 18.02.2016 15:02
Добрый день, Сергей.

Тестирую Вашу обработку ТестВКУФ.erf

Захватывающе! Особенно с окном на WPF.

Очень хочется посмотреть исходники того, что упаковано в двоичный макет.

Можно?

И вот, ещё, встретил в статье след. предложение:
- "Также добавил возможность показать окно семерки созданное через Новый COMОбъект("V77.Application")

А это в каком примере можно увидеть?

Прошу прощения, если что-то пропустил, но, вроде бы читал внимательно.
Ответили: (25)
# Ответить
24. avz_1C 18.02.2016 15:56
При повторном, начиная с третьего, открытии обработки, через Файл -> Открыть ... Появляется сообщение:

- "Неизвестное имя формы: ХХХХХХХХХХХХХХХХХХХХХХХХ.Form"

Пока не разобрался, в чем дело.

Предполагаю, что-то связанное с кэшем.
# Ответить
25. Serginio 18.02.2016 16:34
(23) Я же давал ссылку в 18. Исходники лежат в папке ТестВК
Ответили: (28)
# Ответить
26. Serginio 18.02.2016 16:41
Только там в public partial class Window1 : Window
нужно добавить

public static void СоздатьОкно(dynamic модуль1С, dynamic Object1C)
        {
            модуль1С.СообщитьСтр("Зашли в метод");
            var окно = new Window1(модуль1С, Object1C);
            окно.Show();
            модуль1С.СообщитьСтр("Форма открыта");
        }
...Показать Скрыть
Ответили: (29)
# Ответить
27. Serginio 18.02.2016 16:57
26+ Исходник есть в этой статье http://infostart.ru/public/457898/
Ответили: (30)
# Ответить
28. avz_1C 18.02.2016 18:21
(25) Serginio,

Да, спасибо. Нашел эту папку.
# Ответить
29. avz_1C 18.02.2016 18:22
(26) Serginio,

Спасибо, понял.

Сейчас попытаюсь.
# Ответить
30. avz_1C 18.02.2016 18:44
(27) Serginio,

Да, все получилось. Метод СоздатьОкно(dynamic модуль1С, dynamic Object1C)

работает отлично.

Ошибка с диагнозом

"Неизвестное имя формы: ХХХХХХХХХХХХХХХХХХХХХХХХ.Form"

не появляется при запуске в тонком клиенте.
Ответили: (31)
# Ответить
31. Serginio 19.02.2016 10:13
(30) Большое спасибо за использование и тестирование. Помню в 7 ке окно показывалось в списке окон, но при нажатии 1С вылетала. Видно 1С смотрит дочерние окна, но чужое окно она разрулить не может. Посмотрю.
# Ответить
32. avz_1C 19.02.2016 17:14
Спасибо за Ваш труд.

Никак не наиграюсь :-)

От перспектив захватывает дух.

Кстати, на *NIX-ах надо бы попробовать.

Вероятно, на Linux должно пойти, через Mono?

Или Mono не увидит под собой технологическую базу для Com Interop?

Хотя, вот тут говорят, что можно ...

http://www.mono-project.com/docs/advanced/pinvoke/

Надо потестировать.
Ответили: (36)
# Ответить
33. Serginio 19.02.2016 17:26
Эта библиотека основана на преобразование .Net объектов в IDispatch через Ireflect. На линуксе не взлетит
# Ответить
34. Serginio 20.02.2016 14:32
Очень часто приходится использовать битовую операци OR

например
 AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate



или
 watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite| NotifyFilters.FileName | NotifyFilters.DirectoryName;





Поэтому добавил метод OR. Теперь те же операции можно вызвать

DecompressionMethods= Врап.ПолучитьТип("System.Net.DecompressionMethods");
  handler.AutomaticDecompression=Врап.OR(DecompressionMethods.GZip,DecompressionMethods.Deflate) ;

или

NotifyFilters=врап.ПолучитьТип("System.IO.NotifyFilters");
    рез=Врап.OR(NotifyFilters.LastAccess,NotifyFilters.LastWrite,NotifyFilters.FileName,NotifyFilters.DirectoryName);
# Ответить
35. Serginio 21.02.2016 08:12
Пример алгоритма сжатия строки и результат в Base64 и обратный процесс

стр = "Строка для теста компрессии декомпрессии";
	
	// Получим используемые типы
	MemoryStream=Врап.ПолучитьТип("System.IO.MemoryStream");
	UTF8=Врап.ПолучитьТип("System.Text.Encoding").UTF8;
	CompressionMode = врап.ПолучитьТип("System.IO.Compression.CompressionMode");
	
	
	СжатыйПоток = врап.СоздатьОбъект(MemoryStream); //Поток куда запишутся сжатые данные
	
	
	zipStr = врап.СоздатьОбъект("System.IO.Compression.GZipStream", СжатыйПоток, CompressionMode.Compress);
	
	МассивДанных= UTF8.GetBytes(стр);// Получим массив данных используя кодировку  UTF8
	ПотокДляСжатия = Врап.СоздатьОбъект(MemoryStream,МассивДанных);  // Создадим поток из массива данных

	ПотокДляСжатия.CopyTo(zipStr);
	zipStr.Flush(); // Сбросим данные в  СжатыйПоток
	zipStr.Close(); // Закроем  GZipStream
	compressed = СжатыйПоток.ToArray(); // Получим массив байт сжатых данных

	Convert=Врап.ПолучитьТип("System.Convert");
	стр64=Convert.ToBase64String(compressed); // Переведем сжатые данные в Base64
	//Сообщить(стр64);
...Показать Скрыть



и обратный процесс


//===== Процесс разжатия данных из строки кодированной алгоритмом Base64	
	
compressed=Convert.FromBase64String(стр64);

ПотокСжатыхДанных = врап.СоздатьОбъект(MemoryStream,compressed);
GZipПоток =врап.СоздатьОбъект("System.IO.Compression.GZipStream",ПотокСжатыхДанных, CompressionMode.Decompress);
ПотокРазжатыхДанных = врап.СоздатьОбъект(MemoryStream);
GZipПоток.CopyTo(ПотокРазжатыхДанных);
Данные=ПотокРазжатыхДанных.ToArray();
 output = UTF8.GetString(Данные);

	Сообщить(output);
...Показать Скрыть
# Ответить
36. Serginio 26.02.2016 16:11
(32) Это вызов натива из манагед.
А вот обратно нужно что типа CLR Hosting API
Ответили: (37)
# Ответить
37. avz_1C 26.02.2016 19:22
(36) Пытался провернуть такое на .NET Compact Framework 3.5 ...
Не взлетело.
Ответили: (38)
# Ответить
38. Serginio 26.02.2016 19:33
(37) Сейчас в фаворе Universal Windows Platform
Ответили: (39)
# Ответить
39. avz_1C 27.02.2016 15:32
(38) Приходится работать с CF3.5, так как на ТСД Motorola Symbol (все остальные бренды - копии той или иной степени копийности) в основном установлены Windows CE или Windows Mobile. Пока только китайские китайцы пытаются клепать ТСД и прочие POS девайсы на Windows Phone 8 и даже Windows 10. Нет желающих переделывать отлаженные логистические цепочки под использование экспериментальных образцов. Нет заказчиков - нет разработок.
Ответили: (40)
# Ответить
40. Serginio 27.02.2016 17:28
(39) Согласен у самого под рукой Casio под Win CE. C Compact FW конечно пришлось повозиться. Но когда появились наработки затем писать уже намного легче.
Ответили: (41)
# Ответить
41. avz_1C 28.02.2016 15:29
(40) И, может быть, хорошо, что в промышленном оборудовании (ТСД например) нет такого стремительного мелькания техники и технологий, как в товарах группы "Б". Иначе бы все рухнуло. Доля консерватизма необходима в группе "А", не может быть базис текучим и непредсказуемым.
# Ответить
42. Serginio 15.03.2016 14:52
Понадобилоссь прописать дефолтный принтер в 7 ке

врап=СоздатьОбъект("NetObjectToIDispatch45"); 

    врап.УстЭтоСемерка();
    

Registry=Врап.ПолучитьТип("Microsoft.Win32.Registry");


Ключ="Software\1C\1Cv7\7.7\ИмяБазы\V7\"+ИмяПользователя()+"\Moxel\";
Сообщить(Ключ);
key = Registry.CurrentUser.OpenSubKey(Ключ);
ОсновнойКлюч=СокрЛП(key.Name)+"\";

Ключи=key.GetSubKeyNames();


 Перечислимый=Врап.ПолучитьИнтерфейс(Ключи,"IEnumerable");
 Перечислитель=Перечислимый.GetEnumerator();
// На всякий случай приведем к Интерфейсу IEnumerator

 Перечислитель=Врап.ПолучитьИнтерфейс(Перечислитель,"IEnumerator");
// Теперь можем пройтись по коллекции

 
Пока Перечислитель.MoveNext()<>0 Цикл
//  Врап.ВСтроку вывоит строковое представление всех типов в том числе числовые, строки, неопределено

    Сообщить(Врап.ВСтроку(Перечислитель.Current));

    Ключ=ОсновнойКлюч+СокрЛП(Перечислитель.Current);
    ТекПринтер=Registry.GetValue(Ключ,"DefaultPrinter","");
    Сообщить(ТекПринтер);
    
    Если (Принтер<>"") и (ТекПринтер<>"") и (Принтер<>ТекПринтер) Тогда

        Registry.SetValue(Ключ,"DefaultPrinter",Принтер);
    КонецЕсли;
КонецЦикла;
...Показать Скрыть
# Ответить
43. olo_lo4 23.04.2016 20:01
Добрый день.
врап=новый COMОбъект("NetObjectToIDispatch45");

1С-ка пишет
Ошибка при вызове конструктора (COMОбъект)
врап=новый COMОбъект("NetObjectToIDispatch45");
по причине:
-2147221005(0x800401F3): Недопустимая строка с указанием класса

какие библиотеки нужно доустановить? спасибо
# Ответить
45. olo_lo4 23.04.2016 20:32
(44) не получается. можно для тех кто в бронепоезде черным по белому написать.спасибо
# Ответить
46. Serginio 23.04.2016 21:18
Вторая ссылка в шапке все написано
# Ответить
47. olo_lo4 23.04.2016 21:25
Для таких же как и я в подвоной лодке, для начала работы, скачиваете и распаковываете файл ФайлыNetObjectToIDispatch
далее в папке DLLNetObjetToIDispatch45 запускаем RegAsm.bat
либо из корня скаченного файла запускаем РегистрацияКомСервера.exe и выбираем NetObjetToIDispatch45.dll которая лежит в DLLNetObjetToIDispatch45

Взгляд со стороны, без обид:
у автора очень интересный и нужный контент, но подача просто швахт, разбираться в этом адском количестве ссылок и каше неразложенной инфы ...
Ответили: (48)
# Ответить
48. Serginio 23.04.2016 21:38
(47) В пианиста просим не стрелять - он играет как умеет.
# Ответить
Внимание! За постинг в данном форуме $m не начисляются.
Внимание! Для написания сообщения необходимо авторизоваться
Текст сообщения*
Прикрепить файл






IE 2016