Как идентифицировать и использовать буферные файлы другого пользователя, используя пользователя QTCP (COMMAND PROMPT)?

Здесь я подключаюсь к машине AS400 из командной строки с помощью команды (FTP Servername).
Каждое действие, которое я делаю с использованием командной строки, отправляется с пользователем QTCP в фоновом режиме.

Вот основная проблема:

  • У меня есть команда, которая создает файл спула с именем, которое я использовал для входа в систему из командной строки.
  • Я хочу использовать этот файл спулинга и скопировать его в одну из моих библиотек, и все это можно сделать с помощью команды CPYSPLF, но как сделать то же самое, используя пользователя QTCP.
  • Мое главное требование здесь - выполнять командные операции CL, используя командную строку, а не терминал AS400.

3 ответа

Решение

@user2338816 хорошо описывает использование API QSPRILSP. Но если это не обеспечивает то, что вам нужно, вот как вы можете использовать API Список буферных файлов (QUSLSPL), чтобы найти его.

Перед тем, как начать, просмотрите мой ответ из этого поста: Программирование IBM iSeries API QUSLSPL на C# Это хороший пример использования API QUSLSPL и пользовательских пространств, хотя он говорит на C#. Вот как вы используете этот API в RPG IV:

Для начала вам нужно прототипировать вызовы 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                

Создать пространство пользователя

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)       

Получить данные из пространства пользователя

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)       

Удалить пространство пользователя

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

Мне нравится создавать поле для хранения имени пространства пользователя, чтобы мне не приходилось его набирать:

DUserSpace        S             20    INZ('SPLFSPACE QTEMP     ')

При вызове API вам потребуется следующая структура данных об ошибках 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             

Наконец, вот структура данных с информацией для каждого возвращаемого буферного файла:

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 List Spooled Files имеет больше параметров, чем требовалось в этом другом ответе, и я использовал их в прототипе выше. Поскольку вы не можете указать имя буферного файла в качестве параметра для поиска, мы можем указать дату создания и диапазон времени, чтобы помочь ограничить возвращаемые результаты.

Таким образом, фактическое кодирование просто. Вы перечисляете все буферные файлы, принадлежащие 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 минут, но это, вероятно, слишком большой промежуток времени. Эксперимент, чтобы увидеть, что работает для вас.

Все это должно будет войти в новую программу, которая затем вернет информацию, необходимую для команды CPYSPLF. Фактически, вы можете создать эту программу и выполнить для вас команду CPYSPLF, чтобы ваш сценарий FTP был проще.

До сих пор нет примера для API восстановления идентификатора последнего созданного буферного файла (QSPRILSP), поэтому я добавлю его. Скомпилируйте что-то вроде этого:

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 и возвращает ли правильную идентификационную информацию. (Команда SNDPGMMSG просто помещает сообщение в журнал заданий FTP-сервера; оно не требуется в вашем CL.)

Если вы запустили WRKOBJLCK для своего профиля пользователя перед тем, как ВЫЙТИ из сеанса FTP, вы можете проверить журнал заданий, чтобы увидеть, появляется ли сообщение. Вы можете использовать это сообщение, чтобы узнать номер задания QPRTJOB, чтобы убедиться, что там находится буферный файл из примера команды DSPMSGD. Это должен быть самый последний буферный файл в этой работе. Это также должен быть самый последний буферный файл в списке WRKSPLF; и если вы отображаете его атрибуты, вы должны увидеть имя QPRTJOB.

Этот фрагмент кода копирует последний спулфайл, созданный в 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)          
Другие вопросы по тегам