Здрасьте!
Наверняка многие видели, что внутри исходников на языке C могут быть ассемблерные вставки:
Или на языке Pascal могут быть ассемблерные вставки:
Некоторые даже могут использовать asm в C#.
Подобное можно увидеть в различных ЯВУ.
Даже в 1С при работе с данными в СУБД очень часто используют вставки кода на языке запросов (отличном от основного языка по синтаксису и возможностям).
Пойдём дальше, копнём глубже и ... в 1С можно использовать вставки кода на языке C# (с применением внешней компоненты):
Пока это только концепт, но уже рабочий. С версии 2.0 это уже полноценное решение. Можно с помощью таких микроподпрограмм сильно расширить возможности работы в 1С. Например, ускорять тяжелые участки кода (т.к. 1с в алгоритмических задачах сильно проигрывает взрослым Языкам Высокого Уровня) или использовать алгоритмы, которые на 1с не написать за обозримое время.
Пока есть жесткие ограничения:
- во первых, компонента работает только через COM и только под Windows;
- во вторых, во встроенном коде на шарпе обязательно нужно использовать жёстко зашитые наименования для используемого пространства имён, имени класса и имени метода;
- в третьих, пока что не реализована передача значений между компонентой и кодом 1с;
- в четвертых, при написании чего-то большого придётся прибегать к различным ухищрениям, что даже простой вывод примитивного окна сообщений в Windows будет не так просто сделать.
// код для версии 1.0
ТекстПрограммыНаСиШарп = "
|using System;
|using System.Reflection;
|
|namespace CSCodeEvaler
|{
| public class CSCodeEvaler
| {
| public void EvalCode()
| {
| Assembly a = Assembly.Load(""System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"");
| Type classType = a.GetType(""System.Windows.Forms.MessageBox"");
| MethodInfo mi = classType.GetMethod(""Show"", new[] { typeof(string) });
| object[] par = new[] { ""Привет из 1С !"" };
| mi.Invoke(null, par);
| }
| }
|}
|";
// код для версии 2.0
Компонента.ClearSettings();
Компонента.References = "System.dll;System.Windows.Forms.dll";
Компонента.Parameter0 = "Привет из 1С!";
Компонента.Parameter1 = 100;
ТекстПрограммыНаСиШарп = "
|using System;
|using System.Windows.Forms;
|
|namespace CSCodeEvaler
|{
| public class CSCodeEvaler
| {
| public static void EvalCode(string msg, int p)
| {
| MessageBox.Show(msg + ""\nЭто работает на "" + p + ""%"");
| }
| }
|}
|";
Компонента.Run(ТекстПрограммыНаСиШарп);
Этот код нарисует окно:
Пока что это больше подходит для "поиграться" С версии 2.0 это подходит уже для полноценного применения, но если сообществу будет интересна данная тема, буду продолжать пилить дальше.
В приложенной обработке вы можете сами попробовать выполнить приведённый выше код. Также там есть примеры для использования в разных кейсах.
Протестировано на платформе 8.3.21.1644, но будет работать на любых платформах 8.2 и 8.3 .
Большое обновление! Версия 2.0 (от 21.04.2023)
- Реализована возможность передавать параметры в скрипт и получать результат из него (пока что поддерживаются только примитивные типы);
- Добавлена опция для передачи в скрипт ссылок (References) на библиотеки, в связи с чем отпадает необходимость использования отражения (Reflection) в коде, тем самым код становится короче и проще для понимания;
- Появилась возможность писать короткие односложные скрипты без пространства имён, наименования класса и метода (код будет исполняться в жёстко заданных namespace CSCodeEvaler -> class CSCodeEvaler -> void EvalCode());
- Можно использовать статические классы;
- Добавлен подсчет времени компиляции и выполнения скрипта.
Например, для запуска любой программы достаточно написать
ТекстПрограммыНаСиШарп = "
|string path = @""Folder\program.exe"";
|System.Diagnostics.Process.Start(path);
|";
Компонента.RunScript(ТекстПрограммыНаСиШарп);
А для получения файла внутри GZip архива поможет такой код
Компонента.ClearSettings();
ПутьАрхива = "G:\db.gz";
Компонента.Parameter0 = ПутьАрхива;
ТекстПрограммыНаСиШарп = "
|using System;
|using System.IO;
|using System.IO.Compression;
|
|namespace CSCodeEvaler
|{
| public class CSCodeEvaler
| {
| public static byte[] EvalCode(string path)
| {
| FileStream fs = new FileStream(path, FileMode.OpenOrCreate);
| byte[] gzip = new byte[(int)fs.Length];
| fs.Read(gzip, 0, (int)fs.Length);
|
| byte[] bin;
|
| using (MemoryStream sourceStream = new MemoryStream(gzip))
| using (MemoryStream targetStream = new MemoryStream())
| using (GZipStream decompressionStream = new GZipStream(sourceStream, CompressionMode.Decompress))
| {
| decompressionStream.CopyTo(targetStream);
| bin = targetStream.ToArray();
| }
|
| return bin;
| }
| }
|}
|";
Компонента.Run(ТекстПрограммыНаСиШарп);
ИзвлеченныйФайл = Компонента.Result;
Для регистрации компоненты выполните
regasm OneSharp.dll /tlb /codebase
* нужны админские права. RegAsm.exe найдёте в C:\Windows\Microsoft.NET\Framework\v4.0.30319\
Разработано в MS Visual Studio Community 2019 под .NET Framework 4.8.1
Это моя 20-я юбилейная публикация. Не забывайте заходить в мой профиль, там вы найдёте ещё более интересные и практичные разработки, связанные с около 1с.
Зacим oтклaнивaюcь!