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

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

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

.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 находящейся здесь //mag.itwonline.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используя программы //mag.itwonline.ru/public/14587/ .

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

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

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

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

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

Комментарии
Избранное Подписка Сортировка: Древо развёрнутое
Свернуть все
1. shakmaev 341 13.11.15 11:45 Сейчас в теме
Беда с оформлением статьи, и куда только смотрят модераторы?
гвость; +1 Ответить
2. Serginio 817 13.11.15 12:04 Сейчас в теме
(1) А по существу? Просто править текст очень тяжело.
3. cool.vlad4 44 13.11.15 12:20 Сейчас в теме
(2) статья полезная. только (1) прав. код c# можно было на pastebin разместить, а здесь ссылку оставить. (часть кода ис распарсил в ссылки )
5. Serginio 817 13.11.15 13:03 Сейчас в теме
(3) Спасибо. Учту и попробую
(4) Спасибо.
4. gortol 185 13.11.15 12:29 Сейчас в теме
зато открывает возможности описания собственных событий, очень полезная информация, мне не хватило информации из интернета как раз для формирования собственных событий и передать их в 1с...
6. ivanov660 2087 15.11.15 12:44 Сейчас в теме
Довольно забавно получается - надо писать 1Сом Сишарп.
На мой взгляд:
1. Надо не забывать о правах пользователя под которым собирается и компилируется код.
2. Необходимо не забывать про обработку ошибок при динамической компиляции.
3. Про версии .net при которых возможно использование данных возможностей - где-то от 3.5+ и выше.
4. Можно было просто передать текстовый кусок кода (*.cs) и скомпилировать его на лету.
8. Serginio 817 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 238 15.11.15 13:06 Сейчас в теме
То есть использование .Net в 1С станет достаточно простым.

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

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

Все остальное, это рассказ о том как формируется реальный код. То есть, для тех кому это интересно и использовать сгенеренный код для дальнейшей модификации или как использовать обвязку нетовских свойств для использования через ДобавитьОбработчик или ОбработкаВнешнегоСобытия. Думаю многим это будет полезным. За оформление прошу прощения. Спешил, да и дизайнерские способности у меня невысокие
10. cool.vlad4 44 15.11.15 23:13 Сейчас в теме
(9) да дизайнерские способности ни причем. я например вообще не хочу публиковать статьи на ис, поскольку публикация это боль (у меня процессор так грузился как не зная что, но может с тех пор ситуация изменилась) , ну и форматирование там так себе. насчет статьи, я напимер в теме. (некоторые свои вк, кстати публиковал, опять же по причине движка ис в комментах). но имхо с com есть некоторый геморрой при деплое. например, мне были бы интереснее вещи касательно обмена данных, генерации всяких dto между приложением на C# (какой-нибудь сервис) и 1С. тут нет никакой магии , но просто может есть наработки . и еще была бы интересна генерация именно 1С кода. и некоторый анализатор его . вот с шарпом как раз таки проблем тут нет. (учитывая что Roslyn уже есть)
11. Serginio 817 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 44 16.11.15 00:03 Сейчас в теме
(11) регистрация это и есть проблема. админам это доверять не всегда хочется. а вручную самому во-первых нет смысла этим заниматься, а во-вторых не всегда есть соотвествующие права на ветки реестра.
13. Serginio 817 16.11.15 00:06 Сейчас в теме
(12) Так зарегистрировать нужно только NetObjectToIDispatch45. И будет открыт доступ ко всем Net овским классам, где регистрация не нужна
14. cool.vlad4 44 16.11.15 00:15 Сейчас в теме
(13) это то понятно. (аналогично как и у Elisy своя ВК или у ObjectFerm авторство не помню чье). только код будет specific, поскольку в некоторых конторах есть админы , которые просто откажутся что-то регистрировать, то что по их мнению доверия не заслуживает. и получится две версии кода, одна с ВК, другая без ВК и головная боль.
23. avz_1C 10 16.02.16 12:38 Сейчас в теме
(7) delete,

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

