如何使用 QTCP 用户(命令提示符)识别和使用其他用户的假脱机文件?

How to identify and use spooled files of other user using QTCP user(COMMAND PROMPT)?

我在这里使用 (FTP Servername) 命令从命令提示符连接到 AS400 机器。
我使用命令提示符执行的每个操作都在后台由 QTCP 用户提交。

这里主要关注:

@user2338816 就使用 QSPRILSP API 提出了一个很好的观点。但是,如果这不能提供您需要的内容,您可以通过以下方法使用 List Spooled Files (QUSLSPL) API 找到它。

在开始之前,请回顾一下我在这个 post 中的回答: 这对使用 QUSLSPL API 和用户 spaces 有很好的入门知识,尽管它使用 C# 进行对话。所以这是你如何在角色扮演游戏 IV 中使用 API:

首先,您需要制作对 API 的调用的原型。

列出假脱机文件

DQUSLSPL          PR                  EXTPGM('QUSLSPL')    
D UserSpaceName                       Like(UserSpace) CONST
D FormatName                     8    CONST                
D UserName                      10    CONST                
D QualOutQName                  20    CONST                
D FormType                      10    CONST                
D UsrDta                        10    CONST                
D ErrorCode                           Like(APIError)       
D QualJobName                   26    CONST                
D KeyFields                      1    CONST                
D KeyFieldsNum                  10i 0 CONST                
D ASP                           10i 0 CONST                
D JobSystemName                  8    CONST                
D StartCRDate                    7    CONST                
D StartCRTime                    6    CONST                
D EndCRDate                      7    CONST                
D EndCRTime                      6    CONST                

创建用户Space

DCreateUserSpace  PR                  ExtPgm('QUSCRTUS')   
D Name                                Like(UserSpace) CONST
D ExtendedAttrib                10    CONST                
D InitialSize                   10i 0 CONST                
D InitialValue                   1    CONST                
D PublicAuth                    10    CONST                
D Text                          50    CONST                
D Replace                       10    CONST                
D ErrorCode                           Like(APIError)       

从用户那里获取数据space

DRtvUserSpace     PR                  ExtPgm('QUSRTVUS')   
D UserSpaceName                       Like(UserSpace) CONST
D StartingPos                   10i 0 CONST                
D LengthToReturn                10i 0 CONST                
D ReceiverVar                         Like(SPLF0300)       
D ErrorCode                           Like(APIError)       

删除用户Space

DDeleteUserSpace  PR                  ExtPgm('QUSDLTUS')   
D Name                                Like(UserSpace) CONST
D ErrorCode                           Like(APIError)       

我喜欢创建一个字段来存储用户 space 姓名,这样我就不必一直输入它了:

DUserSpace        S             20    INZ('SPLFSPACE QTEMP     ')

调用 APIs 时,您需要以下 API 错误数据结构:

DAPIError         DS                  Qualified
D AEBytesProv                   10i 0 Inz(117) 
D AEBytesAvail                  10i 0 Inz(0)   
D AEExceptionID                  7             
D AEReserved                     1             
D AEExceptData                  80             

最后,这是一个包含每个假脱机文件信息的数据结构 returned:

DSPLF0300         DS                  Qualified
D JobName                       10             
D UserName                      10             
D JobNumber                      6             
D SplfName                      10             
D SplfNumber                    10i 0          
D SplfStatus                    10i 0          
D DateCreated                    7             
D TimeCreated                    6             
D SplfSchedule                   1             
D SplfSystemName                10             
D UserData                      10             
D FormType                      10             
D OutQName                      10             
D OutQLib                       10             
D ASP                           10i 0          
D SplfSize                      10i 0          
D SplfSizeMult                  10i 0          
D TotalPages                    10i 0          
D CopiesLeft                    10i 0          
D Priority                       1             
D Reserved                       3             
D Internalppji                  10i 0          

假脱机文件列表 API 的参数比其他答案中需要的参数多,我在上面的原型中使用了它们。因为您不能将假脱机文件名指定为要搜索的参数,我们可以指定创建日期和时间范围以帮助限制 returned 结果。

