Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > С/С++: Кроссплатформенное программирование, Qt/Gtk+/wxWidgets > Qt определение вывода ошибок в определенной кодиро


Автор: KUL 24.7.2013, 03:07
Здравствуйте.
Имеются исходники в формате utf-8
Код

QAxObject * ax = new QAxObject("V82.COMConnector");
QAxObject * ac = ax->querySubObject("Connect(\"Srvr=\"172.0.0.100\";Ref=\"base1\";Usr=\"1C-Bot\";Pwd=\"56q\";\")");
QAxObject * ab = ac->querySubObject("NewObject",QObject::tr("Справочники.Контрагенты"));

 

При выполнении имеется сообщение об ошибке
Код

QAxBase: Error calling IDispatch member NewObject: Exception thrown by server
             Code       : 1001
             Source     : 1C:Enterprise 8.2.15.319
             Description: ??? ?? ????????? '???????????.???????????'
             Help       :
         Connect to the exception(int,QString,QString,QString) signal to catch t
his exception


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

Автор: Guinness 24.7.2013, 07:11
1). Попробуйте trUtf8.
2). Куда выводится сообщение? Если в консоль, то нужно настроить саму консоль на кодировку utf8, либо конвертировать строки в необходимую кодировку с помощью QTextCodec.

Автор: KUL 24.7.2013, 13:00
Guinness, пробовал, не получилось. Да, в консоль вывожу.

1 Эксперимент

Код

Кодировка main.cpp ANSI (cp1251)
#include <QApplication>
#include <QWidget>
#include <oleidl.h>
#include <ActiveQt/QAxObject>
#include <QAxBase>
#include <iostream>
#include <QDebug>
#include <QTextCodec>
#include <QString>
 
 
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    ::OleInitialize(0);
    setlocale(LC_ALL, "Russian");
    std::cout << QTextCodec::codecForName("CP1251") << " если значение есть, значит кодировка есть\n";
    QTextCodec* codec = QTextCodec::codecForName("CP1251");
    QTextCodec::setCodecForLocale(codec);
    std::cout << "текст\n";
    qDebug() << "текст2";
    QAxObject * ax = new QAxObject("V82.COMConnector");
    QAxObject * ac = ax->querySubObject("Connect(\"Srvr=\"172.0.0.100\";Ref=\"base1\";Usr=\"1C-Bot\";Pwd=\"56q\";\")");
    QAxObject * ab = ac->querySubObject("NewObject",QObject::tr("Справочники"));
    std::cout << "text";
    return a.exec();
}
 


Результат
Код


0x1240e390 если значение есть, значит кодировка есть
текст
?????2
QAxBase: Error calling IDispatch member NewObject: Exception thrown by server
             Code       : 1001
             Source     : 1C:Enterprise 8.2.15.319
             Description: ??? ?? ????????? '???????????'
             Help       :
         Connect to the exception(int,QString,QString,QString) signal to catch t
his exception
text

 

2 Эксперимент
Кодировка main.cpp utf-8

Код

#include <QApplication>
#include <QWidget>
#include <oleidl.h>
#include <ActiveQt/QAxObject>
#include <QAxBase>
#include <iostream>
#include <QDebug>
#include <QTextCodec>
#include <QString>
 
 
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    ::OleInitialize(0);
    setlocale(LC_ALL, "Russian");
    //std::cout << QTextCodec::codecForName("UTF-8") << " если значение есть, значит кодировка есть\n";
    //QTextCodec* codec = QTextCodec::codecForName("UTF-8");
    //QTextCodec::setCodecForLocale(codec);
    std::cout << "текст\n";
    qDebug() << "текст2";
    QAxObject * ax = new QAxObject("V82.COMConnector");
    QAxObject * ac = ax->querySubObject("Connect(\"Srvr=\"172.0.0.100\";Ref=\"base1\";Usr=\"1C-Bot\";Pwd=\"56q\";\")");
    QAxObject * ab = ac->querySubObject("NewObject",QObject::tr("Справочники"));
    std::cout << "text";
    return a.exec();
 


Результат
Код


С'РчРєС?С'
текст2
QAxBase: Error calling IDispatch member NewObject: Exception thrown by server
             Code       : 1001
             Source     : 1C:Enterprise 8.2.15.319
             Description: ??? ?? ????????? '???????????'
             Help       :
         Connect to the exception(int,QString,QString,QString) signal to catch t
his exception
text

 

Вывод - то ли дебагу Qt 5 плевать на глабольные настройки кодировки, то ли QAxBase классу ... Пробежался по докам QAxBase, ничего про кодировку отладочных сообщений не увидел  smile 

Автор: Guinness 24.7.2013, 13:20
Так а 1С Вам в какой кодировке присылает данные?
Я сначал не вдуплил в вопрос. В своё время, когда я писал smtp-клиент, если открывать поток(сокет), с кодировкой, несоответствующей передаваемому тексту, будут выдаваться вот такие знаки вопросов. И ничего Вы с ними не сделаете.
Соответственно, нужно открывать поток в кодировке, которой Вам передает 1С.