Очень грамотно пишете, читаю с удовольствием!
15. Serginio 817 16.11.15 00:20 Сейчас в теме
Использовать COM это необязательно регистрация. Можно сделать ВК (а они есть) которя будет грузить DLL и по гуиду доставать нужный IDispatch. Пример использования кстати есть в http://infostart.ru/public/238584/
16. Aphanas 140 17.11.15 19:21 Сейчас в теме
Други, простите великодушно, тут, видимо не для средних умов. Интересуюсь темой подписки на события через "ДобавитьОбработчик". Не могу врубиться, что делает эта разработка? Объясните кто-нибудь на простом языке. Я вижу кучу кода на C#, но куда всё это надо толкать, я так и не понял. И как это потом к "ДобавитьОбработчик" прикручивать?
17. Serginio 817 17.11.15 23:28 Сейчас в теме
(16) Это надо скачать http://infostart.ru/public/238584/ там есть обработки с генерацией 1С кода для подключения события.
И смотри пример с SerialPort для считывания Штрих-Кода.
Куча кода на C# объясняет только одну строку ОберткаСобытий=врап.СоздатьОберткуДляСобытий(объект);
18. Serginio 817 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 155 21.12.15 09:48 Сейчас в теме
я не в теме.
и мне ничего не понятно.
20. Serginio 817 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 817 21.12.15 11:13 Сейчас в теме
А если убрать C# код то суть всей этой стать состоит в вызове методов

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


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

    ОберткаСобытий= врап.СоздатьОберткуДляСобытий77(ОбертываемыйОбъект,ГлобальныйКонтекст);
22. Serginio 817 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 817 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 817 05.09.16 10:31 Сейчас в теме
Какой то DLL не хватает. Для чистоты эксперимента создай проект встрой туда ссылки на нужные DLL и текст для C# и скомпилируй сборку и её используй для подключения событий
29. TeMochkiN 05.09.16 11:03 Сейчас в теме
(27) у меня получилось, но только после того, как я все зависимые сборки загрузил с помощью врап.ЗагрузитьСборку(ПутьСборки)
30. Serginio 817 05.09.16 13:34 Сейчас в теме
(29) Обычно когда загружается основная сборка, она грузит и все от которых зависит. Спасибо. Буду иметь ввиду.
(28) Большое спасибо!
31. TeMochkiN 05.09.16 13:53 Сейчас в теме
(30) не знаю, может конечно я что-то неправильно делаю, но в любом случае спасибо вам, т.к. обертка событий у меня заработала :)
у вас вообще столько статей интересных, мне их ещё читать и читать)
32. Serginio 817 05.09.16 14:15 Сейчас в теме
(31) Спасибо! и на здоровье.
28. white-mount 05.09.16 10:50 Сейчас в теме
Статья понравилась, добавил в свой в список "избранного". Автору респект.
Код читаю в оригинальной среде, вопросов не возникает.
34. Serginio 817 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 817 14.05.20 19:15 Сейчас в теме
(35) Спасибо! Интересно! И не знал
Оставьте свое сообщение

См. также

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

Практика программирования Разработка внешних компонент Универсальные функции v7.7 v8 Бесплатно (free)

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

27.01.2016    70910    0    Serginio    108    

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

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

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

12.05.2020    2852    0    YPermitin    24    

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

Математика и алгоритмы Работа с интерфейсом v8 1cv8.cf Бесплатно (free)

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

18.02.2020    3677    0    randomus    18    

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

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

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

30.12.2019    2562    0    Alxby    23    

Автоматические и управляемые блокировки применительно к типовым конфигурациям 1С Промо

Математика и алгоритмы Практика программирования v8 v8::blocking 1cv8.cf Бесплатно (free)

Основные принципы работы с режимами автоматических и управляемых блокировок в 1С Предприятие 8. Теория и применение в типовых конфигурациях: БП, УТ, ЕРП

10.11.2018    30478    0    ids79    40    

Регистры бухгалтерии. Общая информация

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

Общая информация о внутреннем устройстве регистров бухгалтерии.

05.09.2019    21433    0    YPermitin    24    

"Хочу универсально!" [Часть 1]

Математика и алгоритмы Практика программирования Разработка v8 1cv8.cf Бесплатно (free)

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

02.09.2019    8770    0    SeiOkami    35    

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

Математика и алгоритмы v8 Бесплатно (free)

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

22.08.2019    10514    0    ildarovich    19    

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

Практика программирования Математика и алгоритмы Оптовая торговля Оптовая торговля v8 1cv8.cf УУ Бесплатно (free)

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

24.03.2014    43791    0    ildarovich    116    

EnterpriseData – часть 3. Загрузка данных, идентификация объектов

Практика программирования Математика и алгоритмы Перенос данных из 1C8 в 1C8 Разработка v8 v8::УФ 1cv8.cf Бесплатно (free)

Основные этапы загрузки данных через EnterpriseData. Идентификация объектов загружаемых полностью и по ссылке. Приведены схемы процессов загрузки данных. Описание основных операций и обработчиков. Перечень процедур БСП, используемых при загрузке данных, структура «КомпонентыОбмена».

22.08.2019    11849    0    ids79    7    

