Com соединение с 1С из С++

Модераторы: Hawk, Romeo, Absurd, DeeJayC, WinMain

abtat
Сообщения: 3
Зарегистрирован: 24 янв 2007, 11:35

В 1С: Предприятие 8 предусмотрена возможность работать в режиме сервера (COMCntr.dll) и в ее документации даны примеры СОМ соединения из клиентов на Excel и другой 1С. Эти варианты я проверил - все идет. Пример Сом соединения С++ -> С++ по гл. 13 книги Калверта и Райсдорфа я также проверил - ОК. А вот при попытке вызвать 1С из клиента на С++ Builder 6 застрял на шаге Connect, передающем адрес базы, логин и пароль.
В файле V8_TLB.h, автоматически создаваемом оболочкой при подключении библиотеки типов из указанной dll, имеются объявления метода Connect с аргументом в виде символьной строки, содержащей все три компонента, разделенных <;>.
При попытке создать такой вызов
AnsiString basa;
wchar_t* wbasat;
int size;
basa = AnsiString("File =""D:\1C_8_Test_2"";usr = ""Admin"";");
size = basa.WideCharBufSize();
wbasat = basa.WideChar(wbasat,size);
TCOMIV8COMConnector V8ServerConnection = CoCOMConnector::Create();
V8ServerConnection->Connect(wbasat);
при вводе я получаю подсказку оболочки, что методу Connect требуется аргумент типа wchar_t, а вот преобразовать basa в wbasa с использованием объявленного в help метода StringToWideChar или описанного у Архангельского метода WideChar(wchar_t* dest, int destSize) класса АnsiString не удается - при компиляции замечаний нет, а в шаге исполнения этот оператор вызывает сбой в ядре из-за обращения по адресу 15.
Другой, описанный в гл. 14 Кальверта, способ создания COMсоединения:
Variant V8_app;
Variant Connection;
V8_app =Variant::CreateObject("V8.COMConnector");
Connection = V8_app.Connect("File =""D:\1C_7_Test_2"";usr = ""Admin"";");
вызывает при компиляции сообщение, что Connect не является членом класса Variant.
Если кто пробовал соединиться с 1С из С++ или Дельфи или формировал строки типа wchar_t - поделитесь опытом
Absurd
Сообщения: 1228
Зарегистрирован: 26 фев 2004, 13:24
Откуда: Pietari, Venäjä
Контактная информация:

А ему нужен wchar_t* или все-таки BSTR? В мире COM используется все таки обычно BSTR. BSTR str = SysAllocString(L"File =\"D:\\1C_8_Test_2\";usr = \"Admin\";");
2B OR NOT(2B) = FF
abtat
Сообщения: 3
Зарегистрирован: 24 янв 2007, 11:35

Система подсказок С++ требует wchar_t для передачи этого аргумента в 1С.
Использование BSTR по Вашему совету компилируется и линкуется, но дает сообщение
"this->Connect(connectString.(LPDISPATCH*)&Conn
неопознанная ошибка"
Absurd
Сообщения: 1228
Зарегистрирован: 26 фев 2004, 13:24
Откуда: Pietari, Venäjä
Контактная информация:

Система подсказок С++ требует wchar_t для передачи этого аргумента в 1С.
Использование BSTR по Вашему совету компилируется и линкуется, но дает сообщение
BSTR совместим с wchar_t*. Со сути, это подмножество wchar_t*.
Нельзя ли посмотреть Idl этого интерфейса?

PS: Кроме того, если Вам нужна просто wchar_t строка, то ее можно получить безо всяких конверсий типов:

Код: Выделить всё

wchar_t[] str = L"File =\"D:\\1C_8_Test_2\";usr = \"Admin\";";
2B OR NOT(2B) = FF
abtat
Сообщения: 3
Зарегистрирован: 24 янв 2007, 11:35

Действительно, connect в COMСоединении требует BSTR и выполняется, Ole объект "V8.Application" типа Variant создается, но связать его с базой данных 1С не удается, как я уже писал, с сообщением, что Connect не принадлежит классу Variant.
хотя в DispIntf интерфейсах в V8_TLB.h всегда присутствует Connect(...) или ConnectServer(...).
Ну и для меня пока непонятно, как можно включать в текст С++ программ строки инструкций на языке 1С, которые не всегда соответствуют синтаксическим правилам С++ и должны использовать русские названия процедур, функций и свойств, заложенные в 1С.
Аватара пользователя
WinMain
Сообщения: 929
Зарегистрирован: 14 янв 2005, 10:30
Откуда: Москва
Контактная информация:

На сколько я помню, в C++ Builder чтобы общаться с СОМ-объектом через класс Variant, используют методы Variant::OlePropertyGet(), Variant::OlePropertySet(), Variant::OleFunction() и Variant::OleProcedure(). Не помню точно, чем последние два метода отличаются друг от друга, наверно типом возвращаемого значения. В языке Pascal, видимо есть какая-то разница между функцией и процедурой. В любом случае, через них придётся вызывать методы типа "Connect" и передавать значения...
А на счёт того, что функции и методы в 1С русскоязычные, так вроде на каждую русскоязычную функцию там имеется свой англоязычный дублёр.
Absurd
Сообщения: 1228
Зарегистрирован: 26 фев 2004, 13:24
Откуда: Pietari, Venäjä
Контактная информация:

