Имя: Пароль:
1C
1С v8
Проблема с обменом с 1С через COMConnector из MS Visual C++
0 ProxyDixis
 
02.03.17
14:44
Всем привет.

Пытаюсь из программы на MS Visual C++ подключится к базе 1С через COMConnector и получить версию конфигурации.

Ниже приведен код. Почему то после удачного соединения в базой,
не получается получить IDispatch на "Метаданные", чтобы потом получить свойство "Версия". Вызываю Invoke   для dispID "Метаданные" с флагом DISPATCH_PROPERTYGET. Invoke возвращает ошибку 0x80020008 которая означает "Один из аргументов метода не является допустимым типом variant". В чем может быть проблема? Где я ошибся?

Код:
// ProgramTest.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <objbase.h>
#include <comdef.h>
#include <iostream>


int _tmain(int argc, _TCHAR* argv[])
{
    int i;
    HRESULT hr = CoInitialize(NULL);
    if(FAILED(hr))
    {        
        return 0;
    }

    CLSID   cls80;

    hr = CLSIDFromProgID(L"V82.COMConnector", &cls80);
    if(FAILED(hr))
    {
        CoUninitialize();
        return 0;
    }

    IDispatch *pv80;
        
    hr = CoCreateInstance(cls80, NULL, CLSCTX_INPROC_SERVER, IID_IDispatch, (void**)&pv80);

    if(FAILED(hr)||!pv80)
    {
        CoUninitialize();
        return 0;
    }

    VARIANT    vRet;
    DISPPARAMS args = {0, 0, 0, 0};
    VARIANT vars[3];  

    args.cArgs = 1;
    args.rgvarg = vars;
    ZeroMemory(vars, sizeof(vars));

    std::locale::global(std::locale(""));    
    vars[0].vt = VT_BSTR;
    vars[0].bstrVal = OLESTR("File=\"D:\\Разработка\\По работе\\Конвертация\";");

    DISPID dispID;
    BSTR MethodName=L"Connect";
    hr = pv80->GetIDsOfNames(IID_NULL, &MethodName, 1, 0, &dispID);    
    
    if (FAILED(hr))
    {        
        if (pv80) pv80->Release();
        CoUninitialize();
        return 0;
    }
    
    EXCEPINFO exs;


    //соединимся с информационной базой
    hr = pv80->Invoke(dispID, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD,&args, &vRet, &exs, NULL);
    
    if (FAILED(hr))
    {        
        if (pv80) pv80->Release();
        CoUninitialize();
        return 0;
    }

    if(vRet.vt!=VT_DISPATCH)
    {
        if (pv80) pv80->Release();
        CoUninitialize();
        return 0;
    }

    /////ВСЕ ОК, СОЕДИНИЛИСЬ/////
    std::cout<<"Соединилсь с базой успешно"<<std::endl;
    IDispatch *connector=vRet.pdispVal;        
    
    //хотим получить версию конфигурации
    //в 1С  это далется так: Метаданные.Версия
    //если попробовать из однй базы 1С подключится через COMConnector к другой базе 1С вот таким кодом:
    ////V8 = Новый COMObject ("V82.COMConnector");
    ////
    ////Соединение = V8.Connect ("File=""D:\Разработка\По работе\Конвертация"";");
    ////Сообщить(Соединение.Метаданные.Версия);
    //то все получается.
    //теперь попробуем здесь сделать также


    VARIANT    vRetMeta;
    DISPPARAMS argsMeta = {0, 0, 0, 0};    //параметров никаких нет, это же получение свойства
    
    MethodName=L"Метаданные";
    hr = connector->GetIDsOfNames(IID_NULL,&MethodName, 1, 0, &dispID);    
    
    if (FAILED(hr))
    {        
        if (connector) connector->Release();
        if (pv80) pv80->Release();
        CoUninitialize();
        return 0;
    }
    
    //получить IDispatch на метаданные
    hr = connector->Invoke(dispID, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET,&argsMeta, &vRetMeta, &exs, NULL);
    
    if (FAILED(hr))
    {        
        //попадаем сюда, с ошибкой
        if (hr==DISP_E_BADVARTYPE)
        {
            std::cout<<"Что-то не так с DISPPARAMS"<<std::endl;            
        }
        else {
            char ch[20];
            itoa(hr,ch,16);
            std::cout<<"Ошибка с кодом"<<ch<<std::endl;
        }

        std::cin>>i;

        if (connector) connector->Release();
        if (pv80) pv80->Release();
        CoUninitialize();
        return 0;
    }

    if(vRetMeta.vt!=VT_DISPATCH)
    {
        if (connector) connector->Release();
        if (pv80) pv80->Release();
        CoUninitialize();
        return 0;
    }

    
    std::cout<<"отлично, есть IDispatch на метаданные, можно дальше получать версию"<<std::endl;
    std::cin>>i;

    return 0;
}
1 ProxyDixis
 
