Как идентифицировать и использовать буферные файлы другого пользователя, используя пользователя 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)