PinkRabbitMQ - Native API компонента 1С с открытым исходным кодом, для обмена сообщениями через RabbitMQ

Разработка внешних компонент v8 Бесплатно (free)

PinkRabbitMQ представляет собой Native API компоненту для 1С Предприятия 8 (Windows 32bit и 64bit) с открытым исходным кодом на с++ (можно собрать компоненту самостоятельно). PinkRabbitMQ это низкоуровневая компонента которая реализует обмен по протоколу AMQP с брокером сообщений RabbitMQ. Для организации высокоуровнего обмена между информационными базами предназначен Адаптер. Компонента разрабатывается в рамках проекта Адаптер.

29.07.2019    12496    0    Begemoth80    143    

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

Математика и алгоритмы v8 Бесплатно (free)

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

25.07.2019    35204    4    AlbinaAAA    25    

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

Универсальные обработки Математика и алгоритмы Перенос данных из 1C8 в 1C8 v8 1cv8.cf Бесплатно (free)

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

07.08.2015    64364    0    tormozit    27    

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

Практика программирования Математика и алгоритмы Разработка v8 Бесплатно (free)

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

24.07.2019    4881    0    vandalsvq    16    

Управление качеством кода

Математика и алгоритмы Рефакторинг и качество кода v8 Бесплатно (free)

О SonarQube, АПК, EDT. Какие преимущества дает их использование. Для каких команд подходит.

22.07.2019    14544    0    Stepa86    33    

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

Математика и алгоритмы v8 Бесплатно (free)

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

16.07.2019    20018    0    YPermitin    34    

XDTO - это просто Промо

Математика и алгоритмы v8 1cv8.cf Бесплатно (free)

С появлением платформы 8.1 фирма “1С” представила механизм, носящий интригующее название XML Data Transfer Objects или, если коротко - XDTO. По традиции, документирование механизма составлял тот, кто хорошо разбирался в вопросе, а стало быть опустил “и так понятные” с его точки зрения моменты. Целью данной статьи (или цикла статей, как получится) стало желание поделиться накопленным опытом. Мне кажется, многие неочевидные вещи в механизме XDTO необходимо осветить получше.

24.12.2012    281636    0    Evil Beaver    173    

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

Практика программирования Математика и алгоритмы v8 v8::СКД Бесплатно (free)

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

25.06.2019    42011    0    ids79    17    

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

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

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

24.06.2019    12764    0    RonX01    65    

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

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

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

28.05.2019    6745    0    Oleg_nsk    96    

Самоучитель языка запросов 1С. Промо

Практика программирования Решение задач на 1С:Специалист Математика и алгоритмы v8 v8::Запросы Бесплатно (free)

Сервис для изучения запросов 1С: "Консоль изучения запросов 1С:Предприятие 8". Теперь и с конструктором запросов!

07.05.2013    107209    0    bpc222    327    

Регистры накопления. Виртуальные таблицы. Часть №1: Обороты

Практика программирования Математика и алгоритмы Разработка v8 1cv8.cf Бесплатно (free)

Описание работы платформы 1С:Предприятие 8.2 с виртуальной таблицей "Обороты" регистров накопления.

20.05.2019    22350    0    YPermitin    7    

Даем названия переменным: как префиксы экономят наше время

Практика программирования Математика и алгоритмы Разработка v8 Бесплатно (free)

Понятные названия переменных экономят время и силы разработчика : в начале, когда мы даём названия переменным, в процессе развития разработки, когда мы "на лету" понимаем назначение той или иной переменной, в конце, когда мы передаём разработку на поддержку других программистов, сами переходя к новым разработкам

06.05.2019    5919    0    Designer1C    81    

Заметки по SQL: Срез последних - аналог запроса

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

В статье описывается создание среза последних данных средствами классического языка запросов. Причем метод построения запроса был разработан еще во времена, когда автор работал с СУБД Oracle 9i и программировал на PL SQL. Основная идея заключается преобразовании запроса с подзапросом, в запрос без подзапроса (в примерах описывается преобразование до двух вложенных подзапросов). Запросы тестировались на реальных базах данных. Платформа - 1С:Предприятие 8.3 (8.3.10.2561).

15.01.2019    9961    0    IVC_goal    7    

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

Математика и алгоритмы v8 Бесплатно (free)

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

1 стартмани

30.04.2014    34187    10    bforce    22    

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

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

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

05.12.2018    11718    0    _ASZ_    33    

Основные понятия и механизмы оптимизации клиент-серверного взаимодействия в 1C

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