Автор: KUL 24.7.2013, 15:36
Но это же не поток, это же получается просто как использование api дллэлки, которая просто указатель отдаёт. Хотя ...
Если честно с 1С совсем не работал, если подскажите как посмотреть это в 1С, будет круто  smile 

Автор: Guinness 25.7.2013, 07:34
Цитата(KUL @  24.7.2013,  16:36 Найти цитируемый пост)
Но это же не поток, это же получается просто как использование api дллэлки, которая просто указатель отдаёт. Хотя ...

Так, давайте по порядку. Что и как Вы делаете? Ошибка происходит при попытке создать нового пользователя? Где обрабатывается ошибка? Как происходит её вывод?

Цитата(KUL @  24.7.2013,  16:36 Найти цитируемый пост)
Если честно с 1С совсем не работал, если подскажите как посмотреть это в 1С, будет круто  

Я тоже, поэтому помочь Вам не смогу с этим. Однако, Вы можете поинтересоваться у человека, который настраивал сервер, в какой кодировке хранятся данные на нём и вообще какие кодировки он использует. В MySQL, к примеру, есть разные виды кодировок для таблиц, БД, соединений с БД, консоли и т.п.
Это все можно узнать экспериментальным путём, спомощью перебора кодировок, но это если не лень. Попробуйте сделать это таким образом:


Код

QTextCodecs can be used as follows to convert some locally encoded string to Unicode. Suppose you have some string encoded in Russian KOI8-R encoding, and want to convert it to Unicode. The simple way to do it is like this:

QByteArray encodedString = "...";
QTextCodec *codec = QTextCodec::codecForName("KOI8-R");
QString string = codec->toUnicode(encodedString);


After this, string holds the text converted to Unicode. Converting a string from Unicode to the local encoding is just as easy:

QString string = "...";
QTextCodec *codec = QTextCodec::codecForName("KOI8-R");
QByteArray encodedString = codec->fromUnicode(string);


Автор: KUL 31.7.2013, 07:16
Решил поставить qt 4.8 для старых функций класса QTextCodec, поставил, делаю

main.cpp в кодировке UTF-8
Код

#include <QApplication>
#include <oleauto.h>
#include <ActiveQt/QAxObject>
#include <QAxBase>
#include <QDebug>
#include <QTextCodec>
#include <QString>
#include <QByteArray>


int main(int argc, char *argv[])
{

    QCoreApplication a(argc, argv);
    ::OleInitialize(0);

    setlocale(LC_ALL, "Russian");
    QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));

    qDebug() << "текст2";
    QAxObject * ax = new QAxObject("V82.COMConnector");
    QAxObject * ac = ax->querySubObject("Connect(\"Srvr=\"172.0.0.100\";Ref=\"base1\";Usr=\"1C-Bot\";Pwd=\"56q\";\")");

    QAxObject * ab = ac->querySubObject("ПользователиИнформационнойБазы");

    delete ax;

    qDebug() << "end";
    return a.exec();
}


Реузьтат
Код

текст2
QAxBase::dynamicCallHelper: ПользователиИнформационнойБазы: No such property in
 [unknown]
        Candidates are:
end


Вычитал, что 1С сервер через COM принимает кодировкой CP1251 а результат возвращает UTF-8.

Делаю
main.cpp в кодировке UTF-8
Код

#include <QApplication>
#include <oleauto.h>
#include <ActiveQt/QAxObject>
#include <QAxBase>
#include <QDebug>
#include <QTextCodec>
#include <QString>
#include <QByteArray>


int main(int argc, char *argv[])
{

    QCoreApplication a(argc, argv);
    ::OleInitialize(0);

    setlocale(LC_ALL, "Russian");
    QTextCodec::setCodecForTr(QTextCodec::codecForName("Windows-1251"));
    QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));

    qDebug() << "текст2";
    QAxObject * ax = new QAxObject("V82.COMConnector");
    QAxObject * ac = ax->querySubObject("Connect(\"Srvr=\"172.0.0.100\";Ref=\"base1\";Usr=\"1C-Bot\";Pwd=\"56q\";\")");

    QAxObject * ab = ac->querySubObject(QAxObject::tr("ПользователиИнформационнойБазы").toAscii());

    delete ax;

    qDebug() << "end";
    return a.exec();
}


Результат:
Код

текст2
QAxBase::dynamicCallHelper: Р?Р?Р>С?Р·Р?Р?Р°С'РчР>РёР?Р?С"Р?С?Р?Р°С┼РёР?Р?Р?Р?Р№
Р'азС<: No such property in  [unknown]
        Candidates are:
end


Почему так происходит?

зы В 1С есть к русским именам аналоги на английском, т.е. вместо ПользователиИнформационнойБазы можно написать InfoBaseUsers и всё отлично получится даже в первом варианте. НО!!! Люди которые писали конфигуратор, использовали для обозначения объектов только русские имена ... Поэтому в дальнейшем я например не смогу взять и посмотреть права пользователя (специфичные для нашего конфигуратора).

