Здравствуйте, Alexandr Sulimov, Вы писали:
AS>Пишу Addin к 1С на С# VS 2005
AS>Примеры взяты с здесьАвтор(ы): Алексей Столповских
Дата: 20.11.2004
Данная статья описывает технологию создания COM+-компонента для 1С на C#. Код компонента был написан с использованием Microsoft Visual Studio.NET 2003, классов Microsoft .NET Framework 1.1 и протестирован на операционной системе Windows Server 2003 System.
и здесь
AS>Сделано как написано выше, но при подключении к 1С <Неизвестная компонента> (отсутствует интерфейс IInitDone)
AS>На РСДН такая проблема проскакивала здесьАвтор: Bootch
Дата: 23.05.04
, но решение не приводилось, может кто сталкивался.
AS>В чем проблема?
Вот рабочие исходники базового компонента для ВК:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.EnterpriseServices;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace OneC.ExternalComponents
{
public delegate void InitEventHandler();
public delegate void DoneEventHandler();
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property)]
public class Export1cAttribute : Attribute
{
public readonly bool ValidOn;
public Export1cAttribute()
{
ValidOn = true;
}
public Export1cAttribute(bool _validon)
{
ValidOn = _validon;
}
}
[Guid("ab634004-f13d-11d0-a459-004095e1daea")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[ComImport]
public interface IAsyncEvent
{
/// Установка глубины буфера событий
/// <param name="depth">Buffer depth</param>
void SetEventBufferDepth(Int32 depth);
/// Получение глубины буфера событий
/// <param name="depth">Buffer depth</param>
void GetEventBufferDepth(ref long depth);
/// Посылка события
/// <param name="source">Event source</param>
/// <param name="message">Event message</param>
/// <param name="data">Event data</param>
void ExternalEvent(
[MarshalAs(UnmanagedType.BStr)] String source,
[MarshalAs(UnmanagedType.BStr)] String message,
[MarshalAs(UnmanagedType.BStr)] String data
);
/// Очистка буфера событий
void CleanBuffer();
}
[Guid("AB634005-F13D-11D0-A459-004095E1DAEA")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[ComImport]
public interface IStatusLine
{
/// Задает текст статусной строки
/// <param name="bstrStatusLine">Текст статусной строки</param>
void SetStarusLine([MarshalAs(UnmanagedType.BStr)]String bstrStatusLine);
/// Сброс статусной строки
void ResetStatusLine();
}
[Guid("AB634001-F13D-11d0-A459-004095E1DAEA")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[ComImport]
public interface IInitDone
{
void Init([MarshalAs(UnmanagedType.IDispatch)]object connection);
void Done();
void GetInfo([MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)]
ref object[] info);
}
[Guid("AB634003-F13D-11d0-A459-004095E1DAEA")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[ComImport]
public interface ILanguageExtender
{
void RegisterExtensionAs([MarshalAs(UnmanagedType.BStr)]ref String extensionName);
void GetNProps(ref Int32 props);
void FindProp([MarshalAs(UnmanagedType.BStr)]String propName, ref Int32 propNum);
void GetPropName(Int32 propNum, Int32 propAlias, [MarshalAs(UnmanagedType.BStr)]ref String propName);
void GetPropVal(Int32 propNum, ref object propVal);
void SetPropVal(Int32 propNum, ref object propVal);
void IsPropReadable(Int32 propNum, ref bool propRead);
void IsPropWritable(Int32 propNum, ref Boolean propWrite);
void GetNMethods(ref Int32 pMethods);
void FindMethod([MarshalAs(UnmanagedType.BStr)]String methodName, ref Int32 methodNum);
void GetMethodName(Int32 methodNum, Int32 methodAlias, [MarshalAs(UnmanagedType.BStr)]
ref String methodName);
void GetNParams(Int32 methodNum, ref Int32 pParams);
void GetParamDefValue(Int32 methodNum, Int32 paramNum, ref object paramDefValue);
void HasRetVal(Int32 methodNum, ref Boolean retValue);
void CallAsProc(Int32 methodNum, [MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)]
ref object[] pParams);
void CallAsFunc(Int32 methodNum, ref object retValue,
[MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)]
ref object[] pParams);
}
[ClassInterface(ClassInterfaceType.None)]
public class ExtComponentBase: ServicedComponent,IInitDone,ILanguageExtender
{
private IAsyncEvent asyncevent;
private IStatusLine statusline;
private string compname;
public event InitEventHandler InitEvent;
public event DoneEventHandler DoneEvent;
//таблица поиска номера метода по имени
private Hashtable MethodNameToNumber;
//таблица поиска имени метода по номеру
private Hashtable MethodNumberToName;
//таблица количества параметров у методов
private Hashtable MethodNumberCountParams;
//таблица поиска номера свойства по имени
private Hashtable PropNameToNumber;
//таблица поиска имени свойства по номеру
private Hashtable PropNumberToName;
//массив инфо о методах
private MethodInfo[] MethodsInfo;
//массив инфо о свойствах
private PropertyInfo[] PropsInfo;
//интерфейс вызова событий в 1с
protected IAsyncEvent Async
{
get{return asyncevent;}
}
//интерфейс работы со строкой статуса
protected IStatusLine StatusLine
{
get{return statusline;}
}
// имя компоненты при регистрации
protected string ComponentName
{
get{return compname;}
set{compname = value;}
}
//Инициализация компоненты
void IInitDone.Init([MarshalAs(UnmanagedType.IDispatch)]
object connection)
{
asyncevent = (IAsyncEvent)connection;
statusline = (IStatusLine)connection;
if (InitEvent != null)
{
InitEvent();
}
}
void IInitDone.GetInfo([MarshalAs(UnmanagedType.SafeArray, SafeArraySubType=VarEnum.VT_VARIANT)]
ref object[] info)
{
info[0] = 2000;
}
//деинициализация компоненты
void IInitDone.Done()
{
if (DoneEvent != null)
{
DoneEvent();
}
}
//регистрация компоненты в 1с
void ILanguageExtender.RegisterExtensionAs([MarshalAs(UnmanagedType.BStr)]
ref String extensionName)
{
MethodNameToNumber = new Hashtable();
MethodNumberToName = new Hashtable();
MethodNumberCountParams = new Hashtable();
PropNameToNumber = new Hashtable();
PropNumberToName = new Hashtable();
ArrayList TempMethodsInfo = new ArrayList();
ArrayList TempPropsInfo = new ArrayList();
foreach (MethodInfo m in this.GetType().GetMethods())
{
if ((m.DeclaringType == this.GetType()) &&
!(m.IsConstructor))
{
object[] attrs = m.GetCustomAttributes(true);
foreach (object attr in attrs)
{
if ((attr is Export1cAttribute) & (((Export1cAttribute)attr).ValidOn))
{
int Identifier = TempMethodsInfo.Add(m);
MethodNameToNumber.Add(m.Name,Identifier);
MethodNumberToName.Add(Identifier,m.Name);
MethodNumberCountParams.Add(Identifier,m.GetParameters().Length);
break;
}
}
}
}
foreach (PropertyInfo p in this.GetType().GetProperties())
{
if (p.DeclaringType == this.GetType())
{
object[] attrs = p.GetCustomAttributes(true);
foreach (object attr in attrs)
{
if ((attr is Export1cAttribute) & (((Export1cAttribute)attr).ValidOn))
{
int Identifier = TempPropsInfo.Add(p);
PropNameToNumber.Add(p.Name,Identifier);
PropNumberToName.Add(Identifier,p.Name);
break;
}
}
}
}
MethodsInfo = (MethodInfo[])TempMethodsInfo.ToArray(typeof(MethodInfo));
PropsInfo = (PropertyInfo[])TempPropsInfo.ToArray(typeof(PropertyInfo));
if (compname != null)
{
extensionName = compname;
}
else
{
throw new Exception("Не указано имя компоненты");
}
}
//Возвращает количество свойств
void ILanguageExtender.GetNProps(ref Int32 props)
{
props = PropsInfo.Length;
}
//Возвращает целочисленный идентификатор свойства, соответствующий
// переданному имени
void ILanguageExtender.FindProp([MarshalAs(UnmanagedType.BStr)]String propName,
ref Int32 propNum)
{
propNum = (int)PropNameToNumber[propName];
if (propNum == 0)
{
throw new Exception("Свойство с именем "+propName+" не найдено");
}
}
//Возвращает имя свойства, соответствующее
//переданному целочисленному идентификатору
void ILanguageExtender.GetPropName(Int32 propNum,Int32 propAlias,
[MarshalAs(UnmanagedType.BStr)]ref String propName)
{
propName = (string)PropNumberToName[propNum];
if (propName == null)
{
throw new Exception("Ошибка свойство не найдено");
}
}
//Возвращает значение свойства.
void ILanguageExtender.GetPropVal(Int32 propNum,ref object propVal)
{
propVal = PropsInfo[propNum].GetValue(this,null);
}
//Устанавливает значение свойства.
void ILanguageExtender.SetPropVal(Int32 propNum,ref object propVal)
{
PropsInfo[propNum].SetValue(this,propVal,null);
}
//Определяет, можно ли читать значение свойства.
void ILanguageExtender.IsPropReadable(Int32 propNum, ref bool propRead)
{
propRead = PropsInfo[propNum].CanRead;
}
//Определяет, можно ли изменять значение свойства
void ILanguageExtender.IsPropWritable(Int32 propNum, ref Boolean propWrite)
{
propWrite = PropsInfo[propNum].CanWrite;
}
//Возвращает количество методов
void ILanguageExtender.GetNMethods(ref Int32 pMethods)
{
pMethods = MethodsInfo.Length;
}
// Возвращает идентификатор метода по его имени
void ILanguageExtender.FindMethod([MarshalAs(UnmanagedType.BStr)]String methodName,
ref Int32 methodNum)
{
methodNum = (int)MethodNameToNumber[methodName];
if (methodNum == 0)
{
throw new Exception("Метод с именем "+methodName+" не найден");
}
}
// Возвращает имя метода по его идентификатору
void ILanguageExtender.GetMethodName(Int32 methodNum,Int32 methodAlias,
[MarshalAs(UnmanagedType.BStr)]ref String methodName)
{
methodName = (string)MethodNumberToName[methodNum];
if (methodName == null)
{
throw new Exception("Ошибка метод не найден");
}
}
// Возвращает количество параметров метода по его идентификатору
void ILanguageExtender.GetNParams(Int32 methodNum, ref Int32 pParams)
{
pParams = (int)MethodNumberCountParams[methodNum];
}
//Возвращает значение параметра метода поумолчанию
void ILanguageExtender.GetParamDefValue(Int32 methodNum,Int32 paramNum,ref object paramDefValue)
{
paramDefValue = MethodsInfo[methodNum].GetParameters()[paramNum].DefaultValue;
}
//Указывает, что у метода есть возвращаемое значение
void ILanguageExtender.HasRetVal(Int32 methodNum, ref Boolean retValue)
{
if (MethodsInfo[methodNum].ReturnType == typeof(void))
{
retValue = false;
}
else
{
retValue = true;
}
}
// Вызов метода как процедуры с использованием идентификатора
void ILanguageExtender.CallAsFunc(Int32 methodNum,ref object retValue,
[MarshalAs(UnmanagedType.SafeArray, SafeArraySubType=VarEnum.VT_VARIANT)]
ref object[] pParams)
{
retValue = MethodsInfo[methodNum].Invoke(this, pParams);
}
// Вызов метода как функции с использованием идентификатора
void ILanguageExtender.CallAsProc(Int32 methodNum,[MarshalAs(UnmanagedType.SafeArray, SafeArraySubType=VarEnum.VT_VARIANT)]
ref object[] pParams)
{
MethodsInfo[methodNum].Invoke(this, pParams);
}
}
}
А это пример самой ВК для работы с COM-портом:
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.IO.Ports;
using System.Threading;
using OneC.ExternalComponents;
using System.Windows.Forms;
namespace CardReaderMR2000
{
[Guid("835E5814-3642-4433-8473-FA4D90E88C4E")]
[ProgId("AddIn.CardReaderMR2000")]
public class CardReader: ExtComponentBase
{
private SerialPort sp;
private string inputData="";
[Export1c]
public string Port
{
get{return sp.PortName;}
set {sp.PortName = value; }
}
public CardReader()
{
ComponentName = "CardReaderMR2000";
InitEvent += new InitEventHandler(Initialization);
}
public void Initialization()
{
sp = new SerialPort();
sp.PortName = "COM5";
sp.ReadTimeout = -1;
sp.BaudRate = 9600;
sp.Parity = Parity.None;
sp.DataBits = 8;
sp.StopBits = StopBits.One;
sp.Handshake = Handshake.None;
sp.DtrEnable = true;
sp.RtsEnable = true;
sp.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived);
}
void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
string chr = sp.ReadExisting();
if (chr != string.Empty && chr[0] != Convert.ToChar(10))
{
if (chr[0] != Convert.ToChar(13))
{
inputData += chr;
}
else
{
Thread t = new Thread(new ThreadStart(ReadData));
t.Start();
}
}
}
private void ReadData()
{
lock (inputData)
{
this.Async.ExternalEvent("AddIn.CardReaderMR2000", "ДанныеКарты", inputData);
inputData = "";
}
}
[Export1c]
public void Open()
{
sp.Open();
}
[Export1c]
public void Close()
{
sp.Close();
}
}
}
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>