所以实际编码很简单。您列出 QTCP 拥有的所有假脱机文件,例如,最后 5 分钟。查看列表并查看哪些名为 QPJOBLOG。抓住最近的一个。

DCounter          S             10i 0                                     
DStartPoint       S             10i 0                                     
DFiveMinutesAgo   S               Z                                       
DDateStart        S              7                                        
DTimeStart        S              6                                        

DLastSPLF         DS                  Qualified                           
D Job                           26                                        
D SplfName                      10                                        
D SplfNumber                    10i 0                                     
D Date                           7                                        
D Time                           6                                        

 /free                                                                    
  FiveMinutesAgo = %TimeStamp()-%Minutes(5);                              
  DateStart=%Char(%Date(FiveMinutesAgo):*CYMD0);                          
  TimeStart=%Char(%Time(FiveMinutesAgo):*HMS0);                           
  CreateUserSpace(UserSpace:*Blank:1:x'00':'*ALL':*Blank:'*YES':APIError);
  QUSLSPL(UserSpace:'SPLF0300':'QTCP':'*ALL':'*ALL':'*ALL':APIError:  
          *Blanks:*Blank:0:0:'*CURRENT':DateStart:TimeStart:'*LAST':      
          *Blanks);                                                       
  RtvUserSpace(UserSpace:1:%Len(ListInfo):ListInfo:APIError);             
  Counter = 0;                                                          
  StartPoint = ListInfo.ListDataOfs+1;                                  

  DoW Counter<ListInfo.ListEntryCount;                                  
    RtvUserSpace(UserSpace:StartPoint:%Len(SPLF0300):SPLF0300:APIError);
    If SPLF0300.SplfName='QPJOBLOG' And                                 
       SPLF0300.DateCreated>=LastSplf.Date And                          
       SPLF0300.TimeCreated>=LastSplf.Time;                             
      LastSplf.Job = SPLF0300.JobName +                                 
                     SPLF0300.UserName +                                
                     SPLF0300.JobNumber;                                
      LastSplf.SplfName = SPLF0300.SplfName;                            
      LastSplf.SplfNumber = SPLF0300.SplfNumber;                        
      LastSplf.Date = SPLF0300.DateCreated;                             
      LastSplf.Time = SPLF0300.TimeCreated;                             
    EndIf;                                                              
    StartPoint=StartPoint+ListInfo.EntrySize;                           
    Counter=Counter+1;                                                  
  EndDo;                                                                

  DeleteUserSpace(UserSpace:APIError);                                  

我的示例使用了 5 分钟,但这可能时间跨度太大了。实验看看什么对你有用。

所有这些都必须进入一个新程序,然后 return CPYSPLF 命令所需的信息。事实上,您可以让这个程序为您构建和执行 CPYSPLF 命令,这样您的 FTP 脚本就更简单了。

此代码 snipit 将最后创建的假脱机文件复制到 qtemp,然后复制到流文件。 &file 是假脱机文件的名称 'QPRINT' 例如。 &TOSMF 是流文件的名称。我一直使用此代码将报告作为电子邮件附件发送。

/* delete the ifs file this is a good check for authority */        
/* if the object can't be deleted you probably can't replace it */  
             RMVLNK     OBJLNK(&TOSTMF)                             
             MONMSG     MSGID(CPFA0A9)  /*object not found */       