У многих начинающих 1С программистов часто возникают вопросы про клиент-серверное взаимодействие в 1С и чтобы разобраться в непростых механизмах платформы, необходимо понять, что же такое контекст, для чего предназначены директивы компиляции, что представляют собой контекстные/внеконтекстные вызовы и как наиболее оптимально описывать прикладные задачи в модулях управляемых форм.

23.08.2018    34721    0    Rain88    46    

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

Математика и алгоритмы v8 Бесплатно (free)

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

1 стартмани

04.12.2013    29881    5    juntatalor    49    

Теорема номер тринадцать

Математика и алгоритмы v8 Бесплатно (free)

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

15.03.2018    11565    0    vasilev2015    24    

"Взлом" теста "1С:Профессионал" методом машинного обучения

Практика программирования Математика и алгоритмы v8 1cv8.cf Бесплатно (free)

Нейронные сети – не единственная модель, реализующая принципы машинного обучения. Есть еще байесовская модель, которая математически строже и определеннее, поскольку построена на надежном фундаменте теории вероятностей. Применению байесовского вывода к решению интересной теоретической задачи и посвящена данная статья. Слово "взлом" в заголовке использовано для привлечения внимания. Речь идет исключительно о математическом методе, показанном на примере знакомой всем задачи. 

12.03.2018    18173    0    ildarovich    19    

Введение в CI для 1С

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

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

21.11.2017    22511    0    real_MaxA    22    

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

Практика программирования Решение задач на 1С:Специалист Математика и алгоритмы v8 Бесплатно (free)

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

27.06.2013    48754    0    bpc222    51    

#Область ВНЕШНИЕ_ВЫЗОВЫ или MVC в 1С, библиотечность и упрощение интеграции кода

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

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

12.10.2017    17081    0    for_sale    58    

Пишем игру Минер. Обработка событий ActiveX в 1С

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

Пример демонстрирует обработку событий генерируемых компонентой ActiveX в 1С.

29.05.2017    14255    0    user621724_Dimav1979    12    

Как я доступ на kb.1c.ru получал

Решение задач на 1С:Специалист Математика и алгоритмы v8 Россия Бесплатно (free)

kb.1c - база знаний по технологическим вопросам крупных внедрений и не только. В этой базе знаний собираются методики и решения технологических проблем эксплуатации 1с, check-list'ы и инструкции по настройке ПО на серверах. Какие-то из размещенных статей дублируются на ИТС. Когда я искал пути получения доступа к нему я столкнулся с проблемой: мало кто доподлинно знает как получить доступ к нему, не работая у франчайзи 1с. Я опишу путь, который прошёл я, как физическое лицо.

01.05.2017    25154    0    ikekoval    34    

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

Математика и алгоритмы v8 1cv8.cf Бесплатно (free)

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

28.01.2013    37177    0    MarSeN    57    

Улучшение стандарта "Структура модуля"

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

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

26.03.2017    13836    0    o.nikolaev    23    

"Распределение в запросе" или "избавляемся от перебора"

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

Хороший перебор - это отсутствие перебора. Рассмотрим пример замены полного перебора запросом.

16.12.2016    32148    0    alexandersh    48    

Планы обмена. Квитировать или гарантировать?

Практика программирования Математика и алгоритмы v8 1cv8.cf Бесплатно (free)

Планы обмена предлагают использовать две стратегии удаления обработанных изменений: квитирование и гарантированная доставка сообщений. Как сделать правильный выбор?

12.12.2016    16364    0    zhichkin    9    

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

Математика и алгоритмы v8 Бесплатно (free)

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

27.09.2012    193151    0    AlbinaAAA    65    

Некоторые принципы оптимизации запросов 1С (+SQL)

Математика и алгоритмы v8 Бесплатно (free)

Разработка нового функционала часто связана с созданием новых таблиц в базе и написанием запросов. Собственно, размышляя о запросах, мы и формируем в голове содержание таблиц, индексы и количество таблиц и индексов. Заранее можно уверенно рассуждать о том, какая нужна архитектура, если задачу удалось понять. На этом этапе важно привлекать свой опыт. Что же делать, если его нет? Как рассуждать о запросах и формате хранения?

17.11.2016    10229    0    ture    40    

Использование git для доработки типовых конфигураций 1С

Математика и алгоритмы v8 Беларусь Украина Россия Бесплатно (free)

Рассмотрены способы доработок типовой конфигурации 1C для различных изменений, и на картинках продемонстрирован подход к разработке с использованием git и частично с тестами.

11.10.2016    202268    0    pumbaE    31    

Оптимизация запросов 1С:Предприятие – от теории к практике

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

