Библиотека классов для создания внешней компоненты 1С на C#

01.03.15

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

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

Скачать файлы

Наименование Файл Версия Размер
Библиотека для создания внешних компонент на C#
.zip 9,60Kb
236
.zip 9,60Kb 236 Скачать

and it will, I hope, soon seem

as clear as a mountain creek!

Bertrand Meyer

 

Любой программист, которому приходилось написать несколько внешних компонент 1С:Предприятия, наверняка задумывался о странностях реализации интерфейсов IInitDone и ILanguageExtender. Зачем каждый раз полностью копировать реализацию некоторых методов, вроде FindProp или GetPropName? Почему так неудобно передаются параметры вызовов из 1С в CallAsProp и CallAsFunc в виде массивов? И почему нарушен один из основополагающих принципов объектно-ориентированного программирования (ООП) - прямое отображение? (Речь идет о таинственном объекте в 1С, который создается с помощью

ОбъектКомпоненты = Новый("AddIn.SomeName");

но который никак не представлен во внешней компоненте!). В этой статье автором предложен набор классов, который скрывает сложности служебных интерфейсов 1С, включая все трудности маршаллига COM-интерфейсов параметров 1С:Предприятия и позволяет написать внешнюю компоненту, просто создав обычный класс .Net на C#.

 

КАК ПОЛЬЗОВАТЬСЯ

 

Сначала покажем, как написать внешнюю компоненту с помощью библиотеки, прилагаемой в качестве примера к данной статье. Читатели не интересующиеся архитектурой, следующий раздел могут не читать. Но оценить, насколько все стало проще и элегантнее, наверное, сможет каждый. Настройки проекта в Visual Studio, как зарегистрировать dll внешней компоненты и другие нюансы, существенные для начинающих, здесь не объясняются.

Итак, вначале создадим в проекте на C# в Visual Studio типа "Class library" новый открытый (public) класс. Он может быть статическим, тогда наличие (разумеется статического) конструктора не обязательно, либо обычным динамическим, в этом случае обязательное требование - присутствие публичного конструктора по-умолчанию (без параметров), так как это класс и будет представлением того самого виртуального объекта 1С AddIn. Дальше также просто: открытые свойства класса - это свойства объекта, если свойство только get - значит в 1С оно будет доступно только для чтения, set - для записи. Открытые методы класса - методы объекта AddIn с полным соответствием с возвращаемым значением и параметрами. Например:

public class SomeName
{
 public SomeName() 
 {
  InstanceName = "SomeName";
 }

 public bool IsEnabled {get; set;}
 public string InstanceName {get; private set;}
 public object Make(string How, int Count) 
 {
   if (IsEnabled)
   {
    InstanceName = String.Empty;
    for (int i=0;i<Count;++i)
     V8Context.CreateContext().V8Message(MessageTypes.Info,How);
   }
  return null;
 }
}

такой класс будет виден в 1С как объект AddIn.SomeName со свойствами IsEnabled типа булево для чтения и записи, InstanceName - только для чтения и методом Make, возвращающим произвольное значение. Не забываем об ограничениях типов 1С:Предприятия: параметры и свойства могут быть типов string, bool, int, double, decimal, DateTime и object, который может инкапсулировать перечисленные до него типы, содержать null (в 1С Неопределено) либо передавать COM-объект, созданный в компоненте и реализующий интерфейс IDispatch. (В net это реализуется созданием класса с атрибутами [ComVisible] и [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]). Возможна передача массивов этих типов, но в 1С они будут соответствовать не объекту Массив, а COMSafeArray. Класс конечно же может иметь и скрытые (private или protected) поля, свойства, методы, они будут скрыты и для 1С.

После создания и реализации класса, необходимо "подключить" его к библитеке. Для этого копируем папку AddIn из шаблона библиотеки и создаем простой класс-заглушку:

using System;
using System.Reflection;
using System.Runtime.InteropServices;
using V8.AddIn;

