.NET(C#) для 1С. Динамическая компиляция класса обертки для использования .Net событий в 1С через ДобавитьОбработчик или ОбработкаВнешнегоСобытия

Публикация № 417830 12.11.15

Приемы и методы разработки - Разработка внешних компонент

.Net C# event DynamicMethod

Динамическая компиляция класса обертки для использования .Net событий в 1С через ДобавитьОбработчик или ОбработкаВнешнегоСобытия, а так же генерация модулей на C# и 1С для подключения к событиям. Использование DynamicMethod и ILGenerator. Представлены примеры для использовании событий System.IO.FileSystemWatcher (Ожидает уведомления файловой системы об изменениях и инициирует события при изменениях каталога или файла в каталоге.) и SerialPort (обработка сканера штрих кода подключенного к COM порту). Обертка позволяет использовать классы .Net только на языке 1С. Реализация 1C Messenger описанного здесь http://infostart.ru/public/434771/

 Эта статья является дополнением разработки Использование сборок .NET в 1С 7.x b 8.x находящейся здесь //infostart.ru/public/238584/

 

Как то раз пришлось написать интеграцию 1С с WhatsApp. А там порядка 30 событий.

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

Не поленился и написал кодогенератор.

Рассмотрим генерацию кода на примере System.IO.FileSystemWatcher

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

 

using System;

using System.Runtime.InteropServices;

using System.Windows.Forms;

using System.Threading;

using System.Threading.Tasks;

 

 

[ComVisible(true)]

[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]

[Guid("6821a54a-19a2-4e66-85d9-e65396958080")]

public interface IВрапперДляSystem_IO_FileSystemWatcher

{

 

    [DispId(0x00000001)]

    void ОшибкаСобытия(Stringсобытие, object value, objectисключение);

    [DispId(0x00000002)]

    void Changed(object value);

    [DispId(0x00000003)]

    void Created(object value);

    [DispId(0x00000004)]

    void Deleted(object value);

    [DispId(0x00000005)]

    void Error(object value);

    [DispId(0x00000006)]

    void Renamed(object value);

    [DispId(0x00000007)]

    void Disposed(object value);

 

}

 

 

[ComVisible(true)]

[ClassInterface(ClassInterfaceType.AutoDual)]

[Guid("c3919804-ff5f-4d2a-a773-5067a1e051e1")]

[ComSourceInterfaces(typeof(IВрапперДляSystem_IO_FileSystemWatcher))]

public class ВрапперДляSystem_IO_FileSystemWatcher

{

 

    [ComVisible(false)]

    public delegate void Событие_Delgate();

    [ComVisible(false)]

    public delegate void СобытиеСПараметром_Delgate(object value);

    [ComVisible(false)]

    public  delegate void СобытиеСПараметрами_Delgate(Stringсобытие, object value, objectисключение);

 

    public System.IO.FileSystemWatcher РеальныйОбъект;

    dynamic AutoWrap;

    private SynchronizationContext Sc;

    public event СобытиеСПараметрами_Delgate ОшибкаСобытия;

    public Exception ПоследняяОшибка;

    public event СобытиеСПараметром_Delgate Changed;

    public event СобытиеСПараметром_Delgate Created;

    public event СобытиеСПараметром_Delgate Deleted;

    public event СобытиеСПараметром_Delgate Error;

    public event СобытиеСПараметром_Delgate Renamed;

    public event СобытиеСПараметром_Delgate Disposed;

 

    private Object thisLock = newObject();

 

 

    void ОтослатьСобытие(Событие_Delgate Событие, string ИмяСобытия)

    {

 

 

        Task.Run(() =>

        {

            if (Событие != null) //Событие();

            {

                lock (thisLock)

                {

 

                    try

                    {

                        Sc.Send(d => Событие(), null);

                    }

 

                    catch (Exception ex)

                    {

                        try

                        {

 

                            Sc.Send(d => ОшибкаСобытия(ИмяСобытия, null, AutoWrap.ОбернутьОбъект(ex)), null);

                        }

                        catch (Exception)

                        {

                        }

 

                    }

                }

            }

        });

    }

 

    void ОтослатьСобытиеСПараметром(СобытиеСПараметром_Delgate Событие, object value, string ИмяСобытия)

    {

        Task.Run(() =>

        {

 

 

            if (Событие != null) //Событие();

            {

                lock (thisLock)

                {

                    try

                    {

                        Sc.Send(d => Событие(AutoWrap.ОбернутьОбъект(value)), null);

                    }

                    catch (Exception ex)

                    {

                        try

                        {

 

                            Sc.Send(d => ОшибкаСобытия(ИмяСобытия, AutoWrap.ОбернутьОбъект(value), AutoWrap.ОбернутьОбъект(ex)), null);

                        }

                        catch (Exception)

                        {

                        }

                    }

 

                }

            }

        });

 

 

    }

    public ВрапперДляSystem_IO_FileSystemWatcher(object AutoWrap, System.IO.FileSystemWatcher РеальныйОбъект)

    {

 

        if (SynchronizationContext.Current == null)

            SynchronizationContext.SetSynchronizationContext(new WindowsFormsSynchronizationContext());

 

        Sc = SynchronizationContext.Current;

 

 

        this.РеальныйОбъект = РеальныйОбъект;

        this.AutoWrap = AutoWrap;

        РеальныйОбъект.Changed += (sender, e) =>

        {

 

            ОтослатьСобытиеСПараметром(Changed, new { sender = sender, e = e }, "Changed");

        };

 

        РеальныйОбъект.Created += (sender, e) =>

        {

 

            ОтослатьСобытиеСПараметром(Created, new { sender = sender, e = e }, "Created");

        };

 

        РеальныйОбъект.Deleted += (sender, e) =>

        {

 

            ОтослатьСобытиеСПараметром(Deleted, new { sender = sender, e = e }, "Deleted");

        };

 

        РеальныйОбъект.Error += (sender, e) =>

        {

 

            ОтослатьСобытиеСПараметром(Error, new { sender = sender, e = e }, "Error");

        };

 

        РеальныйОбъект.Renamed += (sender, e) =>

        {

 

            ОтослатьСобытиеСПараметром(Renamed, new { sender = sender, e = e }, "Renamed");

        };

 

        РеальныйОбъект.Disposed += (sender, e) =>

        {

 

            ОтослатьСобытиеСПараметром(Disposed, new { sender = sender, e = e }, "Disposed");

        };

 

 

    }

 

    public static object СоздатьОбъект(object AutoWrap, System.IO.FileSystemWatcher РеальныйОбъект)

    {

 

        return new ВрапперДляSystem_IO_FileSystemWatcher(AutoWrap, РеальныйОбъект);

    }

}

Так для упрощения, если параметров больше одного они упаковываются в анонимный класс.

Для вызова событий вызывается один из двух метод для всех событий с параметром и без.

Для вызова события в 1С используется SynchronizationContext для вызова в потоке 1С приложения.

Используется синхронизация на всякий случай и при возникновении ошибки при вызове метода 1С вызывается событие ОшибкаСобытия, так как такие ошибки 1С 8.х не отлавливает без секции попытка-исключение.

Параметры оборачиваются в объект типа AutoWrap  с помощью  AutoWrap.ОбернутьОбъект для использования объектов Net как объектов автоматизации

Модуль для 8 ки формируется такой

 

Перемврап,ОберткаСобытий;

Процедура СоздатьОбертку(объект)
 
//Динамически компилируется модуль C#
ОберткаСобытий=врап.СоздатьОберткуДляСобытий(объект);
// Добавляются обработчики
ДобавитьОбработчик ОберткаСобытий.ОшибкаСобытия,ОшибкаСобытия;


ДобавитьОбработчик ОберткаСобытий.Changed, Changed;
ДобавитьОбработчик ОберткаСобытий.Created, Created;
ДобавитьОбработчик ОберткаСобытий.Deleted, Deleted;
ДобавитьОбработчик ОберткаСобытий.Error, Error;
ДобавитьОбработчик ОберткаСобытий.Renamed, Renamed;
ДобавитьОбработчик ОберткаСобытий.Disposed, Disposed;
КонецПроцедуры
// Дается описание параметров, чтобы было проще к ним обращаться


//ИмяСобытия:String Имя События в котором произошло исключение
//Данные:object Параметры события
//ИсключениеСобытия:Exception Ошибка произошедшая при вызове события
Процедура ОшибкаСобытия(ИмяСобытия,Данные,ИсключениеСобытия)
    Сообщить("Не обработано событие "+ИмяСобытия);
     Сообщить(" Исключение "+Врап.ВСтроку(ИсключениеСобытия));
 Сообщить(" Данные "+Врап.ВСтроку(Данные));
            КонецПроцедуры
//  параметр Данные:Аннимный Тип
                       // Свойства параметра
// sender:System.Object
// e:System.IO.FileSystemEventArgs

            Процедура Changed(Данные)
               Сообщить("Changed "+Врап.ВСтроку(Данные));
            КонецПроцедуры

//  параметр Данные:Аннимный Тип
                       // Свойства параметра
// sender:System.Object
// e:System.IO.FileSystemEventArgs

            Процедура Created(Данные)
               Сообщить("Created "+Врап.ВСтроку(Данные));
            КонецПроцедуры

//  параметр Данные:Аннимный Тип
                       // Свойства параметра
// sender:System.Object
// e:System.IO.FileSystemEventArgs

            Процедура Deleted(Данные)
               Сообщить("Deleted "+Врап.ВСтроку(Данные));
            КонецПроцедуры

//  параметр Данные:Аннимный Тип
                       // Свойства параметра
// sender:System.Object
// e:System.IO.ErrorEventArgs

            Процедура Error(Данные)
               Сообщить("Error "+Врап.ВСтроку(Данные));
            КонецПроцедуры

//  параметр Данные:Аннимный Тип
                       // Свойства параметра
// sender:System.Object
// e:System.IO.RenamedEventArgs

            Процедура Renamed(Данные)
               Сообщить("Renamed "+Врап.ВСтроку(Данные));
            КонецПроцедуры

//  параметр Данные:Аннимный Тип
                       // Свойства параметра
// sender:System.Object
// e:System.EventArgs

            Процедура Disposed(Данные)
               Сообщить("Disposed "+Врап.ВСтроку(Данные));
            КонецПроцедуры

 

Так как в 7.7 нет возможности использования комовских событий, сделал обертку с использование вызова IAsyncEvent метода ExternalEvent

 

 

using System;

using System.Runtime.InteropServices;

using System.Windows.Forms;

using System.Threading;

using System.Threading.Tasks;

 

[Guid("ab634004-f13d-11d0-a459-004095e1daea"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]

public interface IAsyncEvent

{

    void SetEventBufferDepth(int lDepth);

    void GetEventBufferDepth(refint plDepth);

    void ExternalEvent(string bstrSource, string bstrMessage, string bstrData);

    void CleanBuffer();

}

 

public class ВрапперДляSystem_IO_FileSystemWatcher77

{

    System.IO.FileSystemWatcher РеальныйОбъект;

    publicobject Changed;

    publicobject Created;

    publicobject Deleted;

    publicobject Error;

    publicobject Renamed;

    publicobject Disposed;

 

 

    dynamic AutoWrap;

    private SynchronizationContext Sc;

    IAsyncEvent СобытиеДля1С;

    privateObject thisLock = newObject();

    public object ПоследняяОшибка;

    public ВрапперДляSystem_IO_FileSystemWatcher77(object AutoWrap, ObjectГлобальныйКонтекст, System.IO.FileSystemWatcher РеальныйОбъект)

    {

 

        СобытиеДля1С = ГлобальныйКонтекст as IAsyncEvent;

        if (SynchronizationContext.Current == null)

            SynchronizationContext.SetSynchronizationContext(new WindowsFormsSynchronizationContext());

 

        Sc = SynchronizationContext.Current;

 

 

        this.РеальныйОбъект = РеальныйОбъект;

        this.AutoWrap = AutoWrap;

        РеальныйОбъект.Changed += (sender, e) =>

        {

            Changed = new { sender = sender, e = e };

            ОтослатьСобытие("Changed");

        };

 

        РеальныйОбъект.Created += (sender, e) =>

                    {

                        Created = new { sender = sender, e = e };

                        ОтослатьСобытие("Created");

                    };

 

        РеальныйОбъект.Deleted += (sender, e) =>

                    {

                        Deleted = new { sender = sender, e = e };

                        ОтослатьСобытие("Deleted");

                    };

 

        РеальныйОбъект.Error += (sender, e) =>

                    {

                        Error = new { sender = sender, e = e };

                        ОтослатьСобытие("Error");

                    };

 

        РеальныйОбъект.Renamed += (sender, e) =>

                    {

                        Renamed = new { sender = sender, e = e };

                        ОтослатьСобытие("Renamed");

                    };

 

        РеальныйОбъект.Disposed += (sender, e) =>

                    {

                        Disposed = new { sender = sender, e = e };

                        ОтослатьСобытие("Disposed");

                    };

 

 

 

    }

 

    void ОтослатьСобытие(string ИмяСобытия)

    {

 

 

        Task.Run(() =>

        {

 

            lock (thisLock)

            {

 

                try

                {

                    Sc.Send(d => СобытиеДля1С.ExternalEvent("System_IO_FileSystemWatcher", ИмяСобытия, ""), null);

                }

 

                catch (Exception ex)

                {

                    try

                    {

                        ПоследняяОшибка = new { Событие = ИмяСобытия, Исключение = ex };

                        Sc.Send(d => СобытиеДля1С.ExternalEvent("System_IO_FileSystemWatcher", "ОшибкаСобытия", ""), null);

                    }

                    catch (Exception)

                    {

                    }

 

                }

            }

 

        });

    }

 

    public static object СоздатьОбъект(object AutoWrap, Object ГлобальныйКонтекст, System.IO.FileSystemWatcher РеальныйОбъект)

    {

 

        return new ВрапперДляSystem_IO_FileSystemWatcher77(AutoWrap, ГлобальныйКонтекст, РеальныйОбъект);

    }

}

 

 

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

Отмечу, что в данном случае объекты не оборачиваются в AutoWrap, так как обертка возвращается как AutoWrap. Поясню чуть позже

Перемврап,ОберткаСобытий;

Функция СоздатьОбертку(ОбертываемыйОбъект)

// В NetObjetToIDispatch.dllреализованклассВКpublicclassGlobalContext1C :IInitDone, ILanguageExtender

//для получения глобального контекста при вызове

// publicvoid Init([MarshalAs(UnmanagedType.IDispatch)]
//     object connection)
//    {
//        глобальныйКонтекст = connection;
//        Marshal.GetIUnknownForObject(глобальныйКонтекст);
//  }

 
    ПодключитьВнешнююКомпоненту("AddIn.GlobalContext1C");
    объект = СоздатьОбъект("AddIn.GlobalContext1C");
    ГлобальныйКонтекст= объект.ГлобальныйКонтекст;

    ОберткаСобытий= врап.СоздатьОберткуДляСобытий77(ОбертываемыйОбъект,ГлобальныйКонтекст);
КонецФункции // СоздатьОбертку



// Свойства ОберткаСобытий.ПоследняяОшибка
//Событие:String Имя События в котором произошло исключение
//Данные:object Параметры события
//ИсключениеСобытия:Exception Ошибка произошедшая при вызове события
Функция ОшибкаСобытия()
    ПоследняяОшибка=ОберткаСобытий.ПоследняяОшибка;
    Сообщить("Не обработано событие "+ПоследняяОшибка.Событие);
    Сообщить(Врап.ВСтроку(Шаблон("[ОберткаСобытий." + ПоследняяОшибка.Событие+ "]")));
    Сообщить("Ошибка");
    Сообщить(врап.ВСтроку(ПоследняяОшибка.Исключение))
КонецФункции
//  Свойства ОберткаСобытий.Changed
// sender:System.Object
// e:System.IO.FileSystemEventArgs

Функция Changed()
    Сообщить("Changed "+Врап.ВСтроку(ОберткаСобытий.Changed));
КонецФункции

//  Свойства ОберткаСобытий.Created
// sender:System.Object
// e:System.IO.FileSystemEventArgs

Функция Created()
    Сообщить("Created "+Врап.ВСтроку(ОберткаСобытий.Created));
КонецФункции

//  Свойства ОберткаСобытий.Deleted
// sender:System.Object
// e:System.IO.FileSystemEventArgs

Функция Deleted()
    Сообщить("Deleted "+Врап.ВСтроку(ОберткаСобытий.Deleted));
КонецФункции

//  Свойства ОберткаСобытий.Error
// sender:System.Object
// e:System.IO.ErrorEventArgs

Функция Error()
    Сообщить("Error "+Врап.ВСтроку(ОберткаСобытий.Error));
КонецФункции

//  Свойства ОберткаСобытий.Renamed
// sender:System.Object
// e:System.IO.RenamedEventArgs

Функция Renamed()
    Сообщить("Renamed "+Врап.ВСтроку(ОберткаСобытий.Renamed));
КонецФункции

//  Свойства ОберткаСобытий.Disposed
// sender:System.Object
// e:System.EventArgs

Функция Disposed()
    Сообщить("Disposed "+Врап.ВСтроку(ОберткаСобытий.Disposed));
КонецФункции




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

КонецПроцедуры // ПриОткрытии
//======================================================================
Процедура ОбработкаВнешнегоСобытия(Источник, ИмяСобытия, Данные)
    Если Источник = "System_IO_FileSystemWatcher" Тогда

        Шаблон("[" + ИмяСобытия+ "()]");
    КонецЕсли;
КонецПроцедуры // ОбработкаВнешнегоСобытия

Динамическая компиляция происходит следующим образом

 

public class КомВраперДляСобытий<T>

        {

        private static MethodInfo cоздательОбертки = null;

        private static MethodInfo cоздательОбертки77 = null;

 

       static CompilerResults СкомпилироватьОбертку(string строкаКласса,string ИмяКласса)

        {

           

          

            bool ЭтоСборкаГак = typeof(T).Assembly.GlobalAssemblyCache;

            string Путь = Path.GetDirectoryName(typeof(T).Assembly.Location);

           

 

 

            string OutputAssembly = Path.Combine(Путь, ИмяКласса) + ".dll";

       

         

            var compiler = new CSharpCodeProvider();

            var parameters = new CompilerParameters();

 

            parameters.ReferencedAssemblies.Add("System.dll");

            parameters.ReferencedAssemblies.Add("System.Core.dll");

            parameters.ReferencedAssemblies.Add("Microsoft.CSharp.dll");

            parameters.ReferencedAssemblies.Add("System.Windows.Forms.dll");

            parameters.ReferencedAssemblies.Add(typeof(AutoWrap).Assembly.Location);

 

            if (!ЭтоСборкаГак)

                parameters.ReferencedAssemblies.Add(typeof(T).Assembly.Location);

            else

            {

                string ИмяСборки = typeof(T).Assembly.ManifestModule.Name;

                if (parameters.ReferencedAssemblies.IndexOf(ИмяСборки) == -1)

                    parameters.ReferencedAssemblies.Add(ИмяСборки);

 

 

            }

 

            if (ЭтоСборкаГак)

                parameters.GenerateInMemory = true;

            else

            { //  parameters.GenerateInMemory = true;

                parameters.GenerateInMemory = false;

                parameters.OutputAssembly = OutputAssembly;

            }

 

            parameters.GenerateExecutable = false;

            parameters.IncludeDebugInformation = true;

 

            var res = compiler.CompileAssemblyFromSource(parameters, строкаКласса);

            return res;

        }

        public static MethodInfo СоздательОбертки { get {

                if (cоздательОбертки==null)

                {

                    Type типРеальногоОбъекта = typeof(T);

                    string ТипСтрРеальногоОбъекта = типРеальногоОбъекта.FullName;

                    var ИмяКласса = "ВрапперДля" + ТипСтрРеальногоОбъекта.Replace(".", "_").Replace("+", "_");

                   string  строкаКласса = ДляСозданияМодуляВрапераоздатьОписания(типРеальногоОбъекта);

                    var res = СкомпилироватьОбертку(строкаКласса,ИмяКласса);

 

                    Type тип = res.CompiledAssembly.GetType(ИмяКласса);

                    MethodInfo mi = тип.GetMethod("СоздатьОбъект", new Type[]{typeof(object),типРеальногоОбъекта });

                   

                    cоздательОбертки = mi;

                }

 

                return cоздательОбертки;

            } }

 

        public static MethodInfo СоздательОбертки77

        {

            get

            {

                if (cоздательОбертки77 == null)

                {

                    Type типРеальногоОбъекта = typeof(T);

                    string ТипСтрРеальногоОбъекта = типРеальногоОбъекта.FullName;

                    var ИмяКласса = "ВрапперДля" + ТипСтрРеальногоОбъекта.Replace(".", "_").Replace("+", "_")+"77";

                    string строкаКласса = ДляСозданияМодуляВрапераоздатьОписания77(типРеальногоОбъекта);

                    var res = СкомпилироватьОбертку(строкаКласса, ИмяКласса);

 

                    Type тип = res.CompiledAssembly.GetType(ИмяКласса);

                    MethodInfo mi = тип.GetMethod("СоздатьОбъект", new Type[] { typeof(object), typeof(object), типРеальногоОбъекта });

 

                    cоздательОбертки77 = mi;

                }

 

                return cоздательОбертки77;

            }

        }

 

Так, чтобы лишний раз не компилировать, закэшируем результат компиляции через свойство дженерик класса. Реализацию этого класса Net будет создавать при первом обращении, а статические поля будем заполнять компиляцией динамически создаваемого модуля на C# только раз для каждого типа.

Так, для GAC сборок можно компилировать сборку в памяти. Для не гаковских сборок нужно указывать путь, где лежит сборка оборачиваемого типа.

 

Вызов из 1С происходит с помощью 2 методов СоздатьОберткуДляСобытий или СоздатьОберткуДляСобытий77

MethodInfo ПолучитьMethodInfoОберткиСобытий(string ИмяСвойства, object РеальныйОбъект)

        {

 

//      получаем дженерик тип КомВраперДляСобытий<> и указывем тип

 

            Type тип = РеальныйОбъект.GetType();

            Type genType = typeof(КомВраперДляСобытий<>);

            Type constructed = genType.MakeGenericType(new Type[] { тип });

 

            // Nowнаходим свойство и получаем его значение

            PropertyInfo pi = constructed.GetProperty(ИмяСвойства);

            MethodInfo функция = (MethodInfo)pi.GetValue(null, null);

            return функция;

 

        }

        public object СоздатьОберткуДляСобытий(object объект)

        {

 

            object РеальныйОбъект = AutoWrap.ПолучитьРеальныйОбъект(объект);

            var функция = ПолучитьMethodInfoОберткиСобытий("СоздательОбертки", РеальныйОбъект);

            object обертка = функция.Invoke(null,new object[] { this,РеальныйОбъект });

// Возвращаем реальный объект, так как он является COM объектом

            return обертка;

 

        }

        public object СоздатьОберткуДляСобытий77(object объект, object ГлобальныйКонтекст)

        {

 

            object РеальныйОбъект = AutoWrap.ПолучитьРеальныйОбъект(объект);

            var функция = ПолучитьMethodInfoОберткиСобытий("СоздательОбертки77", РеальныйОбъект);

            object обертка = функция.Invoke(null, new object[] {ГлобальныйКонтекстеальныйОбъект });

// Оборачиваем обертку событий в AutoWrap для использования в 1С как объекта автоматизации

            return AutoWrap.ОбернутьОбъект(обертка);

 

        }

 

Кроме того, можно использовать DynamicMethod. В отличие от динамической компиляции сборки,  определяет и представляет динамический метод, который может быть скомпилирован, выполнен и удалендаленные методы доступны для сборки мусора.

 

Так, в 1С нет операторов для битовых операций.  Для работы с FileSystemWatcher

Нам нужно определить события которые мы хотим отслеживать. На C# это выглядит так.

watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite

                   | NotifyFilters.FileName | NotifyFilters.DirectoryName;

 

Создадим функцию в C# проекте

public static NotifyFilters OR(NotifyFilters val1, NotifyFilters val2)

        {

 

            return val1 | val2;

        }

Скомпилирует

В ILSpyнайдемнашметодивыберемязыкдекомпиляции IL

.method public hidebysig static 
    valuetype [System]System.IO.NotifyFilters OR (
        valuetype [System]System.IO.NotifyFilters val1,
        valuetype [System]System.IO.NotifyFilters val2
    ) cil managed 
{
    // Method begins at RVA 0x20cc
    // Code size 9 (0x9)
    .maxstack 2
    .locals init (
        [0] valuetype [System]System.IO.NotifyFilters
    )

    IL_0000: nop
    IL_0001: ldarg.0
    IL_0002: ldarg.1
    IL_0003: or
    IL_0004: stloc.0
    IL_0005: br.s IL_0007

    IL_0007: ldloc.0
    IL_0008: ret
} // end of method MainWindow::OR

 

Для получения кода на MSIL можно использовать:

 Для рефлектора есть дизассемблер в Reflection.Emit, можно попытать щастья с expression trees (exp trees и emit состыковываются через CompileToMethod)

Также рекомендую вводную серию статей — тынц.

http://rsdn.ru/forum/dotnet/6235398.1

Большая благодарность Sinix

Так, используя старый Reflector и плагин ReflectionEmitLanguage.zip  можно получить следующий код

 

public MethodBuilder BuildMethodOR(TypeBuilder
type)
{
    // Declaring method builder
    // Method attributes
    System.Reflection.MethodAttributes methodAttributes = 
          System.Reflection.MethodAttributes.Public
        | System.Reflection.MethodAttributes.HideBySig
        | System.Reflection.MethodAttributes.Static;
    MethodBuildermethod = type.DefineMethod("OR", methodAttributes);
    // Preparing Reflection instances
    // Setting return type
    method.SetReturnType(typeof(NotifyFilters));
    // Adding parameters
    method.SetParameters(
        typeof(NotifyFilters),
        typeof(NotifyFilters)
        );
    // Parameter val1
    ParameterBuilderval1 =  method.DefineParameter(1, ParameterAttributes.None, "val1");
    // Parameter val2
    ParameterBuilderval2 =  method.DefineParameter(2, ParameterAttributes.None, "val2");
    ILGeneratorgen =  method.GetILGenerator();
    // Preparing locals
    LocalBuilderfilters =  gen.DeclareLocal(typeof(NotifyFilters));
    // Preparing labels
    Labellabel7 =  gen.DefineLabel();
    // Writing body
    gen.Emit(OpCodes.Nop);
    gen.Emit(OpCodes.Ldarg_0);
    gen.Emit(OpCodes.Ldarg_1);
    gen.Emit(OpCodes.Or);
    gen.Emit(OpCodes.Stloc_0);
    gen.Emit(OpCodes.Br_S,label7);
    gen.MarkLabel(label7);
    gen.Emit(OpCodes.Ldloc_0);
    gen.Emit(OpCodes.Ret);
    // finished
    return method;

 

 

 

И соответственно напишем это все на языке 1С

Функция ПолучитьМетод()
  //"System.Func`3"

  NotifyFilters=врап.ПолучитьТип("System.IO.NotifyFilters");
  helloArgs=врап.СоздатьМассив(врап.ПолучитьТип("System.Type"),2);
  helloArgs.SetValue(NotifyFilters,0);
  helloArgs.SetValue(NotifyFilters,1);

  ТипДляМодуля=Врап.ТипКакОбъект(врап.ПолучитьТип("System.String"));
  hello= врап.СоздатьОбъект("System.Reflection.Emit.DynamicMethod","OR",
  NotifyFilters,
  helloArgs,
  ТипДляМодуля.Module);


  il= hello.GetILGenerator();


  il.DeclareLocal(NotifyFilters); 
  iL0007Label= il.DefineLabel();

  OpCodes=врап.ПолучитьТип("System.Reflection.Emit.OpCodes");
  
  il.Emit(OpCodes.Nop);
  il.Emit(OpCodes.Ldarg_0);
  il.Emit(OpCodes.Ldarg_1);

  il.Emit(OpCodes.Or);
  il.Emit(OpCodes.Stloc_0);
  il.Emit(OpCodes.Br_S, iL0007Label);
  il.MarkLabel(iL0007Label);
  il.Emit(OpCodes.Ldloc_0);
  il.Emit(OpCodes.Ret);
  тип = врап.ПолучитьТип("System.Func`3");
  типДелегата= Врап.ТипКакОбъект(тип).MakeGenericType(NotifyFilters,NotifyFilters,NotifyFilters);
  res= hello.CreateDelegate(типДелегата
  returnres

КонецФункции

Функция Или2(вал1,вал2)
  возврат врап.ВыполнитьДелегат(ДелегатИЛИ,вал1,вал2);
  //ДелегатИЛИ.DynamicInvoke(вал1,вал2);

КонецФункции// гл

Процедура КнопкаВыполнитьНажатие(Кнопка)
  // Вставить содержимое обработчика.
  Остановить();

    watcher= врап.СоздатьОбъект("System.IO.FileSystemWatcher, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");
    Директория="c:\tmp\";
    watcher.Path= Директория;
       // Only watch text files.

    ДелегатИЛИ=ПолучитьМетод();
    NotifyFilters=врап.ПолучитьТип("System.IO.NotifyFilters");
//watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
    //        | NotifyFilters.FileName | NotifyFilters.DirectoryName;
    рез=Или2(NotifyFilters.LastAccess,Или2(NotifyFilters.LastWrite,Или2(NotifyFilters.FileName,NotifyFilters.DirectoryName)));
    watcher.NotifyFilter=рез;
    watcher.Filter= "*.*";
    watcher.IncludeSubdirectories= true;

    watcher.EnableRaisingEvents= true;

    СоздатьОбертку(watcher);


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

 

Так полностью можно исключить внешние сборки. Мало того, сейчас на подходе релиз scripting api.

https://github.com/dotnet/roslyn/tree/master/src/Scripting/Core
Вот неплохое введение, всю серию статей можно смело читать, вредным не будет.

https://joshvarty.wordpress.com/2015/10/15/learn-roslyn-now-part-14-intro-to-the-scripting-api/


UPD. И ещё статья вдогонку.

http://daveaglick.com/posts/compiler-platform-scripting

То есть вместо IL можно использовать

 

 

 То есть использование .Net в 1С станет достаточно простым.

 

Напоследок приведу пример использоваиня SerialPort для считывания Штрих-Кода

 

sp= Врап.СоздатьОбъект("System.IO.Ports.SerialPort","COM" + НомерПорта);
   
ПИ="System.IO.Ports.";
   
sp.BaudRate= 9600;
   
sp.Parity= Врап.ПолучитьТип(ПИ+"Parity").None;
   
sp.StopBits= Врап.ПолучитьТип(ПИ+"StopBits").One;
   
sp.DataBits= 8;
   
sp.Handshake= Врап.ПолучитьТип(ПИ+"Handshake").None;

   
СоздатьОбертку(sp);
   
sp.Open();

 

и обработка события

 

Процедура DataReceived(Данные)
    sp1 = Данные.sender;
    ШтрихКод= sp1.ReadExisting();
    Компорт= sp1.PortName;
    Сообщить(СтрШаблон("ШК=%1 Порт=%2",ШтрихКод,Компорт));

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

 

К проверял через SerialRedirectorиспользуя программы //infostart.ru/public/14587/ .

Обработки для теста System.IO.FileSystemWatcher и получение текстов модулей для 1С и C# находятся в папке ВнешниеОтчеты

ТестКомпиляцииСобытий.ert

ТестСобытийИзмененийВДиректории.epf

TestSerialPort.epf для теста COM порта.

Специальные предложения

Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. shakmaev 346 13.11.15 11:45 Сейчас в теме
Беда с оформлением статьи, и куда только смотрят модераторы?
гвость; +1 Ответить
2. Serginio 908 13.11.15 12:04 Сейчас в теме
(1) А по существу? Просто править текст очень тяжело.
3. cool.vlad4 45 13.11.15 12:20 Сейчас в теме
(2) статья полезная. только (1) прав. код c# можно было на pastebin разместить, а здесь ссылку оставить. (часть кода ис распарсил в ссылки )
5. Serginio 908 13.11.15 13:03 Сейчас в теме
(3) Спасибо. Учту и попробую
(4) Спасибо.
4. gortol 197 13.11.15 12:29 Сейчас в теме
зато открывает возможности описания собственных событий, очень полезная информация, мне не хватило информации из интернета как раз для формирования собственных событий и передать их в 1с...
6. ivanov660 3594 15.11.15 12:44 Сейчас в теме
Довольно забавно получается - надо писать 1Сом Сишарп.
На мой взгляд:
1. Надо не забывать о правах пользователя под которым собирается и компилируется код.
2. Необходимо не забывать про обработку ошибок при динамической компиляции.
3. Про версии .net при которых возможно использование данных возможностей - где-то от 3.5+ и выше.
4. Можно было просто передать текстовый кусок кода (*.cs) и скомпилировать его на лету.
8. Serginio 908 15.11.15 13:12 Сейчас в теме
(6) ivanov660,
1. Про пользователей согласен. Надо будет озаботиться System.Security.Permissions
2. В статье рассматривается динамическая компиляция для создания оболочки для использования свойств. Там ошибок нет.
Но можно использовать CompilerResults.Errors при использовании CompileAssemblyFromSource
При использовании своего кода при использовании CSharpCodeProvider из 1С.
3. В данном случае применяется 4.5.2 При использовании scripting api. наверное уже будет использоваться 4.6
4. Это можно просто использовать http://infostart.ru/public/238584/ NetObjectToIDispatch45 и использовать CSharpCodeProvider со всеми свойствами итд
33. MherArsh 24 13.09.16 23:35 Сейчас в теме
Привет всем!
Может кто то вкурсе?
Я написал COM объект, зарегистрировал, все вроде норм но вылезает ошибка.
Вопрос в том что я использую стотонную библиотеку в моей сборке, но она ежит вместе с основным dll но я все ровно получаю ошибку.

{ВнешняяОбработка.ВнешняяОбработка1.Форма.Форма.Форма(8)}: Ошибка при вызове метода контекста (Login): Произошла исключительная ситуация (TestNative): Не удалось загрузить файл или сборку "RestSharp, Version=105.2.3.0, Culture=neutral, PublicKeyToken=null" либо одну из их зависимостей. Требуется сборка со строгим именем. (Исключение из HRESULT: 0x80131044)

7. delete 250 15.11.15 13:06 Сейчас в теме
То есть использование .Net в 1С станет достаточно простым.

Куда уж проще то (*сарказм*)

имхо, статья неплоха, но как-то написана больше для тех, кто в теме
ну и из-за оформления читать приходится через боль)
9. Serginio 908 15.11.15 13:22 Сейчас в теме
(7) delete, Ну ты же в теме. Да проблема в том, что мало 1С ников знает .Net и в частности C#. Это статья дополнение к http://infostart.ru/public/238584/ и сводится к использованию нетовских событий к использованию одной строчки
ОберткаСобытий=врап.СоздатьОберткуДляСобытий(объект);

Все остальное, это рассказ о том как формируется реальный код. То есть, для тех кому это интересно и использовать сгенеренный код для дальнейшей модификации или как использовать обвязку нетовских свойств для использования через ДобавитьОбработчик или ОбработкаВнешнегоСобытия. Думаю многим это будет полезным. За оформление прошу прощения. Спешил, да и дизайнерские способности у меня невысокие
10. cool.vlad4 45 15.11.15 23:13 Сейчас в теме
(9) да дизайнерские способности ни причем. я например вообще не хочу публиковать статьи на ис, поскольку публикация это боль (у меня процессор так грузился как не зная что, но может с тех пор ситуация изменилась) , ну и форматирование там так себе. насчет статьи, я напимер в теме. (некоторые свои вк, кстати публиковал, опять же по причине движка ис в комментах). но имхо с com есть некоторый геморрой при деплое. например, мне были бы интереснее вещи касательно обмена данных, генерации всяких dto между приложением на C# (какой-нибудь сервис) и 1С. тут нет никакой магии , но просто может есть наработки . и еще была бы интересна генерация именно 1С кода. и некоторый анализатор его . вот с шарпом как раз таки проблем тут нет. (учитывая что Roslyn уже есть)
11. Serginio 908 15.11.15 23:52 Сейчас в теме
(10) Я пишу в ворде. Затем сохраняю в HTML и загружаю уже на ИС. Корректировать проблема. Удаляются пробелы. Согласен, что что то добавить или отредактировать это проблема. По поводу COM проблем не вижу. И это единственный способ (кроме Native ВК) интеграции 1С с манагед кодом. Кстати начал использовать http://infostart.ru/public/238584/ тогда, когда из 1С не смог достучаться до C# сервисов на по WS- протоколам итд. Там была развитая система классов, и описывать всех из через СОМ было муторно. Через обертку IReflect оказалось значительно проще
А так, это расширение языка без написания ВК. Использутся только COMОбъект("NetObjectToIDispatch45");
Конечно было бы чудесно, если бы 1С включила его в дистрибутив, что бы не надо было отдельно его регистрировать
12. cool.vlad4 45 16.11.15 00:03 Сейчас в теме
(11) регистрация это и есть проблема. админам это доверять не всегда хочется. а вручную самому во-первых нет смысла этим заниматься, а во-вторых не всегда есть соотвествующие права на ветки реестра.
13. Serginio 908 16.11.15 00:06 Сейчас в теме
(12) Так зарегистрировать нужно только NetObjectToIDispatch45. И будет открыт доступ ко всем Net овским классам, где регистрация не нужна
14. cool.vlad4 45 16.11.15 00:15 Сейчас в теме
(13) это то понятно. (аналогично как и у Elisy своя ВК или у ObjectFerm авторство не помню чье). только код будет specific, поскольку в некоторых конторах есть админы , которые просто откажутся что-то регистрировать, то что по их мнению доверия не заслуживает. и получится две версии кода, одна с ВК, другая без ВК и головная боль.
23. avz_1C 10 16.02.16 12:38 Сейчас в теме
(7) delete,

Спасибо от тех, "кто в теме" :-)

Очень грамотно пишете, читаю с удовольствием!
15. Serginio 908 16.11.15 00:20 Сейчас в теме
Использовать COM это необязательно регистрация. Можно сделать ВК (а они есть) которя будет грузить DLL и по гуиду доставать нужный IDispatch. Пример использования кстати есть в http://infostart.ru/public/238584/
16. Aphanas 87 17.11.15 19:21 Сейчас в теме
Други, простите великодушно, тут, видимо не для средних умов. Интересуюсь темой подписки на события через "ДобавитьОбработчик". Не могу врубиться, что делает эта разработка? Объясните кто-нибудь на простом языке. Я вижу кучу кода на C#, но куда всё это надо толкать, я так и не понял. И как это потом к "ДобавитьОбработчик" прикручивать?
17. Serginio 908 17.11.15 23:28 Сейчас в теме
(16) Это надо скачать http://infostart.ru/public/238584/ там есть обработки с генерацией 1С кода для подключения события.
И смотри пример с SerialPort для считывания Штрих-Кода.
Куча кода на C# объясняет только одну строку ОберткаСобытий=врап.СоздатьОберткуДляСобытий(объект);
18. Serginio 908 18.12.15 10:33 Сейчас в теме
Можно повторно использовать скомпилированную сборку. Например использовано здесь 1C Messenger для отправки сообщений, файлов и обмена данными между пользователями 1С, вэб страницы, мобильными приложениями а ля Skype, WhatsApp

Процедура ПолучитьОбертку(NetОбъект)
	
	// Использовал методы .Net классов для того, что бы показать технику использования обертки .Net классов
	Если не Объект.ИспользоватьСкомпилированнуюСборку Тогда
		ОберткаСобытий=врап.СоздатьОберткуДляСобытий(NetОбъект);
		возврат
	КонецЕсли; 
	//Так как сборка компилируется в реальную DLL, то если сборка SignalRHelloClient.dll не менялась, то и обертку событий компилировать не нужно 
	
	
	// Используем ТипКакОбъект для получения методов Type
	// По умолчанию для типа используются статические методы
	Тип=Врап.ТипКакОбъект(NetОбъект.GetType());
	ИмяФайлаСборки = тип.Assembly.Location;
	Path=Врап.ПолучитьТип("System.IO.Path");
	Каталог = Path.GetDirectoryName(ИмяФайлаСборки);
	
	ТипСтрРеальногоОбъекта = тип.FullName;
	// Применим метод ОбернутьЛюбойОбъект для получения методов String
	// Так как String возвращается без обертки
	ИмяКласса = "ВрапперДля" + Врап.ОбернутьЛюбойОбъект(Врап.ОбернутьЛюбойОбъект(ТипСтрРеальногоОбъекта).Replace(".", "_")).Replace("+", "_");
	OutputAssembly = Path.Combine(Каталог, ИмяКласса) + ".dll";
	
	Если  Врап.ПолучитьТип("System.IO.File").Exists(OutputAssembly) Тогда
		ТипОбертки=Врап.ПолучитьТипИзСборки(ИмяКласса,OutputAssembly);
		
		// У типа ТипОбертки есть статический метод  СоздатьОбъект который принимает обертываемый объект
		Попытка
		объектОбертка=ТипОбертки.СоздатьОбъект(Врап,NetОбъект);
	Исключение
		врап.ВывестиПоследнююОшибку()
		КонецПопытки;
		// Нужно получить COM объект из обертки
		ОберткаСобытий=Врап.ПолучитьРеальныйОбъект(объектОбертка);
	Иначе
		// Нет скомпилированной DLL 	
		ОберткаСобытий=врап.СоздатьОберткуДляСобытий(NetОбъект);
		
	КонецЕсли; 
	
	
	
	
КонецПроцедуры // ПолучитьОбертку()
Показать
19. Makushimo 159 21.12.15 09:48 Сейчас в теме
я не в теме.
и мне ничего не понятно.
20. Serginio 908 21.12.15 09:58 Сейчас в теме
Это обертка над нетовскими классами. Мое описание больше для знакомых с нетовскими классами.
Есть пример использования класса DateTime для конвертации данных из строки в дату
http://infostart.ru/public/434345/

У нетовских классов есть события. Которые можно использовать переводя их в Комовские или использовать как внешнее событие. Так или иначе нужно знать какие события есть у класса.

Например из примера
FileSystemWatcher это нетовский объект следящий за изменением директории
Все его свойства, методы и события можно посмотреть здесь
https://msdn.microsoft.com/ru-ru/library/system.io.filesystemwatcher(v=vs.110).aspx
21. Serginio 908 21.12.15 11:13 Сейчас в теме
А если убрать C# код то суть всей этой стать состоит в вызове методов

ОберткаСобытий=врап.СоздатьОберткуДляСобытий(объект);


или
ПодключитьВнешнююКомпоненту("AddIn.GlobalContext1C");
    объект = СоздатьОбъект("AddIn.GlobalContext1C");
    ГлобальныйКонтекст= объект.ГлобальныйКонтекст;

    ОберткаСобытий= врап.СоздатьОберткуДляСобытий77(ОбертываемыйОбъект,ГлобальныйКонтекст);
22. Serginio 908 21.01.16 14:10 Сейчас в теме
Поигрался со Scripting-API https://github.com/dotnet/roslyn/wiki/Scripting-API-Samples#exprstrong

Создал сборку. Проинсталировал
Install-Package Microsoft.CodeAnalysis.Scripting

Создал класс
namespace ScriptApiDlls

{ 
   public class КлассДляВычесленияВыражений 
    { 
      public static  Microsoft.CodeAnalysis.Scripting.ScriptOptions Опции { get { return Microsoft.CodeAnalysis.Scripting.ScriptOptions.Default; } } 
       
        public static object Вычислить(string Код, Microsoft.CodeAnalysis.Scripting.ScriptOptions опции ) 
        { 
            return Microsoft.CodeAnalysis.CSharp.Scripting.CSharpScript.EvaluateAsync(Код, опции).Result;

        }

    } 
}
Показать



Теперь можно на примере регулярных выражений создать делегат и использовать его в Replace. Например для того, что бы все слова начинались с заглавной буквы
врап=новый COMОбъект("NetObjectToIDispatch45");
    Match=Врап.ПолучитьТипИзСборки("System.Text.RegularExpressions.Match","System.dll");
    Regex=Врап.ПолучитьТип("System.Text.RegularExpressions.Regex");

    КлассДляВычесленияВыражений=Врап.ПолучитьТипИзСборки("ScriptApiDlls.КлассДляВычесленияВыражений",ПутьКДлл+"ScriptApiDlls.dll");
    ScriptOptions=КлассДляВычесленияВыражений.Опции;
    
    Слова = "надо заменить все первые буквы в словах на заглавные";
    pattern = "\w+";
    // MatchEvaluator evaluator = (MatchEvaluator)ПолучитьДелегат();

    scr = ScriptOptions.Default.WithReferences(Врап.ТипКакОбъект(Match).Assembly)
    .WithImports("System", "System.Text.RegularExpressions");
    ТекстДелегата =  "return (MatchEvaluator)((match) =>
    |{
    |  string x = match.Value;
    // Если первая буква в нижнем регистре то заменяем на заглавную

    |if (char.IsLower(x[0]))
    |{
    |  // Capitalize it.

    |   return char.ToUpper(x[0]) + x.Substring(1, x.Length - 1);
    |}
    |return x;
    |
    |   });";
    
    evaluator = КлассДляВычесленияВыражений.Вычислить(ТекстДелегата,scr);
    Сообщить(Regex.Replace(Слова, pattern, evaluator));
Показать


В итоге получаем
Надо Заменить Все Первые Буквы В Словах На Заглавные
24. TeMochkiN 04.09.16 23:48 Сейчас в теме
У вас тут столько всего интересного :)
Правда у меня проблема :(
При вызове врап.СоздатьОберткуДляСобытий
возникает ошибка:
Произошла исключительная ситуация (mscorlib): Адресат вызова создал исключение.
честно говоря, даже не знаю куда смотреть, что проверять :(
25. Serginio 908 05.09.16 10:01 Сейчас в теме
Есть обработка ТестСобытийИзмененийВДиректории.epf Там есть пример и обработка формирования текстов модулей на C# и 1С.
Нужно выбрать полное имя класса и имя DLL/ Для не глобальных сборок нужно указывать полный путь. Все зависимые сборки должны быть в одной директории
26. TeMochkiN 05.09.16 10:24 Сейчас в теме
(25) вроде всё так и есть, все зависимые сборки в одной директории. Попытался посмотреть отладчиком вижуал студии, пишет такую вот ошибку:
Исключение типа "System.IO.FileNotFoundException" возникло в mscorlib.dll, но не было обработано в коде пользователя

Дополнительные сведения: Не удалось загрузить файл или сборку "file:///C:\Users\temochkin\Desktop\AsterNET.ARI-master\AsteriskFor1C\bin\Release\ВрапперДляAsterNET_ARI_AriC­lient.dll" либо одну из их зависимостей. Не удается найти указанный файл.




Однако, я вижу, что в этой папке успешно создались файлы ВрапперДляAsterNET_ARI_AriClient.dll и ВрапперДляAsterNET_ARI_AriClient.pdb

или всё-таки на отсутствие какой-то зависимой сборки может ругаться? я просто не знаю, как определить какой именно может не хватать.
27. Serginio 908 05.09.16 10:31 Сейчас в теме
Какой то DLL не хватает. Для чистоты эксперимента создай проект встрой туда ссылки на нужные DLL и текст для C# и скомпилируй сборку и её используй для подключения событий
29. TeMochkiN 05.09.16 11:03 Сейчас в теме
(27) у меня получилось, но только после того, как я все зависимые сборки загрузил с помощью врап.ЗагрузитьСборку(ПутьСборки)
30. Serginio 908 05.09.16 13:34 Сейчас в теме
(29) Обычно когда загружается основная сборка, она грузит и все от которых зависит. Спасибо. Буду иметь ввиду.
(28) Большое спасибо!
31. TeMochkiN 05.09.16 13:53 Сейчас в теме
(30) не знаю, может конечно я что-то неправильно делаю, но в любом случае спасибо вам, т.к. обертка событий у меня заработала :)
у вас вообще столько статей интересных, мне их ещё читать и читать)
32. Serginio 908 05.09.16 14:15 Сейчас в теме
(31) Спасибо! и на здоровье.
28. white-mount 05.09.16 10:50 Сейчас в теме
Статья понравилась, добавил в свой в список "избранного". Автору респект.
Код читаю в оригинальной среде, вопросов не возникает.
34. Serginio 908 14.09.16 00:01 Сейчас в теме
Видно еще каких то библиотек не хватает. Для начала попробовать загрузить из .Net приложения.
Возможно нужно поместить в GAC. https://msdn.microsoft.com/ru-ru/library/h4fa028b(v=vs.110).aspx
Я с этим не сталкивался
35. Dionisiy 14.05.20 12:16 Сейчас в теме
Отличная работа, много раз обращался, поделюсь своими наработками. В 77 добавляю в таблицу ROT

  public КонструкторКласса()
        {
Guid guid = Marshal.GenerateGuidForType(typeof(КонструкторКласса));
Ole32.RegisterActiveObject(this, ref guid, 0, out m_dwRegister);
}


И убираю из таблицы в конце работы, чтобы не висело, приходится вызывать из 1С метод для этого, потому что автоматически этого не происходит почему-то

if (m_dwRegister != 0)
            {                

                IBindCtx bc;
                Ole32.CreateBindCtx(0, out bc);

                IRunningObjectTable rot;
                bc.GetRunningObjectTable(out rot);
                rot.Revoke(m_dwRegister);
                m_dwRegister = 0;
            }
Показать


Таким образом, 1С в одном из вызовов Init (всего их три) передает заполненный контекст. Сделал клавиатурный драйвер сканера ШК, он создает событие, которое вызывает ExternalEvent ОбработкаВнешнегоСобытия.
36. Serginio 908 14.05.20 19:15 Сейчас в теме
(35) Спасибо! Интересно! И не знал
Оставьте свое сообщение

См. также

Звуковое управление в 1С 8.3 Промо

Разработка внешних компонент Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

В данной статье описано создание библиотеки для звукового управления (выполнение команд голосом) для платформы 1С 8.3. Задача была поставлена так, чтобы модуль функционировал непосредственно на клиенте 1С, осуществляя управление формами, и взаимодействовал с интерфейсом.

16.03.2021    9215    velemir    33    

Изменения формата файлов конфигурации (CF) в 8.3.16

Математика и алгоритмы Платформа 1С v8.3 Бесплатно (free)

Дополнение по формату файлов конфигурации (*.cf) в версии 8.3.16.

16.12.2021    2534    fishca    12    

Установка отбора по списку значений при открытии формы выбора справочника из реквизита обработки

Математика и алгоритмы Платформа 1С v8.3 Конфигурации 1cv8 Россия Бесплатно (free)

Описан алгоритм установки отбора по списку значений при открытии формы выбора справочника. Параметром отбора является список значений передаваемый из одной формы обработки в другую форму этой же обработки. Тестировано под платформу 8.3.18

11.12.2021    2303    prog1c_vl    4    

Использование сборок .NET в 1С 7. и 8.x. Создание внешних Компонент. Промо

Разработка внешних компонент Платформа 1С v7.7 Платформа 1С v8.3 Конфигурации 1cv8 Конфигурации 1cv7 Абонемент ($m)

Данная разработка создана для использования сборок .Net в 1С через преобразование объектов и классов в COM-объекты, которые можно использовать в 1С. Достигается это путем создания класса, реализующего методы интерфейса IReflect public class AutoWrap: IReflect.

1 стартмани

28.11.2013    100368    313    Serginio    80    

Что за ? в коде, или Секретный оператор в 1С

Математика и алгоритмы Платформа 1С v8.3 Платформа 1C v8.2 Платформа 1С v8.1 Конфигурации 1cv8 Бесплатно (free)

Инкремент, модуль и прочая магия, которая скрыта под символом "?"

21.10.2021    14319    SeiOkami    43    

Механизм анализа данных. Кластеризация.

Математика и алгоритмы Анализ учета Платформа 1С v8.3 Анализ и прогнозирование Бесплатно (free)

Подробный разбор, с примером использования, встроенного механизма кластеризации 1С.

31.08.2021    3845    dusha0020    8    

Практическое применение операции копирования массива

Математика и алгоритмы Платформа 1С v8.3 Бесплатно (free)

Решение задачи https://projecteuler.net/problem=250 из Project Euler средствами 1C.

02.08.2021    1530    scientes    2    

Как работает серверный вызов в 1С Промо

Математика и алгоритмы Управляемые формы Бесплатно (free)

Клиент-серверная архитектура заложена в платформе изначально — со времен «1С:Предприятие 8.0». Однако при разработке на 8.0 и 8.1 о разделении кода на клиентскую и серверную часть можно было не заботиться, поскольку на клиенте (на толстом клиенте) был доступен тот же функционал, что и на сервере. Всё изменилось с выходом платформы «1С:Предприятие 8.2», когда появился тонкий клиент. Теперь на клиенте доступен один функционал, на сервере — другой. Клиент и сервер «общаются» между собой с помощью серверного вызова. Конечно, это усложнило процесс разработки, но с другой стороны – можно создавать более оптимальные (быстрые) решения, поскольку все сложные задачи выполняются на сервере.

18.11.2017    77664    pahich    86    

Запрос всей номенклатуры с характеристиками

Математика и алгоритмы Платформа 1С v8.3 1С:ERP Управление предприятием 2 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х Бесплатно (free)

Сравнение различных вариантов запроса всей номенклатуры с характеристиками (УТ11.4, КА 2.4, ERP 2.4).

1 стартмани

30.07.2021    2645    Daemonold    3    

Распределенные алгоритмы РИБ 1С

Математика и алгоритмы Обмен между базами 1C Платформа 1С v8.3 Бесплатно (free)

Небольшое исследование на тему применимости классических распределённых алгоритмов репликации и синхронизации данных между узлами обмена РИБ 1С.

02.07.2021    1757    zhichkin    1    

Параллельная обработка очереди сообщений

Математика и алгоритмы Платформа 1С v8.3 Бесплатно (free)

Описание алгоритма обработки очереди последовательных сообщений регистрации изменений записей регистра сведений. Алгоритм может быть применим к любым объектам метаданных. Алгоритм основан на обработке объектов по их ключам.

15.06.2021    3393    zhichkin    11    

Минимализмы 3 Промо

Математика и алгоритмы Платформа 1С v8.3 Бесплатно (free)

Очередная серия "минимализмов" [http://infostart.ru/public/306536/, https://infostart.ru/public/460935/]. Также, как и в предыдущих статьях, здесь приведена подборка коротких оригинальных авторских решений некоторых задач. Ранее эти решения были разбросаны по моим комментариям к чужим публикациям.

19.02.2018    52359    ildarovich    47    

Чем воспользоваться для распознавания котиков в 1С?

Математика и алгоритмы Языки и среды Платформа 1С v8.3 Бесплатно (free)

На митапе по инструментам для расширения возможностей 1С выступил Олег Филиппов. Он сравнил подходы Native API, COM, Docker и Serverless, и рассказал, как упростить использование в 1С алгоритмов, реализованных на других языках, с помощью облачной технологии «Функция как сервис».

12.04.2021    4267    comol    10    

Эффективные приемы разработки

Математика и алгоритмы Рефакторинг и качество кода СКД Платформа 1С v8.3 Бесплатно (free)

На Infostart Meetup Ekaterinburg.Online выступил Сергей Наумов – руководитель центра аналитики и консалтинга WiseAdvice. Сергей поделился с коллегами приемами разработки, которые помогут избежать потенциальных проблем при реализации сложных проектов.

07.04.2021    4422    SergeyN    13    

Будни автоматизации или "мне нужна программка для 3D упаковки" Промо

Математика и алгоритмы Оптовая торговля Платформа 1С v8.3 Конфигурации 1cv8 Управленческий учет Бесплатно (free)

Автоматизация отечественных предприятий, которой приходиться заниматься, это нужная и высокооплачиваемая, но довольно нервная работа. Выручает юмор. Например, при общении с требовательным клиентом можно вспомнить анекдот: "Держась руками за стену, на ногах еле стоит мужик. К нему пристает ребенок: "Ну, папа, пожалуйста, сделай мне кораблик!", папа отвечает: "Ага! - Сейчас все брошу и пойду делать тебе кораблик!". Про один такой сделанный для клиента "кораблик" и хочется рассказать. Надеюсь, совместное погружение в теплое ламповое (то есть клиентоориентированное) программирование доставит Вам положительные эмоции, да и задача попалась интересная. Поплыли?

24.03.2014    48298    ildarovich    121    

Рекурсия для начинающих

Математика и алгоритмы Платформа 1С v8.3 Бесплатно (free)

Рассмотрен подход к пониманию рекурсий. Приведены примеры из реальной практики.

10.02.2021    7355    szv    5    

Самый быстрый FizzBuzz на 1С

Математика и алгоритмы Платформа 1С v8.3 Бесплатно (free)

Давайте попробуем найти самое быстрое решение задачи "BuzzFizz" на 1С.

03.02.2021    1661    Donrad    23    

Программное создание корректировочного счета-фактуры выданного в УПП 1.3

Математика и алгоритмы Механизмы типовых конфигураций Запросы Платформа 1С v8.3 1С:Управление производственным предприятием Россия Бухгалтерский учет НДС Бесплатно (free)

Данный функционал можно использовать, например, в процессе оформления возвратов от поставщика (корректировка реализации по согласованию сторон) при автоматическом создании корректировок реализации по документам поставщика, он позволяет массово создать корректировочные счета-фактуры в УПП 1.3. При создании документа из первичного счета-фактуры выданного в новый корректировочный счет-фактуру выданный копируются значения свойств.

17.12.2020    976    ksnik    0    

Минимализмы 2 Промо

Математика и алгоритмы Платформа 1С v8.3 Бесплатно (free)

Следующая серия "минимализмов" [http://infostart.ru/public/306536/]. Также, как и в предыдущей статье, здесь приведена подборка коротких оригинальных решений некоторых задач. Ранее эти решения были разбросаны по моим комментариям к чужим публикациям.

23.02.2016    53054    ildarovich    84    

Параллельные вычисления расчета факториала числа N

Математика и алгоритмы Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Распараллеливание алгоритма с помощью фоновых заданий (асинхронные вычисления)

29.06.2020    4921    RustIG    18    

Работа с журналом регистрации. Выходим за границы платформы

Журнал регистрации Бесплатно (free)

Работа с журналом регистрации нестандартными средствами. А также немного про использование платформы .NET в экосистеме 1С.

12.05.2020    14030    Infostart    30    

Минимализмы Промо

Математика и алгоритмы Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Приводится подборка кратчайших решений некоторых задач. Ранее эти решения были разбросаны по комментариям к чужим публикациям.

08.10.2014    97508    ildarovich    85    

Treemapping — способ визуализации данных древовидной структуры. Карта-схема дерева

Математика и алгоритмы Работа с интерфейсом Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Предлагается ознакомиться с редким способом графического представления иерархических данных. Приводится алгоритм формирования и пример реализации.

18.02.2020    7614    randomus    20    

Сравнение адресов: случай из практики

Математика и алгоритмы Универсальные функции Платформа 1С v8.3 Россия Бесплатно (free)

Как с учетом обстоятельств сравнить два небрежно записанных адреса и решить, означают ли они одно и то же. Программный код написан для режима совместимости с 8.2.

04.01.2020    4692    AnatolPopov    7    

[После]Новогодние задачи

Математика и алгоритмы Платформа 1С v8.3 Бесплатно (free)

Совсем немного времени осталось до того момента, когда отзвучат куранты, шампанское будет выпито, мандарины съедены, и даже оливье закончится. Возникнет вопрос: чем бы занять неожиданно появившееся свободное время?

30.12.2019    3734    Alxby    23    

Приемы обработки больших данных в 1С Промо

Универсальные обработки Математика и алгоритмы Обмен между базами 1C Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Рассказ об эффективных приемах организации обработок больших объемов данных на платформе 1С

07.08.2015    73853    tormozit    29    

30 задач. Странных и не очень

Математика и алгоритмы Механизмы платформы 1С Платформа 1С v8.3 Бесплатно (free)

30 задач на знание языка программирования 1С и некоторого поведения платформы. Маленьких. Странных и не очень.

02.12.2019    32830    Infostart    63    

Иерархия без "В ИЕРАРХИИ"

Математика и алгоритмы Платформа 1С v8.3 Бесплатно (free)

Говорится о том, как эффективно представлять иерархию в СУБД, как получать и использовать эти представления при решении задач в запросной технике. Уточняются и дополняются запросы из статьи "Уровни, глубина, прародители, циклы и аналоги запросом" [https://infostart.ru/public/160707/].

22.08.2019    17748    ildarovich    24    

Побитовые операции "на пальцах"

Математика и алгоритмы Платформа 1С v8.3 Бесплатно (free)

Простой пример для понимания того, как это работает.

02.08.2019    4631    nbeliaev    16    

Решение транспортной задачи запросом Промо

Математика и алгоритмы Платформа 1С v8.3 Бесплатно (free)

Списание по двум последовательностям партий запросом (без программной обработки)

1 стартмани

30.04.2014    36758    bforce    22    

Обработчики событий при записи объектов. Зачем и что за чем?

Математика и алгоритмы Платформа 1С v8.3 Бесплатно (free)

Программисту, имеющему немного опыта на платформе 1С 8.3, бывает сложно разобраться: ПередЗаписью, ПриЗаписи, ПослеЗаписи, на сервере, на клиенте, в модуле формы, в модуле объекта.... Эта шпаргалка была создана в процессе обучения и реального опыта с целью разложить всё по полочкам, чтобы было четкое понимание в каком случае какой обработчик нужно использовать и в какой последовательности они запускаются при записи и проведении документов. Данная статья будет полезна в большей степени начинающим разработчикам. Но и опытным позволит освежить информацию, упорядочить её.

25.07.2019    159268    AlbinaAAA    50    

FizzBuzz на 1С. Чем короче, тем веселее. Варианты принимаются...

Математика и алгоритмы Платформа 1С v8.3 Бесплатно (free)

Мне было скучно, я не мог себя заставить написать ничего полезного. И читал статью на Хабре. Потом я читал комментарии, а потом... нет я не ушел смотреть котиков на ютюбе. Я решил сделать несколько решений задачки FizzBuzz на 1С, с целью "чем короче, тем лучше". Прошу сильно не пинать, это просто развлечение для вечера.

24.07.2019    6444    vandalsvq    19    

Что делает "В ИЕРАРХИИ" в запросе?

Математика и алгоритмы Платформа 1С v8.3 Бесплатно (free)

Описание действий платформы 1С при использовании конструкции "В ИЕРАРХИИ" в запросах.

16.07.2019    62179    Infostart    34    

Парсер запросов 1С. Часть 1: Введение, разбор математических выражений Промо

Математика и алгоритмы Платформа 1С v8.3 Бесплатно (free)

Рано или поздно становится скучно решать типичные задачи, для которых придумана 1С. Голова пухнет от бухгалтерских терминов и очередных "хотелок" пользователей. Именно в такие моменты хочется гордо поднять голову, воскликнуть "Но я же программист!" и заняться чем-то интересным. В цикле статей я постараюсь доступно описать, как устроены парсеры в целом и на примере парсера языка запросов 1С. Требования к навыкам читающего: основы языка 1С, основы алгоритмизации.

1 стартмани

04.12.2013    31738    juntatalor    49    

Создание отчетов с помощью СКД - основные понятия и элементы

Математика и алгоритмы Платформа 1С v8.3 Система компоновки данных Бесплатно (free)

Основные принципы работы СКД. Понятия схемы компоновки и макета компоновки. Описание основных элементов схемы компоновки: наборы данных, поля, вычисляемые поля, ресурсы, параметры.

25.06.2019    90463    ids79    32    

Реализуем Стек, Очередь и Приоритетную очередь в 1С

Математика и алгоритмы Универсальные функции Платформа 1С v8.3 Конфигурации 1cv8 Россия Бесплатно (free)

В статье рассматриваются способы реализации таких абстрактных структур данных, как стек, очередь и приоритетная очередь, используя готовые типы данных 1С. Выявляются "узкие" места, сложные моменты в реализации и сравнивается скорость работы.

24.06.2019    18217    RonX01    69    

Организация хранения промежуточных данных

Математика и алгоритмы Платформа 1С v8.3 Бесплатно (free)

Организация хранения промежуточных данных в процедуре сверки.

29.05.2019    4842    scientes    1    

Сервис для изучения методов платформы 1С:Предприятие 8. Бесплатно! Промо

Подготовка к аттестации Математика и алгоритмы Платформа 1С v8.3 Бесплатно (free)

Бесплатный ON-Line сервис изучения методов платформы 1С:Предприятие 8. Подготовка к аттестации 1С:Специалист on-line! Тестовые задания по различным видам учета! Подсказки для оптимального решения!

27.06.2013    52271    bpc222    54    

Вычисление 200 тысяч знаков числа pi

Математика и алгоритмы Платформа 1С v8.3 Россия Бесплатно (free)

В статье рассматриваются возможности платформы выполнять сверхточные вычисления без использования сложных алгоритмов и внешних компонент на примере вычисления числа pi.

28.05.2019    10310    Oleg_nsk    97    

Парсер таблиц по шаблону. Автоматическая корректировка парсера. Представление таблиц в виде графа.

Математика и алгоритмы Работа с интерфейсом Универсальные функции Платформа 1С v8.3 Конфигурации 1cv8 Россия Бесплатно (free)

Возникла такая задача: нужно нарисовать в макете шаблон таблицы, где расписано какая ячейка за что отвечает, загрузить таблицу из html и сравнить, подходит ли она под шаблон. Если да, то загрузить информацию по правилу из шаблона. Проблема в том, что в html таблица может приходить с ошибками, то есть какие то ячейки совмещены, хотя не должны. Поэтому нужно сделать так, что бы программа понимала, что таблицы похожи и где конкретно ошибки. Соответсвенно, поделил задачу на 3 этапа. 1 - это представление таблицы в виде графа, 2 - сравнение графов, 3 - забор информации. В данной статье пойдет описание пункта 1.

25.04.2019    4424    trim89    5    

Нечёткий поиск. Bitap алгоритм, модификация от Wu-Manber

Математика и алгоритмы Платформа 1С v8.3 Россия Бесплатно (free)

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

01.04.2019    5562    trim89    10    

v8: Концепция минимального изменения конфигурации для легкого обновления Промо

Математика и алгоритмы Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

"Лучше день потерять потом за пять минут долететь" ((с) "Крылья, ноги и хвосты") или как сделать так чтобы обновление конфигурации проходило с минимальными трудозатратами.

28.01.2013    39159    MarSeN    57    

Решение системы линейных уравнений

Математика и алгоритмы Платформа 1С v8.3 Бесплатно (free)

Пример использования объекта Расчет систем линейных уравнений.

25.03.2019    10181    scientes    9    

Обсуждение двух задач на пересечение отрезков

Математика и алгоритмы Платформа 1С v8.3 Бесплатно (free)

Ищем общее в частностях, или задача о пересечении отрезков.

15.03.2019    7170    scientes    16    

Многопоточное восстановление последовательностей

HighLoad оптимизация Математика и алгоритмы Универсальные функции Платформа 1С v8.3 Бесплатно (free)

Универсальный алгоритм многопоточного фонового восстановления любой последовательности.

05.12.2018    16535    _ASZ_    33    

Пример выбора несколько обработчиков событий записи объекта для решения одной задачи Промо

Математика и алгоритмы Платформа 1С v8.3 Бесплатно (free)

Данная публикация предназначена для начинающих разработчиков и является продолжением статьи "Обработчики событий при записи объектов. Зачем и что за чем?" (ссылка далее). Содержит пример использования несколько обработчиков событий для решения одной задачи и объясняется почему выбраны именно они.

27.09.2012    198315    AlbinaAAA    65    

Возврат (loop) в Алгоритмах визирования. Бит Финанс

Бюджетирование и планирование Математика и алгоритмы Платформа 1С v8.3 Конфигурации 1cv8 Финансовые услуги, инвестиции Россия Бюджетный учет Бесплатно (free)

В статье рассматривается минимальная доработка конфигурации БИТ Финанс, с сохранением поддержки, для расширения функционала Визирования: Возрат к предидущим точкам алгоритмов. Полезно будет для программистов и специалистов, занимающихся внедрением БИТ Финанс.

07.08.2018    8176    gladky    2    

Извлечение текстов модулей из внешней обработки 1С

Математика и алгоритмы Платформа 1С v8.3 Россия Бесплатно (free)

Лень в очередной раз сподвигла меня на доработку существующего инструментария. В публикации опишу свой опыт парсинга бинарного файла с данными обычной формы (выгруженного с помощью функционала платформы 1С "Выгрузить в файлы").

28.04.2018    16458    zenechka    6    

Преобразование запросов

Математика и алгоритмы Платформа 1С v8.3 Бесплатно (free)

Использование математических методов для языка запросов.

15.03.2018    12802    vasilev2015    24