Автор: bsa 31.7.2013, 09:57
Цитата
main.cpp в кодировке UTF-8
...
QTextCodec::setCodecForTr(QTextCodec::codecForName("Windows-1251"))
...
QAxObject::tr("ПользователиИнформационнойБазы")

Тут ошибка. tr ты передаешь строку в utf8. А ждет она cp1251.
Убери setCodecForTr вообще. И делай так:
Код
QByteArray toCp1251(const char *data)
{
   return QTextCodec::codecForName("Windows-1251")->fromUnicode(QString::fromUtf8(data));
}

...

   QAxObject * ab = ac->querySubObject(toCp1251("ПользователиИнформационнойБазы").data());
...


А разработчикам 1C надо яйца оторвать за использование кириллицы в синтаксисе языка и названиях полей БД

Автор: KUL 1.8.2013, 06:53
bsa, сделал по вашей рекомендации:

main.cpp utb-8 без BOM
Код

#include <QApplication>
#include <oleauto.h>
#include <ActiveQt/QAxObject>
#include <QAxBase>
#include <QDebug>
#include <QTextCodec>
#include <QString>
#include <QByteArray>

QByteArray toCp1251(const char *data)
{
   return QTextCodec::codecForName("Windows-1251")->fromUnicode(QString::fromUtf8(data));
}

int main(int argc, char *argv[])
{

    QCoreApplication a(argc, argv);
    ::OleInitialize(0);

    setlocale(LC_ALL, "Russian");

    QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));

    qDebug() << "текст2";
    QAxObject * ax = new QAxObject("V82.COMConnector");
    QAxObject * ac = ax->querySubObject("Connect(\"Srvr=\"172.0.0.100\";Ref=\"base1\";Usr=\"1C-Bot\";Pwd=\"56q\";\")");

    QAxObject * ab = ac->querySubObject(toCp1251("ПользователиИнформационнойБазы").data());

    delete ax;

    qDebug() << "end";
    return a.exec();
}


Результат
Код

текст2
QAxBase::dynamicCallHelper: ??????????????????????????????: No such property in
 [unknown]
        Candidates are:
end

Автор: bsa 1.8.2013, 11:19
KUL, есть подозрение, что ты что-то не до конца настроил при подключении.

Автор: KUL 9.8.2013, 07:45
bsa насчёт кодировки кончено интересно. Вот какие примерно мысли посетили:

Исходники в utf-8, qt4.8
Код

    setlocale(LC_ALL, "Russian");
    QTextCodec *wincodec = QTextCodec::codecForName("UTF-8");
    QTextCodec::setCodecForTr(wincodec);

    QString str2 = "ПользователиИнформационнойБазы";
    qDebug() << str2; //тут выходят кракозябры
    QString str3 = QObject::tr(str2.toAscii().data());
    qDebug() << str3; //текст как надо!

//как перегнать стринг str3 в char* чтобы потом его отдать в ac->querySubObject() ???
    char * am = new char[30];
    

Как можно корректно (да даже хоть по символьно!) перегнать кустринг в чар? Так str3[0] не получится, т.к. QChar получается. А str3[0].toAscii().data() получается каша из кракозябр ...

Автор: bsa 9.8.2013, 12:25
KUL, это делается через TextCodec. Я ранее показал уже как.

И не используй tr() тут. Она тебе не нужна! Используй QString::fromUtf8() для получения QString, а затем QTextCodec для преобразования в cp1251 (windows-1251).
А еще лучше сделай специальный файл, в котором будешь хранить все эти поля. Загружай его в карту (std::map<int,std::string>) и пользуйся.

Автор: KUL 13.8.2013, 04:49
Всё перепробовал, уже как только не извращался, не хочет Qt русский текст понимать. Точнее ActiveQT модуль и его компоненты ...

На Visual Basic 2010 вообще всё чудесно работает
Код

Module Module1

    Sub Main()
        Dim cntr As Object
        Dim trade As Object
        Dim allusers As Object
        Dim users As Object

        Dim line As String

        cntr = CreateObject("V82.COMConnector")
        trade = cntr.Connect("Srvr=""172.0.0.100"";Ref=""base1"";Usr=""1C-Bot"";Pwd=""56q"";")
        allusers = trade.ПользователиИнформационнойБазы
        users = allusers.НайтиПоИмени("admin")
        Console.WriteLine(users.Имя)
        Console.WriteLine(users.АутентификацияОС)

        Console.WriteLine("end")

        line = Console.ReadLine()

    End Sub

End Module


Прям вот хоть бери и учи этот закрытопроприетарнодотнетовский VisualBasic ;( ...

Автор: bsa 14.8.2013, 11:48
KUL, посмотри в коде программы (скомпилированной), в какой кодировке там строки. Посмотри в отладке, правильные ли данные генерит toCp1251. Еще попробуй все эти русские строки записать в файл, а при старте программы читать в переменные (QByteArray) и используй при необходимости.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)