C#使用EHLLAPI读取IBM iSeries模拟器字符串出现后缀垃圾字符
AS400模拟器EHLLAPI读取屏幕内容出现垃圾字符问题
问题场景
我正在尝试对AS400模拟器(IBM Personal Communications iSeries)中的流程做自动化,为此我使用了CodeProject的代码,通过EHLLAPI连接模拟器。
我创建了一个Winforms程序,添加了按钮和文本框来测试代码,以下是封装EHLLAPI方法的类:
public class EhllapiFunc //Class used to import the DLL. { [DllImport("PCSHLL32.dll")] public static extern UInt32 hllapi(out UInt32 Func, StringBuilder Data, out UInt32 Length, out UInt32 RetC); } class EhllapiWrapper { /*These are the constants used to as function codes that are sent as parameters to the function in the DLL. There are a lot more constants but these are the only ones used for the moment*/ const UInt32 HA_CONNECT_PS = 1; /* 000 Connect PS*/ const UInt32 HA_DISCONNECT_PS = 2; /* 000 Disconnect PS*/ const UInt32 HA_COPY_PS_TO_STR = 8; /* 000 Copy PS to String*/ /*EHLLAPI return codes. There are a lot more. I'll leave just some of them as I'm not getting any return codes in my issue*/ const UInt32 HARC_SUCCESS = 0; /* 000 Good return code.*/ const UInt32 HARC99_INVALID_INP = 0; /* 000 Incorrect input*/ const UInt32 HARC_INVALID_PS = 1; /* 000 Invalid PS, Not*/ const UInt32 HARC_BAD_PARM = 2; /* 000 Bad parameter, or*/ //Method to connect to the emulator. public static UInt32 Connect(string sessionID) { StringBuilder Data = new StringBuilder(4); Data.Append(sessionID); UInt32 rc = 0; UInt32 f = HA_CONNECT_PS; UInt32 l = 4; return EhllapiFunc.hllapi(out f, Data, out l, out rc); } //Method to disconnect. public static UInt32 Disconnect(string sessionID) { StringBuilder Data = new StringBuilder(4); Data.Append(sessionID); UInt32 rc = 0; UInt32 f = HA_DISCONNECT_PS; UInt32 l = 4; return EhllapiFunc.hllapi(out f, Data, out l, out rc); } /*This is the method where I'm having the problem.*/ public static UInt32 ReadScreen(int position, int len, out string txt) { StringBuilder Data = new StringBuilder(3000); UInt32 rc = (UInt32)position; UInt32 f = HA_COPY_PS_TO_STR; UInt32 l = (UInt32)len; UInt32 r = EhllapiFunc.hllapi(out f, Data, out l, out rc); txt = Data.ToString(); return r; } }
以下是窗体中调用该方法的点击事件:
private void bReadString_Click(object sender, EventArgs e) { //调用方法前先清空输出结果的文本框 tbReadOut.Text = ""; string s; //将表单输入的位置和字符串长度传入方法,ReadScreen方法会修改s的值 EhllapiWrapper.ReadScreen(Convert.ToInt32(tbReadPos.Text), Convert.ToInt32(tbReadLen.Text), out s); tbReadOut.Text = s; }
问题表现
试图从光标位置30处读取长度为2的字符串,预期返回内容为"Sy",但实际返回的结果中存在垃圾字符,问题时好时坏,在模拟器不同位置测试都可复现。目前获取光标位置、向模拟器发送字符串的功能都正常,仅读取字符串时出现异常。这段代码最初发布于2005年,暂无相关问题的公开解决思路。
解决方案
出现垃圾字符的核心原因是原ReadScreen方法的参数处理和字符串返回逻辑不符合EHLLAPI的接口规范,修正方案如下:
- StringBuilder初始化长度匹配读取长度:原代码初始化了长度为3000的StringBuilder,EHLLAPI只会填充前len个字符,剩余空间的未初始化内容会被当成字符串的一部分返回,产生垃圾值。
- 返回字符串截断处理:EHLLAPI返回的字符串末尾可能包含空字符、空格或控制字符,需要按实际返回的长度截断并过滤无效字符。
- 校验位置计数规则:EHLLAPI的屏幕位置是从1开始计数,若传入的position是从0开始计算的偏移量,会导致读取位置错位,产生异常内容。
修正后的ReadScreen方法代码如下:
/*修正后的读取屏幕方法*/ public static UInt32 ReadScreen(int position, int len, out string txt) { txt = string.Empty; // 初始化StringBuilder长度与要读取的长度严格一致 StringBuilder Data = new StringBuilder(len); UInt32 rc = (UInt32)position; UInt32 f = HA_COPY_PS_TO_STR; UInt32 l = (UInt32)len; UInt32 r = EhllapiFunc.hllapi(out f, Data, out l, out rc); // 仅返回成功状态下的有效内容 if (r == HARC_SUCCESS) { // 按实际返回长度截断,过滤末尾空字符和空白符 txt = Data.ToString().Substring(0, (int)l).TrimEnd('\0', ' '); } return r; }
附加优化建议:调用ReadScreen方法前可增加10~50ms的延时,确保模拟器页面渲染完成后再读取内容,避免加载过程中读取到无效内容。
内容的提问来源于stack exchange,提问作者ArminAH
相关产品推荐
相关产品推荐