[ComVisible(true)]
[Guid("6a81d0a9-6441-463f-a0c9-ec7b1f2cbd56")] // произвольный Guid-идентификатор Вашей компоненты
[ProgId("AddIn.SomeComponent")] // это имя COM-объекта, по которому Вы будете ее подключать
public class Some : LanguageExtenderAddIn
{
 public Some() : base(typeof(SomeName), 1000) {}
}

Класс LanguageExtenderAddIn содержит реализацию всей интерфейсной части компоненты, в его конструктор передается описание типа объекта компоненты и номер версии (он может быть 1000 или 2000). Подключается компонента инструкцией:

ПодключитьВнешнююКомпоненту("AddIn.SomeComponent");

В целом все, проект собирается и компонента готова. Остались мелкие детали.

Вывод сообщений, дополнительные интерфейсы. Реализованы с помощью класса V8Context. Это синглетон, его не следует создавать явно, а вызывать конструкцией:

V8Context.CreateV8Context()

Он содержит перезагруженные методы V8Message, выводящие текст в окно сообщений или диалог с предупреждением об ошибке. Например,

V8Context.CreateV8Context().V8Message(MessageTypes.MsgboxInfo, "Текст сообщения");

выведет информационный диалог с текстом. Также класс V8Context имеет свойство AsyncEvent, реализующее интерфейс IAsyncEvent для отправки сообщений в 1С.

Русскоязычные синонимы, параметры по умолчанию устанавливаются с помощью атрибутов Alias и HasDefaultValue. В качестве примера, дополним класс SomeName:

public class SomeName
{
 public SomeName() {}
 
 [Alias("Включена")]
 public bool IsEnabled {get; set;}
 [Alias("ИмяЭкземпляра")]
 public string InstanceName {get; private set;}

 [Alias("Выполнить")]
 public object Make(string How, [HasDefaultValue(1)] int Count) { return null;}
}

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

ПодключитьВнешнююКомпоненту("AddIn.SomeComponent");
ОбъектКомпоненты = Новый("AddIn.SomeName");
ОбъектКомпоненты.Включена = Истина;
Если ПустаяСтрока(ОбъектКомпоненты.InstanceName) Тогда
 ОбъектКомпоненты.Выполнить("Быстро");
КонецЕсли;

ИНТЕРФЕЙСЫ ВНУТРЬ И НАРУЖУ

(УСТРОЙСТВО БИБЛИОТЕКИ)


