Работа с 1C Предприятие из Visual C++
Страница 2.




Есть несколько причин, по которым 1С может не быть запущен.
1) Вы пользуетесь локальной версией и в памяти уже висит какое то приложение с 1С Предприятием (в документации об этом сказано очень поверхностно – но поверьте на слово или сами поставьте эксперимент);

2) Произошла ошибка при компиляции глобального модуля (которая происходит каждый раз при запуске 1С), т.о. вам сначала желательно в конфигураторе поправить ошибки 1С Предприятия;

3) Произошло нарушение индексации таблиц из за некорректного завершения работы базы. Т.о. Вам сначала нужно запустить 1С Предприятие в монопольном режиме, что бы восстановить индексацию.
Кстати – в локальной версии тоже есть монопольный режим. Только вот зачем он нужен.. для меня загадка. Напомню, что командная строка для запуска в монопольном режиме должна заканчиваться /M.

теперь у нас есть запущенное приложение 1С Предприятия, можно к нему обращаться с помощью спецфункций: EvalExpr, CreateObject, ExecuteBatch, подробнее об этом – в официальном руководстве.

Экспортируемая функция глобального модуля, которую мы будем вызывать, будет называться ПриветМир, на языке 1С она выглядит следующим образом:

Функция ПриветМир (Слово) Экспорт
  ВозврСтрока = "Привет мир: " + Слово + "  спасибо за весточку в красно-желтую темницу!";   
  Возврат ВозврСтрока;
КонецФункции

У нас есть несколько способов вызвать эту функцию.

Вариант 1. Выполнить её с помощью функции EvalExpr, которая предназначена исполнения выражений на языке 1С (ExecuteBatch – тоже вариант).

Вариант 2. Взять ID непосредственно функции ПриветМир и вызвать сразу её. В 1С Предприятии нет никакой чёрной магии – она насквозь пропитана технологией OLE, поэтому у каждой функции есть ID. Тут я не уверен насчёт SQL версии, но использовать приведённый здесь код можно и с этой версией тоже.

Приступим!

1 Вариант.

VARIANT vRetEvalExpr;
UINT nArgErrRetEvalExpr;
DISPPARAMS argsRetEvalExpr = {0, 0, 0, 0};
VARIANT varsRetEvalExpr [1];  

///.......///

argsRetEvalExpr.cArgs = 1;
argsRetEvalExpr.rgvarg = varsRetEvalExpr;

BSTR                bstrEvalExpr      = L"EvalExpr";
DISPID              dispIDEvalExpr;
hr = pv77->GetIDsOfNames(IID_NULL, &bstrEvalExpr, 1, 0, &dispIDEvalExpr);    

if (FAILED(hr))
{
  AfxMessageBox("Невозможно получить ID от EvalExpr");
  if (pv77)
    pv77->Release();
  CoUninitialize();      
}

varsRetEvalExpr [0] = _variant_t("ПриветМир(\"Весточка 1С Предприятию\")");

/*
После этого Invoke можете проверить переменную vRetEvalExpr, 
в ней должна располагаться строка-ответ от 1С Предприятия.
*/
hr = pv77->Invoke(dispIDEvalExpr, IID_NULL, 0, DISPATCH_PROPERTYGET, 
  &argsRetEvalExpr, &vRetEvalExpr, NULL, NULL);

Способ с EvalExpr плох.. Почему? Потому что если бы в строке «Весточка 1С Предприятию» затесалась хотя бы одна кавычка, вызов произвести не удалось бы. Это накладывает определённые ограничения на наши действия. Поэтому, для серьёзных целей такой метод не подходит, к тому же – он не самый оптимальный по производительности, потому что сначала вызывается функция EvalExpr, которая потом вызывает функцию ПриветМир. «Чем больше посредников, тем больше в вине воды» (Copyright кто то из древних), поэтому мы не будем пользоваться функцией EvalExpr, а будем вызвать функцию ПриветМир непосредственно.

BSTR bstrHelloWorld      = L"ПриветМир";
DISPID dispIDHelloWorld;
hr = pv77->GetIDsOfNames(IID_NULL, &bstrHelloWorld, 1, 0, &dispIDHelloWorld);    

if (FAILED(hr))
{
  AfxMessageBox("Сначала добавьте в глобальный модуль фукнцию ПриветМир");
  if (pv77)
    pv77->Release();
  CoUninitialize();      
}

VARIANT vRetHelloWorld;
DISPPARAMS argsHelloWorld = {0, 0, 0, 0};
VARIANT varsHelloWorld[1];  

argsHelloWorld.cArgs = 1;
argsHelloWorld.rgvarg = varsHelloWorld;

varsK[0] = _variant_t("Привет в жёлто красную темницу");               

hr = pv77->Invoke(dispIDHelloWorld, IID_NULL, 0, DISPATCH_METHOD, &argsHelloWorld,
  &vRetHelloWorld, NULL, NULL);

Обратите внимание что при вызове Invoke используется DISPATCH_METHOD а не DISPATCH_PROPERTYGET.

Вот в общем то почти всё. Хочу добавить, что можно продвинуться и дальше – функция CreateObject() может создавать объекты (например, справочник товаров), при этом вы получаете IDispatch интерфейс, у которого есть все методы, которые Вы использовали в 1С для работы со справочником товаров. Их можно использовать, но думаю, что дойдя до этого места, Вы захотите написать какую ни будь удобную обёртку (может быть даже tlb-шку?) над всем этим, ибо вызывать каждый раз Invoke вручную уже не останется ни сил, ни терпения. Но это – тема другой статьи.
 
« Предыдущая статья   Следующая статья »