02.03.17
17:09
ап
2 ProxyDixis
 
03.03.17
09:04
ап
3 Кирпич
 
03.03.17
10:15
(0) автор, ты конечно мазохист и меня втянул еще. так работает:

VARIANT    vRetMeta; vRetMeta.vt = 0;
DISPPARAMS argsMeta = { NULL, NULL, 0, 0 };
4 ProxyDixis
 
03.03.17
10:33
(3) DISPPARAMS argsMeta = { 0, 0, 0, 0 } не стал менять на DISPPARAMS argsMeta = { NULL, NULL, 0, 0 }, а вот добавление
vRetMeta.vt = 0 решило проблему. Спасибо большое. Почему об этом нигде не написано, или написано просто я не там смотрю:-) Почему мазохист?
5 Кирпич
 
03.03.17
10:41
(4) "Почему мазохист?" ну как бы писать целую страницу кода чтобы вызвать два метода. отвык я уже от такого.

vRetMeta.vt = 0

ну как бы инициализируем VARIANT
1c наверное пытается сначала обнулить VARIANT и сначала выяснить нет ли там строки или массива или еще чего такого, что нужно дестроить, а там мусор. Нолик подставили, значит пустой VARIANT и ничо дестроить не надо.
6 ProxyDixis
 
03.03.17
10:43
(5) Век живи, век учись. А код на самом деле не такой, это я для форума написал, так-то все в класс завернуто. Спасибо большое.
7 Serginio1
 
03.03.17
10:44
(4) >> Почему мазохист
Вообще С++ ники для этого используют питон и не парятся.
8 Кирпич
 
03.03.17
10:46
(7) питон используют питонники
9 Serginio1
 
03.03.17
12:05
(8) Ошибаешься. С++ ники активно используют питон для обширного круга задач.
https://www.ibm.com/developerworks/ru/library/l-python_details_07/
10 Кирпич
 
03.03.17
12:07
(9) да нет. то ек С++ ники, то питонники, которые используют С++
11 Serginio1
 
03.03.17
12:07
12 Вафель
 
03.03.17
12:08
(11) что только подтверждает (10)
13 Serginio1
 
03.03.17
12:08
(10) Я общаюсь на http://rsdn.org/ там достаточно крутые С++ ники и они все испоьзуют питон
14 Serginio1
 
03.03.17
12:10
Мало того, сейчас питон используется и для сборок С++ го кода https://github.com/python-cmake-buildsystem/python-cmake-buildsystem
15 Кирпич
 
03.03.17
12:17
(14) ты всё врешь. С++ ники не используют питон, потому что они используют ассемблер
16 Кирпич
 
03.03.17
12:18
+(15) вот доказательство https://habrahabr.ru/post/252647/
17 lock19
 
03.03.17
12:29
(14) Существуют несколько нативнопитонных систем сборки, несвязанных с cmake.
Вообще, проще сказать кто не использует питон чем наоборот.
18 lock19
 
03.03.17
13:04
(13) и nullptr
19 Serginio1
 
03.03.17
15:10
(18) Я конечно только начинающий, но тоже предпочитаю nullptr
20 lock19
 
03.03.17
15:55
(19) А ведь закоренелые сишники по сей момент считают это вопросом косметики.