簡體   English   中英

用C#編程IBM iSeries API QUSLSPL

[英]Programming IBM iSeries API QUSLSPL in C#

有人可以幫我用完整的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的步驟如下:

  1. 創建用戶空間。
  2. 調用API。
  3. 檢查API中的錯誤。
  4. 查找每個條目的大小。
  5. 查找列表數據的開始。
  6. 循環瀏覽用戶空間中的條目。
  7. 刪除用戶空間。

創建用戶空間

通過創建用戶空間(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;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM