如何使用 QTCP 用户(命令提示符)识别和使用其他用户的假脱机文件?
How to identify and use spooled files of other user using QTCP user(COMMAND PROMPT)?
我在这里使用 (FTP Servername) 命令从命令提示符连接到 AS400 机器。
我使用命令提示符执行的每个操作都在后台由 QTCP 用户提交。
这里主要关注:
- 我有一个命令可以生成假脱机文件,其中包含我用于从命令提示符登录的名称。
- 我想使用该假脱机文件内容并复制到我的一个库中,所有这些都可以使用 CPYSPLF 命令来完成,但是如何使用 QTCP 用户来完成同样的事情.
- 我这里的主要要求是使用命令提示符而不是 AS400 终端执行 CL 命令操作。
@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 名称。
我在这里使用 (FTP Servername) 命令从命令提示符连接到 AS400 机器。
我使用命令提示符执行的每个操作都在后台由 QTCP 用户提交。
这里主要关注:
- 我有一个命令可以生成假脱机文件,其中包含我用于从命令提示符登录的名称。
- 我想使用该假脱机文件内容并复制到我的一个库中,所有这些都可以使用 CPYSPLF 命令来完成,但是如何使用 QTCP 用户来完成同样的事情.
- 我这里的主要要求是使用命令提示符而不是 AS400 终端执行 CL 命令操作。
@user2338816 就使用 QSPRILSP API 提出了一个很好的观点。但是,如果这不能提供您需要的内容,您可以通过以下方法使用 List Spooled Files (QUSLSPL) API 找到它。
在开始之前,请回顾一下我在这个 post 中的回答:
首先,您需要制作对 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 名称。