微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

delphi – 协调错误:有没有人遇到截断错误消息的问题?

在这里再次向你寻求帮助.这次我相信,鉴于我将要涉及的问题的特殊性,很少有人会作出回应.我开始在DataSnap的世界里,仍然有一些我不明白我将如何关联这个错误的事情.

我的Delphi是XE(版本1,Update1).我正在使用Postgres生成葡萄牙语(葡萄牙语巴西)的错误消息,因此错误消息有重音符号.连接组件是zeosLib包.

我正在使用一个对话框“reconcile error”来显示更新应用程序产生的错误并进行测试,我试图插入已经存在的记录,从而违反了一个唯一的密钥,从而显示了协调错误对话框.

在对话框的备忘录中,出现的消息被截断,即剪切.看看这个:

ERRO:  duplicar valor da chave viola a restrição de unicidade "uc_usu_va_login"
DETAIL:  Chave (va_login)=(admin) já existe.
CONTEXT:  comando sql "INSERT INTO USUARIOS (VA_NOME,VA_LOGIN,CH

但实际应该返回的是:

ERRO:  duplicar valor da chave viola a restrição de unicidade "uc_usu_va_login"
DETAIL:  Chave (va_login)=(admin) já existe.
CONTEXT:  comando sql "INSERT INTO USUARIOS (VA_NOME,CH_SENHA,VA_EMAIL)
                        VALUES (pVA_NOME,pVA_LOGIN,pCH_SENHA,pVA_EMAIL)"
    PL/pgsql function "idu_usuarios" line 7 at comando sql

我在服务器上做了一个调试,看看问题是否是zeosLib,但我发现服务器上生成错误消息已经完成,证明zeosLib没有截断消息.一切都是unicode.我的程序和zeosLib中的所有字符串都是WideString(认值).

如你所知,要抛出服务器,异常会被DataSnap转发给客户端,在客户端,TClientDataSet的Reconcile方法验证是否存在问题,然后抛出可能出现的着名异常EReconcileError.在TClientDataSet的OnReconcileError事件中处理,因此我认为该消息被DataSnap截断.

在客户端我调试Reconcile方法(DBClient.pas),并在抛出异常之前,流进入cpp源代码中的函数,我认为这是库midas.dll,MidasLib.obj的一部分更具体,因为我是使用此策略,不必使用我的应用程序分发DLL.

Check(FDSBase.Reconcile_MD(FReconcileDataSet.FDSBase,FDeltaPacket,VarToDataPacket(Results),Integer(Self),RCB));

调用在Delphi XE Update1上的单元DBClient.pas的第1952行完成.按F7,调试器进入源C(cpp),所以我相信它在midaslib.obj中.我怎么不理解C,我按Shift-F8退出当前方法并返回下一条指令,即已经在事件OnReconcileError !!因此,截断必须在我提到的函数内,在一个cpp源中,在midaslib内完成.

我的目的是使Reconcile Error对话框不仅是最终用户的工具,而且是支持个人的工具,提供错误,详细信息和上下文的单独信息.这有助于发现问题.

现在的问题是使消息完整显示.消息被midas截断有没有人遇到过这种问题?

另外一点DSClient.pas我可以在传递给异常时提取错误消息:

'Erro sql: ERRO:  duplicar valor da chave viola a restrição de unicidade "uc_usu_va_login"'#$A'DETAIL:  Chave (va_login)=(admin) já existe.'#$A'CONTEXT:  comando sql "INSERT INTO USUARIOS (VA_NOME'#$A',VA_LOGIN'#$A',CH'

如果删除引号并用空格(一个字符)替换#$A(1个字符),您将看到该字符串正好有255个字符!

我还发现dspickle.cpp中的“GetErrorString”使用常量DBIMAxmsGLEN,它在bdetypes.h中定义为127(255的一半).由于我们处于Unicode的世界中,为了每个字符有两个字节,将这个值增加到255不是一个问题吗?这只是猜测……

我把问题留在空中,因为我缺乏理解C的知识:)谁能提供帮助,只需看看dspickle.cpp中的函数实现“GetErrorString”.这有:

LoadString((HINSTANCE)hDll,iErrCode,pString,DBIMAxmsGLEN)

pString是错误消息,DBIMAxmsGLEN = 127.

解决方法

与其他人的意见相矛盾我决定进一步调整,最后想出如何增加“Reconcile”错误消息中的字符数.我认为问题出在midas.dll,或者更具体地说是构成midas dll的源代码,因为同一组源可以创建MidasLib,这不需要midas dll.为了解决我不得不安装Delphi C个性来编译midas.

找到错误的一行之后,我发现甚至有一个QC(http://qc.embarcadero.com/wc/qcmain.aspx?d=84960)修理请求似乎被Embarcadero的工作人员忽略了,因为“决议”就是“推迟到Next Rel” (推迟到下一个版本),但请求是从2010年开始,我正在使用Delphi XE,在我看来应该有解决方案,但在这里我自己纠正;)

问题出在“DSBASE”类的方法“Clone”内,在第2133行(Delphi XE,Update1)的源“ds.cpp”内.下面是代码块.红线是有问题的线:

// Set the third field for the error string.
LdStrcpy((pCHAR)pFldDes->szName,szdsERRMESSAGE);
pFldDes->iFldType = fldZSTRING;
pFldDes->iUnits1 = 255; // Increased on request.. DBIMAxmsGLEN;
pFldDes++;

请注意问题行非常有趣.它的常量值为255,它限制了错误消息的大小和注释“根据请求增加”.还要注意,在注释旁边有一个常量DBIMAxmsGLEN,我已经找到并且已经怀疑它是否对该问题负责,但由于它没有被使用,我改变了DBIMAxmsGLEN的值但是错误消息总是没有变化.值得一提的是,在DBIMAxmsGLEN之后有一个分号(;)让我认为之前(我不知道什么时候)这行是我修复后的那一行:

pFldDes->iUnits1 = DBIMAxmsGLEN;

就好像有人故意将字段值设置为255,删除了之前真正动态且看似更正确的实现.在执行替换行之后,我将DBIMAxmsGLEN的值增加到1024.将DBIMAxmsGLEN声明为“bdetypes.h”作为定义.纠正线后像这样:

#define DBIMAxmsGLEN         1024           // Max message len

在“ds.cpp”和“bdetypes.h”中进行了这两个更改后,我构建,测试,结果与预期一致:错误消息在Reconcile对话框中完整显示.

对于想要尝试的勇敢者,如果他们已经看到了这个问题,你需要MIDAS的来源,如果我没记错的话,它将从2010年开始附带Delphi.祝你们好运.

原文地址:https://www.jb51.cc/delphi/101811.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