Для улучшения какого-либо программного решения, необходимо выяснить, что в нем не устраивает. Изучив примеры создания внешних компонент с дисков ИТС, ответ напрашивается сам собой - отсутствие подходящего коннектора между addin объектом компоненты и 1С:Предприятием. И дело не в том, что в примерах он (как класс) вообще не реализован, а в том что даже написав его, мы были бы вынуждены вызывать свойства и методы через их описания массивами строк. Код этого объекта все равно бы находился внутри класса, реализующего ILanguageExtender. Net Framework с самой первой версии имеет замечательный механизм отражения своих метаданных - пространство имен Reflection. Полезность его использования при создании компонент была отмечена в статье (http://rsdn.ru/article/dotnet/cs1c.xml), но автор остановился на пол пути и не отделил реализацию компоненты от интерфейсной части 1С.

Технология внешних компонент предоставляет ряд интерфейсов, из которых IInitDone и ILanguageExtender нужны только для использования внутри 1С. 1С:Предприятие по ним распознает внешнюю компоненту и управляет ей. Для программиста их реализация - лишняя работа, поэтому мы попытаемся их отделить. Начнем с IInitDone, имеющего три метода и создадим его реализацию:

 

using System;
using System.Runtime.InteropServices;

namespace V8.AddIn
{
 [ComVisible(true), Guid("bc631c98-2f0b-49b9-b722-b7e223e46059")]
 public abstract class InitAddIn : IInitDone
 {
  private int m_Version;
  protected InitAddIn(int Version)
  {
   this.m_Version = Version;
  }
  void IInitDone.Init([MarshalAs(UnmanagedType.IDispatch)] object pConnection)
  {
   new V8Context(pConnection);
  }
  void IInitDone.Done()
  {
   GC.Collect();
   GC.WaitForPendingFinalizers();
  }
  void IInitDone.GetInfo([MarshalAs(UnmanagedType.SafeArray)] ref object[] pInfo)
  {
   pInfo.SetValue(this.m_Version, 0);
  }
 }
}

подключение компоненты начинается с вызова Init, в нем мы инициализируем V8Context объектом 1С. Оставшийся код очевиден: храним версию компоненты и принудительно собираем мусор при закрытии 1С в методе Done. В принципе после этого уже можно написать компоненту, например так:

 

using System;
using System.Reflection;
using System.Runtime.InteropServices;
using V8.AddIn;

[ComVisible(true)]
[Guid("73D8A32F-8195-4482-B845-71B6535DC079")]
public class VoidComponent : InitAddIn
{
 public VoidComponent() : base(1000) {}
}

Это компонента, не реализующая расширения встроенного языка, о ней многие забывают. Такие компоненты могут вызывать внешние события в 1С, например от какого-то оборудования и выводить сообщения. При реализации ILanguageExtender прийдется воспользоваться всей мощью пространства Reflection. Как уже было видно в примере, в конструктор абстрактного класса LanguageExtenderAddIn передается описание типа класса компоненты (Type). Через него необходимо выполнять вызовы свойств и методов класса. Вначале посмотрим на объвление, конструктор и служебные члены класса:

using System;
using System.Reflection;
using System.Runtime.InteropServices;

namespace V8.AddIn
{
 [Guid("43295454-83da-49a0-beca-58a9f6ac1ef0"), ComVisible(true)]
 public abstract class LanguageExtenderAddIn : InitAddIn, ILanguageExtender
 {
  private string m_Name;
  private PropertyInfo[] m_Properties;
  private MethodInfo[] m_Methods;

  private object m_Wrapper;

  private void InitWrapperInfo(Type WrapperType, BindingFlags flags)
  {
   this.m_Name = WrapperType.Name;
   this.m_Properties = WrapperType.GetProperties(flags);
   this.m_Methods = WrapperType.GetMethods(flags);
  }

  protected LanguageExtenderAddIn(Type WrapperType, int Version) : base(Version)
  {
   ConstructorInfo constructor = WrapperType.GetConstructor(Type.EmptyTypes);
   if (constructor == null)
   {
    this.InitWrapperInfo(WrapperType, BindingFlags.Static | BindingFlags.Public);
	return;
   }
   this.m_Wrapper = constructor.Invoke(null);
   this.InitWrapperInfo(WrapperType, BindingFlags.Instance | BindingFlags.Public);
  }

Объект m_Wrapper - это экземпляр класса компоненты. Мы храним описание его свойств и методов в массивах m_Properties и m_Methods. При отсутствии конструктора по умолчанию, полагаем что имеем дело со статическим классом, для которого вызов Invoke не нужен. Покажем два простых примера, реализацию RegisterExtensionAs и GetNProps:

void ILanguageExtender.RegisterExtensionAs([MarshalAs(UnmanagedType.BStr)] ref string bstrExtensionName)
{
 bstrExtensionName = m_Name;
}
void ILanguageExtender.GetNProps(ref int plProps)
{
 plProps = this.m_Properties.GetLength(0);
}

Далее при реализации методов ILanguageExtender необходмо вызывать обращаться к классу компоненты через их описания, не забывая существование русских синонимов (для этого нужно получать значения атрибута Alias):

void ILanguageExtender.FindProp([MarshalAs(UnmanagedType.BStr)] string bstrPropName, ref int plPropNum)
{
 plPropNum = 0;
 Type typeFromHandle = typeof(AliasAttribute);
 for (int i = 0; i <= this.m_Properties.GetUpperBound(0); i++)
 {
  AliasAttribute aliasAttribute = (AliasAttribute)Attribute.GetCustomAttribute(this.m_Properties[i], typeFromHandle);
  if (this.m_Properties[i].Name.ToUpper() == bstrPropName.ToUpper() || (aliasAttribute != null && aliasAttribute.AliasName.ToUpper() == bstrPropName.ToUpper()))
  {
   plPropNum = ++i;
   return;
  }
 }
}
void ILanguageExtender.GetPropVal(int lPropNum, ref object pvarPropVal)
{
 PropertyInfo propertyInfo = this.m_Properties[lPropNum - 1];
 try
 {
  pvarPropVal = propertyInfo.GetValue(this.m_Wrapper, null);
 }
 catch (Exception ex)
 {
  V8Context v8Context = V8Context.CreateV8Context();
  if (ex.InnerException!=null)
   v8Context.V8Message(MessageTypes.Fail, ex.InnerException.Message, ex.InnerException.Source);
  else
   v8Context.V8Message(MessageTypes.Fail, ex.Message, ex.Source);
 }
}

Обработку исключений необходимо делать в компоненте, так как любой Exception из net framework в 1С будет восприниматься как исключение в mscorlib.dll без расшифровки. В следующем примере показана реализация GetParamDefValue и обработка атрибута HasDefaultValue:

 

void ILanguageExtender.GetParamDefValue(int lMethodNum, int lParamNum, ref object pvarParamDefValue)
{
 ParameterInfo element = this.m_Methods[lMethodNum - 1].GetParameters()[lParamNum];
 HasDefaultValueAttribute hasDefaultValueAttribute = (HasDefaultValueAttribute)Attribute.GetCustomAttribute(element, typeof(HasDefaultValueAttribute));
 if (hasDefaultValueAttribute != null)
 {
  pvarParamDefValue = hasDefaultValueAttribute.DefaultValue;
 }
}

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

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

См. также

Медиадисплей. Рекламный информационный монитор для покупателя.

Разработка внешних компонент POS терминал Рабочее место Розничная торговля Платформа 1С v8.3 1С:Комплексная автоматизация 1.х 1С:Управление торговлей 10 1С:Розница 2 1С:Управление нашей фирмой 1.6 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х Розничная и сетевая торговля (FMCG) Рестораны, кафе и фаст-фуд Реклама, PR и маркетинг Управленческий учет Платные (руб)

Монитор покупателя может отображать текущую покупку на кассовом месте, показывать видеорекламу, баннеры, во время простоя разворачивать рекламу на весь экран. Можно использовать в качестве графического меню-борда в кафе и видеовывески. Управление выводом на телевизор через hdmi-приставку на базе Windows или Android. В качестве устройства отображения можно использовать Android-планшеты, фоторамки с Android, монитор любого Windows-компьютера, доступного по сети. Настраивается ЛЮБОЙ ДИЗАЙН экрана!

16800 руб.

30.05.2017    52098    34    69    

43

Внешняя компонента для сканирования (замена TWAIN-компоненты БСП) (Native Win 32/64)

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

Внешняя компонента позволяет работать c TWAIN-совместимым оборудованием (сканерами, камерами) . Полностью совместима со стандартной TWAIN-компонентой из БСП и может применяться как ее замена без изменения вызовов, при этом может работать с 64-разрядной платформой, а так же имеет расширенную функциональность, например, сохранение результата непосредственно в PDF без использования сторонних утилит. Прекрасно работает на сервере, тонком клиенте и веб-клиенте (проверена работа в браузерах Google Chrome, Mozilla Firefox и Microsoft Internet Explorer).

2400 руб.

12.05.2020    26242    131    99    

83

Внешняя компонента для подключения 1С к телефонии Asterisk

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

Внешняя компонента выполнена по технологии Native API для 1С 8.х, обеспечивает доступ к программным АТС Asterisk (FreePBX, Elastix) через AMI интерфейс. Через него можно управлять многими функциями Asterisk (определение номеров, перевод звонков, набор телефона и т. д.)

2400 руб.

04.05.2018    44974    117    64    

60

Внешняя компонента печати PDF (Native Win 32/64)

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

Внешняя компонента позволяет печатать PDF файлы непосредственно из 1С, не используя при этом сторонних программ. Прекрасно работает на сервере, тонком клиенте и веб-клиенте. Основана на проекте PDFium из состава проекта Chromium/Chrome

1500 руб.

17.09.2018    35074    104    123    

111

Мастер создания внешних компонент 1С (технология COM) для DELPHI 6/7/8/2005/2006/2007/2008/2010/XE/XE2/XE3

Разработка внешних компонент Платформа 1С v8.3 Платные (руб)

Средство для сверхбыстрой разработки внешних компонент 1С:Предприятия 7.7 и 8 по технологии COM на всех версиях DELPHI, начиная с 6.

2000 руб.

28.03.2013    53997    35    14    

68

QR-код с логотипом компании (обычная и управляемая форма)

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

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

2400 руб.

22.06.2016    30839    4    4    

8

Внешняя компонента 1С и С++. Продолжаем разговор.

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

А давайте запилим 8.3.26 до релиза, или оповещение с сервера...

19.02.2024    4037    starik-2005    28    

52

Внешние компоненты 1С и язык C++

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

Некоторые практические аспекты создания внешних компонент на языке С++ для платформы 1С 8.3++.

26.01.2024    4774    starik-2005    32    

39
Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. I_G_O_R 69 02.03.15 23:50 Сейчас в теме
к сожалению в СП написано, что подключение компоненты, созданной по технологии com, не работает на сервере.
18. _Devill 26.09.17 10:30 Сейчас в теме
Пытаюсь создать внешнюю компоненту с помощью вашей библиотеки. 1С выдает ошибку : Тип не определен (AddIn.SomeName)
ОбъектКомпоненты = Новый("AddIn.SomeName");
Код компоненты:
using System;
using System.Reflection;
using System.Runtime.InteropServices;
using V8.AddIn;

namespace V8.AddIn
{

    [ComVisible(true)]
    [Guid("9fe0db43-beef-4358-b46a-1fb0f80c9bd6")] // произвольный Guid-идентификатор Вашей компоненты
    [ProgId("AddIn.SomeComponent")] // это имя COM-объекта, по которому Вы будете ее подключать
    public class Some : LanguageExtenderAddIn
    {
        public Some() : base(typeof(SomeName), 1000) { }
    }

    public class SomeName
   { 
        public SomeName() { }

        [Alias("Включена")]
        public bool IsEnabled { get; set; }
        [Alias("ИмяЭкземпляра")]
        public string InstanceName { get; private set; }

        [Alias("Выполнить")]
        public object Make(string How, [HasDefaultValue(1)] int Count) { return null; }
        
    }

    
}
Показать


Подскажите пожалуйста что делаю не так?
19. spacecraft 26.09.17 10:55 Сейчас в теме
(18)
ОбъектКомпоненты = Новый("AddIn.SomeName");

[ProgId("AddIn.SomeComponent")] // это имя COM-объекта, по которому Вы будете ее подключать
Оно?
2. nixel 1403 04.03.15 11:24 Сейчас в теме
И линукс-системы в пролете.
Но идея отличная!
3. IgorKissil 350 04.03.15 11:57 Сейчас в теме
В статье описана старая технология внешних компонент, которая работает только на клиенте и только на Windows. Несмотря на то, что 1С позиционирует свою открытость к интеграции, поле инструментов для создания компонент NativeAPI сильно уменьшилось, фактически остался только C++. Пример их создания от 1С с точки зрения архитектуры имеет те же недостатки, которые описаны в статье, но методы преодоления сложнее, т.к. в C++ нет отражений.
5. I_G_O_R 69 08.05.15 13:59 Сейчас в теме
(3) на .NET тоже можно сделать компоненту NativeAPI используя Hosting CLR
4. AlexanderKai 16.04.15 13:43 Сейчас в теме
Кто-нибудь переписывал шаблон компоненты на Си (без плюсов)?
6. IgorKissil 350 04.08.15 06:52 Сейчас в теме
To 5: Можно сделать компоненту, можно вызывать через COM+, через Web сервисы в конце концов. Но все это через проксю, иными словами в отдельном процессе, следовательно присутствуют накладные расходы на межпроцессное взаимодействие (в том числе и в отдельном AppDomain, как в Вашей компоненте). Внешние компоненты 1С как com'овские так и нативные работают в общем адресном пространстве с 1С.
7. I_G_O_R 69 04.08.15 19:40 Сейчас в теме
(6) Я умею запускать и в основном домене, и даже использовать раннее связывание, при этом скорость значительно выше по сравнению с опубликованной компонентой, но конечно медленнее, чем компонента написанная только на с++. Но я и не утверждаю, что моя компонента и сам способ лучшие, у них единственный плюс - это простое развертывание, на сервер клиента бывает проблематично что-нибудь установить, а Native API компонента не требует установки в системе.
8. quick 583 20.10.15 14:38 Сейчас в теме
Я такую штуку делал в Delphi XE2, очень удобно методы подключать декораторами.
9. Serginio 938 29.12.15 14:32 Сейчас в теме
Работая с Глобальным контекстом проще работать через DynamicObject

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Dynamic;
using System.Reflection;
using System.Runtime.InteropServices;

namespace ТестВК
{

    class ДинамикГК : DynamicObject, IDisposable

{
        dynamic ГК1С;
        Type ТипГК;
        object App1C;

        void УничтожитьОбъект(object Объект)
        {
            Marshal.Release(Marshal.GetIDispatchForObject(Объект));
            Marshal.ReleaseComObject(Объект);


        }
  public ДинамикГК(dynamic ГК1С)
        {
            ТипГК = ГК1С.GetType();
            App1C = ГК1С.AppDispatch;
            this.ГК1С = ГК1С;


        }
    // установка свойства
    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
         try
        {
        ТипГК.InvokeMember(binder.Name, BindingFlags.SetProperty, null, App1C, new object[]{value});
        return true;
        }
         catch (Exception)
         {
         }
         return false;
    }
    // получение свойства
    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        try
        {
            result = ТипГК.InvokeMember(binder.Name, BindingFlags.GetProperty, null, App1C, null);
            return true;
        }
        catch (Exception)
        {  
        }
        result = null;
        return false;
    }
    // вызов метода
    public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
    {
       // dynamic method = members[binder.Name];
       // result = method((int)args[0]);
       // return result != null;
        if (binder.Name=="ЗакрытьОбъект")
        {

            Dispose();
            result = null;
            return true;

        }


        try
        {
            if (args.Length == 1 && args[0].GetType() == typeof(System.Object[]))
                result = ТипГК.InvokeMember(binder.Name, BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.InvokeMethod, null, App1C, (System.Object[])args[0]);
            else
                result = ТипГК.InvokeMember(binder.Name, BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.InvokeMethod, null, App1C, args);

            return true;
        }
        catch (Exception)
        {
        }
        result = null;
        return false;
    }

    bool disposed = false;
      public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    // Protected implementation of Dispose pattern. 
    protected virtual void Dispose(bool disposing)
    {
        if (disposed)
            return;

        if (disposing)
        {
            if (ГК1С != null)
            {
                УничтожитьОбъект(ГК1С);
                УничтожитьОбъект(App1C);
                ГК1С = null;
                App1C = null;
                // Free any other managed objects here. 
                //
            }
        }

        // Free any unmanaged objects here. 
        //
        disposed = true;
    }

  }


}
Показать


И использование


 public dynamic Новый( params object[] Параметры)
    {

        return ГК.NewObject(Параметры);
    }



ГК = new ДинамикГК(Object1C);

 ГК.Сообщить("Привет из ВК", ГК.СтатусСообщения.Важное);


dynamic Тз = Новый("ТаблицаЗначений");
    dynamic Колонки = Тз.Колонки;
    Колонки.Добавить("КолонкаЧисло", ПолучитьОписаниеТиповЧисла(9, 0));
    Колонки.Добавить("КолонкаЧисло4", ПолучитьОписаниеТиповЧисла(7, 2));

Показать


Подробне здесь http://infostart.ru/public/238584/
10. itworks 48 12.06.17 17:23 Сейчас в теме
Добрый день!
Подскажите пожалуйста! Сделал сборку с тестовым классом. В целом библиотека подключается, свойства читаются, методы вызываются. Но столкнулся с непонятным поведением.
Если вызывать метод отправки внешнего события в 1С несколько раз подряд, то в 1С обработчик внешнего события вызывается только один раз для первого вызова.
Кроме того, попробовал внутри метода класса запустить таймер, который каждую секунду должен выводить сообщение в 1С и дергать внешнее событие. Методы, которые вызываются в обработчике таймера не отрабатываются в 1С, как-будто обработчик таймера вообще не срабатывает. не могу понять в чем проблема.

namespace V8.AddIn
{
	public class MyTest1C
	{
		public MyTest1C()
		{
			this.InstanceName = "MyTest1C";
		}

		private Timer timer;

		[Alias("Включена")]
		public bool IsEnabled { get; set; }

		[Alias("ИмяЭкземпляра")]
		public string InstanceName { get; private set; }

		[Alias("Выполнить")]
		public void Make(string How, int Count)
		{
			if (IsEnabled)
			{
				timer = new Timer(1000);
				timer.AutoReset = true;
				timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
				timer.Start();

				V8Context.CreateV8Context().V8Message(MessageTypes.Info, "Hello!"); // Работает
				V8Context.CreateV8Context().V8Message(MessageTypes.Info, "Hello!"); // Работает
				V8Context.CreateV8Context().AsyncEvent.ExternalEvent("Test1", "Test2", "Test3"); // Работает
				V8Context.CreateV8Context().AsyncEvent.ExternalEvent("Test1", "Test2", "Test3"); // Не работает
			}
		}

		void timer_Elapsed(object sender, ElapsedEventArgs e)
		{
			V8Context.CreateV8Context().V8Message(MessageTypes.Info, "Hello!");		// Не работает
			V8Context.CreateV8Context().AsyncEvent.ExternalEvent("Test1", "Test2", "Test3"); // Не работает
		}
	}
}
Показать
11. I_G_O_R 69 12.06.17 21:26 Сейчас в теме
(10) Добрый день!
Вы явно пользуетесь не моей компонентой.
12. itworks 48 12.06.17 22:01 Сейчас в теме
(11) Я пользуюсь библиотекой, которую скачал в этой статье с помощью большой зеленой кнопки "Скачать".
"Библиотека для создания внешних компонент на C#"
Она не Ваша?
13. I_G_O_R 69 13.06.17 12:30 Сейчас в теме
(12) Я прошу прощения, мне вообще не стоило отвечать, это же не моя публикация))
просто уведомление пришло на почту, а я не внимательно прочитал...
16. IgorKissil 350 02.07.17 16:28 Сейчас в теме
(10) Сообщения пропадают из-за того, что Вы скорее всего не задали размер буфера. Что касается таймеров, Вы используете объект из пространства Threads или Timers, а они многопоточные. Многозадачность порождает проблемы даже в nativeAPI-компонентах, не говоря уж о .net. Ну хочет 1С, чтобы мы использовали их асинхронные вызовы, что тут поделаешь! Попробуйте прикрутить Timer из WinForms - он singlethreaded
14. twin 28.06.17 14:19 Сейчас в теме
Ну рабочий пример бы тут не помешал в архиве конечно.
15. twin 29.06.17 10:08 Сейчас в теме
Хотел сказать что код компоненты надо обернуть в

