在 C# 中编程 IBM iSeries API QUSLSPL
本文关键字:iSeries API QUSLSPL IBM 编程 | 更新日期: 2023-09-27 18:03:04
有人可以帮助我使用完整的 c# 代码来调用 QUSLSPL SPLF0200格式吗?我可以调用该程序,但不知道如何捕获/读取输出。我是这个领域的新手。感谢您的帮助。
这是我的代码。
cwbx.ProgramParameters parameters = new cwbx.ProgramParameters();
//user space name
parameters.Append("usrspcnam", cwbrcParameterTypeEnum.cwbrcInout, 20);
StringConverter stringConverterUsrSpaceNm = new cwbx.StringConverter();
stringConverterUsrSpaceNm.Length = 20;
parameters["usrspcnam"].Value = stringConverterUsrSpaceNm.ToBytes("HRAHMAN QGPL ");
//Format
parameters.Append("frmname", cwbrcParameterTypeEnum.cwbrcInout, 8);
StringConverter stringConverterFrmname = new cwbx.StringConverter();
stringConverterFrmname.Length = 8;
parameters["frmname"].Value = stringConverterFrmname.ToBytes("SPLF0200");
//User Name
parameters.Append("usrnam", cwbrcParameterTypeEnum.cwbrcInout, 10);
StringConverter stringConverterUsrnam = new cwbx.StringConverter();
stringConverterUsrnam.Length = 10;
//parameters["usrnam"].Value = stringConverterUsrnam.ToBytes("*CURRENT");
parameters["usrnam"].Value = stringConverterUsrnam.ToBytes(" ");
//qualified output queue
parameters.Append("cola", cwbrcParameterTypeEnum.cwbrcInout, 20);
StringConverter stringConverterCola = new cwbx.StringConverter();
stringConverterCola.Length = 20;
//parameters["cola"].Value = stringConverterCola.ToBytes("*ALL");
parameters["cola"].Value = stringConverterCola.ToBytes(" ");
//form type
parameters.Append("frmtyp", cwbrcParameterTypeEnum.cwbrcInout, 10);
StringConverter stringConverterFrmtyp = new cwbx.StringConverter();
stringConverterFrmtyp.Length = 10;
//parameters["frmtyp"].Value = stringConverterFrmtyp.ToBytes("*ALL");
parameters["frmtyp"].Value = stringConverterFrmtyp.ToBytes(" ");
//user-specific data
parameters.Append("usrdta", cwbrcParameterTypeEnum.cwbrcInout, 10);
StringConverter stringConverterUsrdta = new cwbx.StringConverter();
stringConverterUsrdta.Length = 10;
//parameters["usrdta"].Value = stringConverterUsrdta.ToBytes("*ALL");
parameters["usrdta"].Value = stringConverterUsrdta.ToBytes(" ");
//error
parameters.Append("error", cwbrcParameterTypeEnum.cwbrcInout, 116);
Structure sc2 = new Structure();
sc2.Fields.Append("bytesprov", 4);
sc2.Fields.Append("bytesavail", 4);
sc2.Fields.Append("messageid", 7);
sc2.Fields.Append("err", 1);
sc2.Fields.Append("messagedta", 100);
parameters["error"].Value = sc2.Bytes;
//qualified job name
parameters.Append("qualifiedjobnm", cwbrcParameterTypeEnum.cwbrcInput, 26);
StringConverter stringConverterUsrdta1 = new cwbx.StringConverter();
stringConverterUsrdta1.Length = 26;
parameters["qualifiedjobnm"].Value = stringConverterUsrdta1.ToBytes("* ");
//keys
parameters.Append("keys", cwbrcParameterTypeEnum.cwbrcInput, 44); //44 is 11 keys times 4 bytes per key
LongConverter lc = new cwbx.LongConverter();
Structure keys = new Structure();
keys.Fields.Append("Spooledfilename", 4); //char10 201
keys.Fields["Spooledfilename"].Value = lc.ToBytes(201);
keys.Fields.Append("Username", 4); //char10 203
keys.Fields["Username"].Value = lc.ToBytes(203);
keys.Fields.Append("opqueue", 4); //206
keys.Fields["opqueue"].Value = lc.ToBytes(206);
keys.Fields.Append("userdata", 4); //209
keys.Fields["userdata"].Value = lc.ToBytes(209);
keys.Fields.Append("status", 4); //210
keys.Fields["status"].Value = lc.ToBytes(210);
keys.Fields.Append("totpages", 4); //bin 211
keys.Fields["totpages"].Value = lc.ToBytes(211);
keys.Fields.Append("copies", 4); //bin 213
keys.Fields["copies"].Value = lc.ToBytes(213);
keys.Fields.Append("openeddate", 4); //216
keys.Fields["openeddate"].Value = lc.ToBytes(216);
keys.Fields.Append("opentime", 4); //217
keys.Fields["opentime"].Value = lc.ToBytes(217);
keys.Fields.Append("jobid", 4); //218
keys.Fields["jobid"].Value = lc.ToBytes(218);
keys.Fields.Append("fileid", 4); //219
keys.Fields["fileid"].Value = lc.ToBytes(219);
parameters["keys"].Value = keys.Bytes;
//number of keys to return
parameters.Append("numberoffields", cwbrcParameterTypeEnum.cwbrcInput, 4);
LongConverter LongConverterKeys = new cwbx.LongConverter();
parameters["numberoffields"].Value = LongConverterKeys.ToBytes(11); //11 keys in total
program.Invoke(true, ref parameters);
现在接下来呢?在哪里以及如何读取输出?感谢您的回复。
你选择了一个 API 的哼哼声来开始。 您有一个具有全键列表格式的用户空间列表 API。 这些都是复杂的。 我会尽力解释这一切。 系好安全带!
QUSLSPL API 不返回除错误结构中的内容之外的任何内容。 其他所有内容都是输入参数。 要访问 API 生成的假脱机文件列表,您必须访问用户空间对象。 在您的示例中,用户空间是 QGPL/HRAHMAN。 在我开始检查用户空间的输出之前,让我们了解如何使用用户空间。
什么是用户空间?
用户空间只是存储在主机系统上的库中的一大块旧字节,最大大小为 16,776,704 字节。 您可以将它们用于不仅仅是列表 API 结果,但这就是我真正使用它们的全部目的。 需要用户空间的列表 API 的步骤如下:
- 创建用户空间。
- 调用 API。
- 检查 API 中的错误。
- 查找每个条目的大小。
- 找到列表数据的开头。
- 循环访问用户空间中的条目。
- 删除用户空间。
创建用户空间
创建用户空间是通过创建用户空间(QUSCRTUS(API完成的。 这个 API 非常简单。 您可以向它传递用户空间的限定名称、一些初始值和 API 错误结构(以便您可以处理出现的问题(。 可以在此处找到 API 定义:http://www.ibm.com/support/knowledgecenter/ssw_ibm_i_71/apis/quscrtus.htm
参数为:
- 完全限定名(字符[20](
- 扩展属性(字符[10](
- 初始大小(二进制[4](
- 初始值(字符[1](
- 公共权力(字符[10](
- 文本描述(字符[50](
- 替换(字符[10](
- API 错误结构
从用户空间检索数据
调用 QUSLSPL API 后,您需要从用户空间中检索数据。 为此,您可以使用QUSRTVUS API。 此 API 采用用户空间名称、起始位置、长度、接收方变量和 API 错误结构。 API 定义如下:http://www.ibm.com/support/knowledgecenter/ssw_ibm_i_71/apis/qusrtvus.htm
参数为:
- 完全限定名(字符[20](
- 起始位置(二进制[4]( 注意:这是从 1 开始的,而不是从零开始的。
- 要返回的数据长度(二进制[4](
- 接收器变量 (*(
- API 错误结构
删除用户空间
完成后,使用 QUSDLTUS API 删除用户空间。 这个更容易,它采用完全限定的名称和 API 错误结构。API 定义可在此处找到:http://www.ibm.com/support/knowledgecenter/ssw_ibm_i_71/apis/qusdltus.htm
列出用户空间中的 API 结构
列表 API 以特定格式将数据返回到用户空间。 它看起来像这样:
- 用户区域
- 泛型标头
- 输入参数部分
- 页眉节
- 列表数据部分
就读取列表 API 而言,真正重要的是用户空间前面的以下值,在该通用标头中。 请注意,这些位置从零开始。
- 位置 0x7c:偏移到列表数据部分
- 排名0x84:列表条目数
- 排名0x88:每个条目的大小
使用此信息,您可以分块读取用户空间。 每个块从 offset+(当前从零开始的条目编号 * 每个条目的大小(开始,并按条目大小的长度运行。
查看 QUSLSPL 的结果
从 QUSLSPL 返回的格式SPLF0200列表中的每个条目都包含两个部分。 前 4 个字节保存返回的字段计数。 然后,它为每个字段重复字段数据结构。 字段数据结构的大小是可变的。 您必须为每个字段遍历它,查看字段键,并使用该键确定返回了哪个值。 最终结果是一个两级循环。外部循环循环遍历每个假脱机文件条目。 内部循环循环遍历以SPLF0200格式返回的每个字段。
下面是一些基于您原始问题的示例代码。 一些注意事项,首先:
- 我没有围绕 API 调用进行错误检查或尝试/捕获逻辑,但生产程序会这样做。
- 我可能会将用户空间 API 调用放入它们自己的类中以实现可重用性。
- 我更改了设置输入参数值的方式,使其更加简化。
- 我使用单个StringConverter和LongConverter进行所有转换。
另请注意,我稍微更改了参数以显示当前用户的假脱机文件,因为在测试此示例时,我不想在当前作业中生成假脱机数据。
//Define a single StringConverter and LongConverter to re-use
cwbx.StringConverter stringConverter = new cwbx.StringConverter();
cwbx.LongConverter longConverter = new cwbx.LongConverter();
//Type the user space name only once. It's re-used a lot.
String userSpaceName = "HRAHMAN QGPL ";
//Connect to the AS/400
AS400System as400 = new AS400System();
as400.Define("MY_SYSTEM_HOST_ADDRESS");
as400.UserID = "MY_USER";
as400.Password = "MY_PASSWORD";
as400.Connect(cwbcoServiceEnum.cwbcoServiceRemoteCmd);
//Define the error structure once, to be re-used a lot.
Structure sc2 = new Structure();
sc2.Fields.Append("bytesprov", 4);
sc2.Fields.Append("bytesavail", 4);
sc2.Fields.Append("messageid", 7);
sc2.Fields.Append("err", 1);
sc2.Fields.Append("messagedta", 100);
sc2.Fields["bytesavail"].Value = longConverter.ToBytes(sc2.Length);
//Create the user space
cwbx.Program quscrtus = new cwbx.Program();
quscrtus.system = as400;
quscrtus.LibraryName = "QSYS";
quscrtus.ProgramName = "QUSCRTUS";
cwbx.ProgramParameters quscrtusParms = new cwbx.ProgramParameters();
quscrtusParms.Append("UserSpaceName", cwbrcParameterTypeEnum.cwbrcInput, 20).Value = stringConverter.ToBytes(userSpaceName);
quscrtusParms.Append("ExtendedAttr", cwbrcParameterTypeEnum.cwbrcInput, 10).Value = stringConverter.ToBytes("".PadRight(10));
quscrtusParms.Append("InitialSize", cwbrcParameterTypeEnum.cwbrcInput, 4).Value = longConverter.ToBytes(1);
quscrtusParms.Append("InitialValue", cwbrcParameterTypeEnum.cwbrcInput, 1).Value = longConverter.ToBytes(0);
quscrtusParms.Append("Auth", cwbrcParameterTypeEnum.cwbrcInput, 10).Value = stringConverter.ToBytes("*ALL".PadRight(10));
quscrtusParms.Append("Desc", cwbrcParameterTypeEnum.cwbrcInput, 50).Value = stringConverter.ToBytes("QUSLSPL Results".PadRight(50));
quscrtusParms.Append("Replace", cwbrcParameterTypeEnum.cwbrcInput, 10).Value = stringConverter.ToBytes("*YES".PadRight(10));
quscrtusParms.Append("APIError", cwbrcParameterTypeEnum.cwbrcInout, sc2.Length).Value = sc2.Bytes;
quscrtus.Call(quscrtusParms);
sc2.Bytes = quscrtusParms["APIError"].Value;
if (((string)stringConverter.FromBytes(sc2.Fields["messageid"].Value)).Trim().Length > 0)
{
//deal with error
return;
}
//Call the list spooled files API
cwbx.Program quslspl = new cwbx.Program();
quslspl.system = as400;
quslspl.LibraryName = "QSYS";
quslspl.ProgramName = "QUSLSPL";
ProgramParameters quslsplParms = new cwbx.ProgramParameters();
quslsplParms.Append("usrspcnam", cwbrcParameterTypeEnum.cwbrcInput, 20).Value = stringConverter.ToBytes(userSpaceName); //user space name
quslsplParms.Append("frmname", cwbrcParameterTypeEnum.cwbrcInput, 8).Value = stringConverter.ToBytes("SPLF0200"); //Format
quslsplParms.Append("usrnam", cwbrcParameterTypeEnum.cwbrcInput, 10).Value = stringConverter.ToBytes("*CURRENT".PadRight(10)); //User Name
quslsplParms.Append("cola", cwbrcParameterTypeEnum.cwbrcInput, 20).Value = stringConverter.ToBytes("*ALL".PadRight(20)); //qualified output queue
quslsplParms.Append("frmtyp", cwbrcParameterTypeEnum.cwbrcInput, 10).Value = stringConverter.ToBytes("*ALL".PadRight(10)); //form type
quslsplParms.Append("usrdta", cwbrcParameterTypeEnum.cwbrcInput, 10).Value = stringConverter.ToBytes("*ALL".PadRight(10)); //user-specific data
quslsplParms.Append("error", cwbrcParameterTypeEnum.cwbrcInout, sc2.Length).Value = sc2.Bytes; //error
quslsplParms.Append("qualifiedjobnm", cwbrcParameterTypeEnum.cwbrcInput, 26).Value = stringConverter.ToBytes("".PadRight(26)); //qualified job name
//keys. The SPLF0200 structure uses a list of field keys. So we tell the API which keys we want and that's what it returns.
cwbx.Structure keys = new cwbx.Structure();
keys.Fields.Append("Spooledfilename", 4).Value = longConverter.ToBytes(201);
keys.Fields.Append("Username", 4).Value = longConverter.ToBytes(203);
keys.Fields.Append("opqueue", 4).Value = longConverter.ToBytes(206);
keys.Fields.Append("userdata", 4).Value = longConverter.ToBytes(209);
keys.Fields.Append("status", 4).Value = longConverter.ToBytes(210);
keys.Fields.Append("totpages", 4).Value = longConverter.ToBytes(211);
keys.Fields.Append("copies", 4).Value = longConverter.ToBytes(213);
keys.Fields.Append("openeddate", 4).Value = longConverter.ToBytes(216);
keys.Fields.Append("opentime", 4).Value = longConverter.ToBytes(217);
keys.Fields.Append("jobid", 4).Value = longConverter.ToBytes(218);
keys.Fields.Append("fileid", 4).Value = longConverter.ToBytes(219);
quslsplParms.Append("keys", cwbrcParameterTypeEnum.cwbrcInput, keys.Length).Value=keys.Bytes;
quslsplParms.Append("numberoffields", cwbrcParameterTypeEnum.cwbrcInput, 4).Value = longConverter.ToBytes(keys.Fields.Count); //number of keys to return
quslspl.Call(quslsplParms);
sc2.Bytes = quslsplParms["error"].Value;
if (((string)stringConverter.FromBytes(sc2.Fields["messageid"].Value)).Trim().Length > 0)
{
//deal with error
return;
}
//Get the list information from the user space
cwbx.Structure listInfo = new cwbx.Structure();
listInfo.Fields.Append("OffsetToData", 4);
listInfo.Fields.Append("DataSectionSize", 4);
listInfo.Fields.Append("NumberOfEntries", 4);
listInfo.Fields.Append("EntrySize", 4);
//The List information data structure starts at zero-based position 0x7c. The retrieve user space
//API uses 1-based indexing. Retreive the list information from the user space.
cwbx.Program qusrtvus = new cwbx.Program();
qusrtvus.system = as400;
qusrtvus.LibraryName = "QSYS";
qusrtvus.ProgramName = "QUSRTVUS";
cwbx.ProgramParameters qusrtvusParms = new cwbx.ProgramParameters();
qusrtvusParms.Append("UserSpaceName", cwbrcParameterTypeEnum.cwbrcInput, 20).Value = stringConverter.ToBytes(userSpaceName);
qusrtvusParms.Append("StartingPosition", cwbrcParameterTypeEnum.cwbrcInput, 4).Value = longConverter.ToBytes(0x7c + 1);
qusrtvusParms.Append("Length", cwbrcParameterTypeEnum.cwbrcInput, 4).Value = longConverter.ToBytes(listInfo.Length);
qusrtvusParms.Append("Receiver", cwbrcParameterTypeEnum.cwbrcInout, listInfo.Length);
qusrtvusParms.Append("APIError", cwbrcParameterTypeEnum.cwbrcInout, sc2.Length).Value = sc2.Bytes;
qusrtvus.Call(qusrtvusParms);
sc2.Bytes = qusrtvusParms["APIError"].Value;
if (((string)stringConverter.FromBytes(sc2.Fields["messageid"].Value)).Trim().Length > 0)
{
//deal with error
return;
}
listInfo.Bytes = qusrtvusParms["Receiver"].Value;
int offsetToData = longConverter.FromBytes(listInfo.Fields["OffsetToData"].Value);
int numberOfEntries = longConverter.FromBytes(listInfo.Fields["NumberOfEntries"].Value);
int entrySize = longConverter.FromBytes(listInfo.Fields["EntrySize"].Value);
//Define the structure to receive the SPLF0200 Field data. This is described in the QUSLSPL API.
//Note: According to the API documentation, this is the only part that repeats for each key. The first
//four bytes of the SPLF0200 structure is the count of keys returned.
cwbx.Structure SPLF0200Field = new cwbx.Structure(); //individual field value data
SPLF0200Field.Fields.Append("LengthOfInformation", 4);
SPLF0200Field.Fields.Append("KeyField", 4);
SPLF0200Field.Fields.Append("TypeOfData", 1);
SPLF0200Field.Fields.Append("Reserved", 3);
SPLF0200Field.Fields.Append("LengthOfData", 4);
//Loop through each entry in the list and get the field values by key
for (int currentEntry = 0; currentEntry < numberOfEntries; currentEntry++)
{
qusrtvusParms["StartingPosition"].Value = longConverter.ToBytes(offsetToData + (currentEntry * entrySize) + 1);
qusrtvusParms["Length"].Value = longConverter.ToBytes(entrySize);
qusrtvusParms["Receiver"].Length = entrySize;
qusrtvus.Call(qusrtvusParms);
sc2.Bytes = qusrtvusParms["APIError"].Value;
if (((string)stringConverter.FromBytes(sc2.Fields["messageid"].Value)).Trim().Length > 0)
{
//deal with error
return;
}
//According to the SPLF0200 format, the first 4-byte integer is the number of fields returned.
//After that, it's a variable list of key structures.
byte[] entry = qusrtvusParms["Receiver"].Value;
byte[] numberOfFieldsReturnedBytes = new byte[4];
Array.Copy(entry, 0, numberOfFieldsReturnedBytes, 0, 4);
int numberOfFieldsReturned = longConverter.FromBytes(numberOfFieldsReturnedBytes);
int lastBufferEnd = 4;
//Fields to hold the spooled file field elements. Note: In a production environment, I would normally
//create a class to hold all of this, but this is just for sample purposes.
String spooledFileName = "";
String userName = "";
String opqueue = "";
String userdata = "";
String status = "";
int totpages = 0;
int copies = 0;
String openeddate = "";
String opentime = "";
byte[] jobid = new byte[16];
byte[] fileid = new byte[16];
for (int currentField = 0; currentField < numberOfFieldsReturned; currentField++)
{
byte[] SPLF0200FieldBytes = new byte[SPLF0200Field.Length];
Array.Copy(entry, lastBufferEnd, SPLF0200FieldBytes, 0, SPLF0200FieldBytes.Length);
SPLF0200Field.Bytes = SPLF0200FieldBytes;
int fieldDataLength = longConverter.FromBytes(SPLF0200Field.Fields["LengthOfData"].Value);
int fieldInfoLength = longConverter.FromBytes(SPLF0200Field.Fields["LengthOfInformation"].Value);
int fieldKey = longConverter.FromBytes(SPLF0200Field.Fields["KeyField"].Value);
byte[] fieldDataBytes = new byte[fieldDataLength];
Array.Copy(entry, lastBufferEnd + 16, fieldDataBytes, 0, fieldDataLength);
lastBufferEnd = lastBufferEnd + fieldInfoLength;
switch (fieldKey) {
case 201:
spooledFileName = stringConverter.FromBytes(fieldDataBytes);
break;
case 203:
userName = stringConverter.FromBytes(fieldDataBytes);
break;
case 206:
opqueue = stringConverter.FromBytes(fieldDataBytes);
break;
case 209:
userdata = stringConverter.FromBytes(fieldDataBytes);
break;
case 210:
status = stringConverter.FromBytes(fieldDataBytes);
break;
case 211:
totpages = longConverter.FromBytes(fieldDataBytes);
break;
case 213:
copies = longConverter.FromBytes(fieldDataBytes);
break;
case 216:
openeddate = stringConverter.FromBytes(fieldDataBytes);
break;
case 217:
opentime = stringConverter.FromBytes(fieldDataBytes);
break;
case 218:
jobid = fieldDataBytes;
break;
case 219:
fileid = fieldDataBytes;
break;
}
}
//All field elements that the API returned (that we care about) are loaded.
//Now do something with the spooled file fields here.
}
//Delete the user space
cwbx.Program qusdltus = new cwbx.Program();
qusdltus.system = as400;
qusdltus.LibraryName = "QSYS";
qusdltus.ProgramName = "QUSDLTUS";
cwbx.ProgramParameters qusdltusParms = new cwbx.ProgramParameters();
qusdltusParms.Append("UserSpaceName", cwbrcParameterTypeEnum.cwbrcInput, 20).Value = stringConverter.ToBytes(userSpaceName);
qusdltusParms.Append("APIError", cwbrcParameterTypeEnum.cwbrcInout, sc2.Length).Value = sc2.Bytes;
qusdltus.Call(qusdltusParms);
sc2.Bytes = qusdltusParms["APIError"].Value;
if (((string)stringConverter.FromBytes(sc2.Fields["messageid"].Value)).Trim().Length > 0)
{
//deal with error
return;
}