You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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的接口规范,修正方案如下:

  1. StringBuilder初始化长度匹配读取长度:原代码初始化了长度为3000的StringBuilder,EHLLAPI只会填充前len个字符,剩余空间的未初始化内容会被当成字符串的一部分返回,产生垃圾值。
  2. 返回字符串截断处理:EHLLAPI返回的字符串末尾可能包含空字符、空格或控制字符,需要按实际返回的长度截断并过滤无效字符。
  3. 校验位置计数规则: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 10:27:02