/* make sure the spool file exists by holding it */                 
/* cpf returns to caller if the spool file doesn't exist */         
             HLDSPLF    FILE(&FILE) SPLNBR(*LAST)                   
             MONMSG     MSGID(CPF3337)  /*already held */           

    DLTF       FILE(QTEMP/QSPOOL)                               
    MONMSG     MSGID(CPF2105)   /*object not found */           
    CRTPF      FILE(QTEMP/QSPOOL) RCDLEN(132)                   
    CPYSPLF    FILE(&FILE) TOFILE(QTEMP/QSPOOL) SPLNBR(*LAST)   
    CPYTOSTMF  +                                                
                 FROMMBR('/qsys.lib/qtemp.lib/qspool.file/qsp+  
                 ool.mbr') TOSTMF(&TOSTMF) +                    
                 STMFOPT(*REPLACE) STMFCCSID(*PCASCII)          

仍然没有检索上次创建的假脱机文件的标识 (QSPRILSP) API 的示例,因此我将添加一个。像这样编译:

pgm    ( +
         &pSplFName   +
         &pJobName    +
         &pUserName   +
         &pJobNbr     +
         &pSplFNbr    +
       )

   dcl   &pSplFName   *char    10
   dcl   &pJobName    *char    10
   dcl   &pUserName   *char    10
   dcl   &pJobNbr     *char     6
   dcl   &pSplFNbr    *int


   dcl   &szRcvVar    *int            value( 70 )

   dcl   &errCod      *char   128
   dcl   &errRtn      *int            stg( *defined ) defvar( &errCod    1 )
   dcl   &errAvl      *int            stg( *defined ) defvar( &errCod    5 )
   dcl   &errMsgID    *char     7     stg( *defined ) defvar( &errCod    9 )
   dcl   &errMsgDta   *char    80     stg( *defined ) defvar( &errCod   17 )

   dcl   &fSPRL0100   *char    70
   dcl   &bytRtn      *int            stg( *defined ) defvar( &fSPRL0100   1 )
   dcl   &bytAvl      *int            stg( *defined ) defvar( &fSPRL0100   5 )
   dcl   &splFName    *char    10     stg( *defined ) defvar( &fSPRL0100   9 )
   dcl   &jobName     *char    10     stg( *defined ) defvar( &fSPRL0100  19 )
   dcl   &userName    *char    10     stg( *defined ) defvar( &fSPRL0100  29 )
   dcl   &jobNbr      *char     6     stg( *defined ) defvar( &fSPRL0100  39 )
   dcl   &splFNbr     *int            stg( *defined ) defvar( &fSPRL0100  45 )
   dcl   &jobSysName  *char     8     stg( *defined ) defvar( &fSPRL0100  49 )
   dcl   &splFCrtDat  *char     7     stg( *defined ) defvar( &fSPRL0100  57 )
   dcl   &rsv01       *char     1     stg( *defined ) defvar( &fSPRL0100  64 )
   dcl   &splFCrtTim  *char     6     stg( *defined ) defvar( &fSPRL0100  65 )



   call QSPRILSP   ( +
                     &fSPRL0100   +
                     &szRcvVar    +
                     'SPRL0100'   +
                     &errCod      +
                   )


   chgvar     &pSplFName       &splFName
   chgvar     &pJobName        &jobName
   chgvar     &pUserName       &userName
   chgvar     &pJobNbr         &jobNbr
   chgvar     &pSplFNbr        &splFNbr


   return

endpgm

在你的 CL 中,这样称呼它:

pgm    ( +
       )


   dcl   &splFName    *char    10
   dcl   &jobName     *char    10
   dcl   &userName    *char    10
   dcl   &jobNbr      *char     6
   dcl   &splFNbr     *int


   dspmsgd     CPF9898 output( *PRINT )

   call @@TSTSPL   ( +
                     &splFName    +
                     &jobName     +
                     &userName    +
                     &jobNbr      +
                     &splFNbr     +
                   )

   sndpgmmsg  msgid( CPF9897 ) msgf( QSYS/QCPFMSG ) +
                msgdta( &splFName *bcat &jobName *bcat &jobNbr ) +
                topgmq( *EXT ) +
                msgtype( *INFO )


   return

endpgm

代替@@TSTSPL,为新程序起一个有意义的名称。可以编译第二组示例代码,您可以在 FTP 会话中调用它以测试它是否调用 API 示例和 returns 正确的识别信息。 (SNDPGMMSG 命令只是将一条消息放入 FTP 服务器作业日志;您的 CL 中不需要它。)

如果您在退出 FTP 会话之前针对您的用户配置文件 运行 WRKOBJLCK,您可以检查作业日志以查看该消息是否显示。您可以使用该消息来了解您的 QPRTJOB 作业的作业编号,以验证来自示例 DSPMSGD 命令的假脱机文件是否显示在那里。它应该是该作业中最新的假脱机文件。它也应该是 WRKSPLF 列表中最新的假脱机文件;如果显示其属性,您应该会看到 QPRTJOB 名称。