abtat писал(а):Действительно, connect в COMСоединении требует BSTR и выполняется, Ole объект "V8.Application" типа Variant создается, но связать его с базой данных 1С не удается, как я уже писал, с сообщением, что Connect не принадлежит классу Variant.
хотя в DispIntf интерфейсах в V8_TLB.h всегда присутствует Connect(...) или ConnectServer(...).
Можно воспользоваться либо COM -подходом, запросив через IUnknown нужный интерфейс, содержащий метод Connect, либо через OLE Automation, запросив IDispatch и вызвав нужную функцию через IDispatch->Invoke, передав туда имя функции в виде строки и параметры в виде OLE - массива вариантов.
abtat писал(а): Ну и для меня пока непонятно, как можно включать в текст С++ программ строки инструкций на языке 1С, которые не всегда соответствуют синтаксическим правилам С++ и должны использовать русские названия процедур, функций и свойств, заложенные в 1С.
Через OLE Automation и уникод я думаю.
2B OR NOT(2B) = FF
Владимир
Сообщения: 56
Зарегистрирован: 25 апр 2005, 13:57

Absurd писал(а):Можно воспользоваться либо COM -подходом, запросив через IUnknown нужный интерфейс, содержащий метод Connect, либо через OLE Automation, запросив IDispatch и вызвав нужную функцию через IDispatch->Invoke, передав туда имя функции в виде строки и параметры в виде OLE - массива вариантов.

Через OLE Automation и уникод я думаю.
Через IDispatch работает, вот пример работающего кода

Код: Выделить всё

CLSID CLSID_COMConnector;
CLSIDFromProgID(OLESTR("V8.COMConnector"),&CLSID_COMConnector);

IDispatch *pIV8COMConnector = NULL;
HRESULT hr = CoCreateInstance(CLSID_COMConnector,NULL,CLSCTX_INPROC_SERVER,IID_IDispatch,(void**)&pIV8COMConnector);
if SUCCEEDED(hr)
{
   OLECHAR * MethodName = OLESTR("Connect");
   DISPID dispid;

   pIV8COMConnector->GetIDsOfNames  (IID_NULL,&MethodName,1,LOCALE_SYSTEM_DEFAULT,&dispid);

   DISPPARAMS dispparam = {NULL,NULL,0,0};
   dispparam.rgvarg = new VARIANT[1];
   dispparam.cArgs = 1;

   VariantInit(dispparam.rgvarg);
   dispparam.rgvarg[0].vt = VT_BSTR;
   dispparam.rgvarg[0].bstrVal = SysAllocString(OLESTR("File=\"C:\\BASES\\80\\BASE\";Usr=\"Admin\"")); 

   pIV8COMConnector->Invoke(dispid,IID_NULL,LOCALE_SYSTEM_DEFAULT,DISPATCH_METHOD,&dispparam,NULL,NULL,NULL);

   pIV8COMConnector->Release();

   SysFreeString(dispparam.rgvarg[0].bstrVal);

   delete [] dispparam.rgvarg;
}
Владимир
Сообщения: 56
Зарегистрирован: 25 апр 2005, 13:57

abtat писал(а):Ну и для меня пока непонятно, как можно включать в текст С++ программ строки инструкций на языке 1С, которые не всегда соответствуют синтаксическим правилам С++ и должны использовать русские названия процедур, функций и свойств, заложенные в 1С.
Метод Connect() вторым параметром возвращает IDispatch* объекта COM -соединение и скорее всего через вызовы GetIDsOfNames() и Invoke() можно получить доступ к рускоязычным процедурам, функциям и свойствам.

Цитата из документации 1С:
"...В качестве своих методов COM-соединение может иметь:

- системные процедуры и функции;
- процедуры и функции модуля внешнего соединения и общих модулей, объявленные с ключевым словом Экспорт;
- дополнительный метод NewObject..."
cheerful
Сообщения: 2
Зарегистрирован: 05 окт 2007, 13:41

Кому надо, вот пример рабочего кода подключения и работы с v8:

Variant Ole1C=CreateOleObject("V81.Application"); //Подключение к версии 8.1
//Подключение к БД файлового варианта
AnsiString ConnectLine="File=C:\Progra~l\lcv8\Db\Trade; Озг=Иванов; Pwd=super";
//Подключение к БД клиент-серверного варианта
//AnsiString ConnectLine="Srvr=ServerlC; Ref=Trade; изг=Иванов; Pwd=super";
Ole1C.OleProcedure("Connect", ConnectLine.c_str());
Variant sprorg=Ole1C.OlePropertyGet("Справочники").OlePropertyGet("Организации");
Variant organization=sprorg.OleFunction("НайтиПоКоду","000000004");
Variant newdoc=Ole1C.OlePropertyGet("Документы").OlePropertyGet("ЗаказПокупателя").OleFunction("СоздатьДокумент");
ewdoc.OlePropertySet("Организация",organization);
newdoc.OlePropertySet("Дата",Now());
newdoc.OlePropertySet("ДатаОтгрузки",Date());
Ответить