- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
有人可以帮我用完整的C#代码调用SPLF0200格式的QUSLSPL吗?我可以调用该程序,但不知道如何捕获/读取输出。我是这个领域的新手。感谢你的帮助。
这是我的代码。
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。那些很复杂。我会尽力解释这一切。系好安全带!
除了错误结构中的内容以外,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
参数为:
完全限定的名称(char [20])
扩展属性(char [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
参数为:
全限定名(char [20])
起始位置(二进制[4])注意:这是从1开始的,而不是从0开始的。
要返回的数据长度(二进制[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调用进行错误检查或try / catch逻辑,但是生产程序会具有该功能。
我可能会将用户空间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;
}
关于c# - 用C#编程IBM iSeries API QUSLSPL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39024495/
有人可以帮我用完整的C#代码调用SPLF0200格式的QUSLSPL吗?我可以调用该程序,但不知道如何捕获/读取输出。我是这个领域的新手。感谢你的帮助。 这是我的代码。 cwbx.ProgramPar
我是一名优秀的程序员,十分优秀!