namespace V8.AddIn {

}

а то тип не будет виден.

В самой студии убедитесь, что у вас в Проект -> Свойства -> Сборка -> Регистрация для COM-Взаимодействия стоит галка
17. twin 17.07.17 15:05 Сейчас в теме
Подскажите, а как из кода вызвать
Состояние(<ТекстСообщения>, <Прогресс>, <Пояснение>, <Картинка>)
?
20. _Devill 26.09.17 12:02 Сейчас в теме
(19)
нет
ПодключитьВнешнююКомпоненту("AddIn.SomeComponent");
ОбъектКомпоненты = Новый("AddIn.SomeName");
21. spacecraft 27.09.17 16:14 Сейчас в теме
(20) ясно. Не там.
Там: конструктор класса пустой. В нем нужно заполнить InstanceName, тогда будет 1С видеть.
public SomeName() 
 {
  InstanceName = "SomeName";
 }
22. _Devill 28.09.17 07:29 Сейчас в теме
(21)
Заработало. Проблема была в том что 1С x64 была запущена.
23. _Devill 28.09.17 08:30 Сейчас в теме
24. _Devill 04.10.17 15:39 Сейчас в теме
Добрый день, не могу понять почему 1С видит только 3 свойства

using System;
    using System.Reflection;
    using System.Runtime.InteropServices;
    using System.Net;
    using System.Net.Sockets;
    using System.Text.RegularExpressions;
    using System.Text;
    using System.Threading;
    using System.IO;
    using V8.AddIn;


    namespace V8.AddIn
    {
        public class SomeName
        {
            private Socket clientSocket;

            [Alias("Пароль")]
            public string Password { get; set; }
            [Alias("IPАдрес")]
            public string IPAdress { get; set; }
            [Alias("Порт")]
            public int Port { get; set; }
            [Alias("ИмяПользователя")]
            public string Name { get; set; }


            [Alias("Подключиться")]
            public bool Connection()
            {


                clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse(IPAdress), Port);
                clientSocket.Connect(serverEndPoint);

                // Login to the server; manager.conf needs to be setup with matching credentials.
                clientSocket.Send(Encoding.ASCII.GetBytes("Action: Login\r\nUsername: "+ Name + "\r\nSecret: "+ Password + "\r\nActionID: 1\r\nEvents: off\r\nEventmask: call\r\n\r\n"));

                int bytesRead = 0;
                byte[] buffer = new byte[1024];
                bytesRead = clientSocket.Receive(buffer);
                string response = "";
                response = Encoding.ASCII.GetString(buffer, 0, bytesRead);

                if (Regex.Match(response, "Message: Authentication accepted", RegexOptions.IgnoreCase).Success)
                {
                    // Send a ping request the asterisk server will send back a pong response.
                    return true;

                } else
                {
                    return false;
                }

            }
            public SomeName()
            {

            }
        }

        [ComVisible(true)]
        [Guid("9fe0db43-beef-4358-b46a-1fb0f80c9bd6")] // произвольный Guid-идентификатор Вашей компоненты
        [ProgId("AddIn.Some")] // это имя COM-объекта, по которому Вы будете ее подключать
        public class Some : LanguageExtenderAddIn
        {
            public Some() : base(typeof(SomeName), 1000) { }
        }
    }
Показать
25. sersoft 03.03.21 14:52 Сейчас в теме
Добрый день, смотрю давно комментариев не было :)

Но я скачал данную библиотеку классов для реализации нативной библиотеки для работы с эквайринговой системой.

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

Не покажите пример кода на C# как создать внешнее событие чтобы можно было его отловить в обработчкие ВнешнееСобытие(Источник, Событие, Данные)

Заранее спасибо.
Оставьте свое сообщение