Я давно отметил достаточно серьезный интерес сообщества к вопросам оптимизации и повышения производительности высоконагруженных систем. Общаясь с различными специалистами, обслуживающими малые и большие предприятия (торговые и производственные), я пришел к выводу, что вопросы повышения производительности интересны почти всем, вне зависимости от того, какую конфигурацию они обслуживают – большую или маленькую, измененную или без значительных изменений. В связи с этим я пришел к выводу, что стоит посвятить данный материал вопросам оптимизации запросов, поскольку именно запросы являются основным инструментом извлечения данных из системы.

07.10.2016    36449    0    bpc222    20    

Miracle Native - ВК для V8 Промо

Разработка внешних компонент v8 Россия Бесплатно (free)

Настоящая ВК написана по технологии 1С-Native. По методам и свойствам является наследницей MIracveV8 с планируемым развитием функционала. Версия 1.2.1.1 Не триальная, подправлена некорректная работа под х64

23.04.2012    30784    0    Abadonna    81    

.Net Core, обмен с 1C по TCP/IP между различными устройствами

Разработка внешних компонент v8 Бесплатно (free)

Часто нужно обмениваться данными с клиентом 1С из различных устройств, между клиентами 1С, а также при виртуализации между разными ОС на компьютере. Это кроссплатформенная ВК, позволяющая обмениваться сообщениями по TCP/IP между различными устройствами по определенному протоколу.

28.09.2016    20248    0    Serginio    8    

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

Разработка внешних компонент v8 Бесплатно (free)

Часто нужно использовать события объектов .Net. Например событие от COM порта, поступление сообщений по WhatsAp, сообщение об изменение в директории итд. Напрямую этого сделать нельзя, но можно сделать класс обертку и через него получать ВнешнееСобытие

14.09.2016    15437    0    Serginio    1    

.Net Core, 1C, динамическая компиляция, Scripting API

Разработка внешних компонент Практика программирования v8 Бесплатно (free)

Очень часто приходится использовать динамический код в 1С, используя Выполнить или Вычислить. Аналогичная задача и для использования скриптов на .Net. Я постарался показать, как можно скрестить ежа с ужом и получить удобный код. В этой статье много вражеского кода для чистого одноэсника, но все когда-то бывает впервые.

07.09.2016    18315    0    Serginio    7    

Альтернативные способы работы с XML. Часть 2: Введение в xPath или запросы к XML Промо

Обмен через XML Математика и алгоритмы v8 1cv8.cf Бесплатно (free)

В предыдущей статье "Введение в DOM или объектная модель документа" было описано понятие объектной модели документа (DOM), раскрыты плюсы и минусы использования модели при разборе файлов XML, приведено сравнение с построчным последовательным разбором. Были представлены варианты выборки данных с помощью объекта 1С ДокументDOM. Теперь настало время познакомить читателей с самым, на мой взгляд, интересным способом извлечения данных из XML - при помощи языка запросов xPath.

09.08.2012    41170    0    1cspecialist    13    

1С, Linux, Excel, Word, OpenXML, ADO, Net Core

Разработка внешних компонент v8 Бесплатно (free)

В данной статье показаны примеры кроссплатформенной работы с файлами Excel и Word (xlsx,docx) с помощью библиотеки OpenXML и Net Core

22.08.2016    20088    0    Serginio    14    

Асинхронное программирование в 1С через использование классов .Net из Native ВК

Разработка внешних компонент v8 Бесплатно (free)

Это продолжение статьи Кроссплатформенное использование классов .Net в 1С через Native ВК. Или замена COM на Linux II http://infostart.ru/public/541518/ В этой статье покажу, как можно асинхронно вызывать асинхронные методы и вызывать ВнешнееСобытие в 1С из сборки .Net

09.08.2016    17025    0    Serginio    3    

Регистры сведений 1С. Как это устроено.

Математика и алгоритмы v8 Бесплатно (free)

Основная идея публикации - собрать в одном месте информацию о внутреннем устройстве такой абстрактной сущности, как "Регистр сведений 1С" и ответить на ряд вопросов: Что происходит при записи регистра в различных режимах? Что такое на самом деле "СрезПервых" и "СрезПоследних"? Как оптимально выбрать структуру регистра? Это та информация, владея которой, начинаешь лучше понимать как это работает и как правильно использовать регистры сведений.

05.08.2016    175559    0    Sergey.Noskov    156    

Переводим расширения на 8.3.8. Памятка.

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

Типовые конфигурации переходят на новую платформу 8.3.8 без режима совместимости. А значит нужно переделывать расширения под эти условия. В статье небольшая памятка о переводе расширения на 8.3.8

29.07.2016    45720    0    mrXoxot    12