21
Sat, Dec
3 New Articles

The API Corner: Running CL Commands from RPG

APIs
Typography
  • Smaller Small Medium Big Bigger
  • Default Helvetica Segoe Georgia Times

Use the QCMDEXC, system, and QCAPCMD APIs to run CL commands from within your RPG application.

 

In last month's column, "Do I Really Need to Call a CL Program to Perform This Function?," the QCMDEXC, system, and QCAPCMD APIs were introduced. All three of these APIs are available to enable the running of CL commands from an application program. Today, we'll look at what is required to implement these APIs within your application program as well as some of the considerations that exist with each of the APIs.

What We Hope to Accomplish by Running CL from an RPG Program

To initially demonstrate the three APIs, we'll use a rather simple scenario: clearing a physical file member in preparation of further processing (this further processing will not be shown but could be along the lines of loading a new batch of records). The name of the file is SOMEFILE, and the name of the member is the user profile name associated with the job running the program. This initial scenario will either successfully clear the member and continue processing, or return an escape message to the caller of the program. Two different user escape messages are defined because of the characteristics of the APIs we will be using. To create message file OURMSGS, along with escape messages ESC0001 and ESC0002, use the following commands.

 

CRTMSGF MSGF(OURMSGS)

ADDMSGD MSGID(ESC0001) MSGF(OURMSGS) +

   MSG('Unexpected error encountered. Examine job log for further information.')

ADDMSGD MSGID(ESC0002) MSGF(OURMSGS) +

   MSG('Unexpected error &1 encountered .') FMT((*CHAR 7))

 

In a future scenario demonstrating error recovery using these APIs, we'll add checks for anticipated errors. These checks will include the following:

  • If the clear fails due to the member not being found, the program will add the member and continue processing.
  • If the clear fails due to the file not being found, the program will create the file and member and then continue processing
  • If any other error is encountered, the program will end with one of the escape messages previously defined.

Using the Execute Command (QCMDEXC) API

Using the Execute Command (QCMDEXC) API, documented here, the following program implements the initial scenario described above.

 

h dftactgrp(*no)                                               

                                                               

dRunCmd           pr                  extpgm('QCMDEXC')        

d Cmd                          512    const options(*varsize)  

d LenCmd                        15p 5 const                    

d IGC                            3    const options(*nopass)   

                                                               

dSndMsg           pr                  extpgm('QSYS/QMHSNDPM')  

d MsgID                          7    const                    

d QualMsgF                      20    const                    

d MsgDta                     65535    const options(*varsize)  

d LenMsgDta                     10i 0 const                    

d MsgType                       10    const                    

d CSE                        65535    const options(*varsize)  

d CSECtr                        10i 0 const                    

d MsgKey                         4                             

d QUSEC                               likeds(QUSEC)          

d LenCSE                        10i 0 const options(*nopass) 

d CSEQual                       20    const options(*nopass) 

d DSPWaitTime                   10i 0 const options(*nopass) 

d CSEType                       10    const options(*nopass) 

d CCSID                         10i 0 const options(*nopass) 

                                                             

 /copy qsysinc/qrpglesrc,qusec                               

                                                             

dPSDS            sds           429    qualified              

d JobUsr                254    263                           

                                                              

dCmd              s            512                           

dMsgKey           s              4                           

                                                             

 /free                                                        

                                                             

  QUSBPRV = 0;                                                 

                                                               

  monitor;                                                      

     Cmd = 'CLRPFM FILE(SOMEFILE) MBR(' + PSDS.JobUsr + ')';   

     RunCmd(Cmd :%len(%trim(Cmd)));                            

  on-error;                                                    

     SndMsg('ESC0001' :'OURMSGS   *LIBL' :' ' :0               

            :'*ESCAPE' :'*PGMBDY' :1 :MsgKey :QUSEC);          

  endmon;                                                      

                                                               

  // Do further processing                                     

                                                               

  *inlr = *on;                                                 

  return;                                                      

                                                                

 /end-free                                                     

 

The program source, named CMDEXC0, starts by prototyping the QCMDEXC API along with the Send Program Message (QMHSNDPM) API. If you are not familiar with the QMHSNDPM API, you may want to review the article "Inform Users of Problems by Sending Error Messages from Application Programs." Related to the use of QMHSNDPM, the program later also copies the QSYSINC QRPGLESRC include QUSEC, defines the variable MsgKey, and sets the Bytes provided field of the QUSEC error code structure to zero. As the name of the member to be cleared is the same as the name of the user running the job, the program also defines the Program Status Data Structure (PSDS) and sub-field JobUsr (the job user profile name). This is followed by the definition for the Cmd variable. The Cmd variable will be used to hold the CL command to be run.

 

Actually running the command is very simple. The program starts a monitor group to detect if any errors are encountered (as mentioned in the previous article, "Do I Really Need to Call a CL Program to Perform This Function?," QCMDEXC returns errors as escape messages), sets the Cmd variable to the CL command string we want to run (CLRPFM with the MBR keyword set to the job user profile name PSDS.JobUsr), and then calls the QCMDEXC API (prototyped as function RunCmd). When calling QCMDEXC, the second parameter is set to the blank-trimmed length of the command string to run. This trimming of trailing blanks is not actually necessary (we could have just as easily used %size(Cmd) because the API tolerates trailing blanks), but is done as a personal preference.

 

If the CLRPFM command runs without error, the program resumes execution following the associated endmon statement. Note that, if you have a file named SOMEFILE in your library list, this demonstration program (and those that follow) will clear a member of that file named the same as the user profile you signed on with. To avoid inadvertently clearing a production file on your system if you do have a production file by this name, you will want to change the CLRPFM command string to reference another file name or ensure that the library containing SOMEFILE is not in your library list.

 

If any error is encountered when running the CLRPFM command, the associated on-error block is run. The on-error block sends the escape message ESC0001, which then ends the program. ESC0001 is used as QCMDEXC returns errors as exceptions, and while the monitor group handles the exception, the exception message can still be found in the job log.

 

To compile and run the program, you can use these commands:

 

CRTBNDRPG PGM(CMDEXC0)

CALL PGM(CMDEXC0)

 

If the file SOMEFILE is not currently in your jobs library list, you will receive the escape message ESC0001 and in your job log find CPF3142, File SOMEFILE in library *LIBL not found. If the file SOMEFILE does exist but does not contain a member with the name of the user profile you signed on with, you will receive the escape message ESC0001 and in your job log find CPF3141, Member XXXXXX not found, where XXXXXX is the name of your user profile. If the file SOMEFILE does exist and contains a member with the name of the user profile you signed on with, your job log will contain CPC3101, Member XXXXXX file SOMEFILE in YYYYYY cleared, where YYYYYY is the name of the library containing file SOMEFILE.

 

It's that easy. Now let's look at what's required to clear the member using the system API, which is documented in Chapter 2 here.

 

Using the Execute a Command (System) API

h dftactgrp(*no) bnddir('QC2LE')                                 

                                                                 

dRunCmd           pr            10i 0 extproc('system')          

d Cmd                             *   value options(*string)     

                                                                 

dSndMsg           pr                  extpgm('QSYS/QMHSNDPM')    

d MsgID                          7    const                      

d QualMsgF                      20    const                      

d MsgDta                     65535    const options(*varsize)    

d LenMsgDta                     10i 0 const                      

d MsgType                       10    const                      

d CSE                        65535    const options(*varsize)    

d CSECtr                        10i 0 const                      

d MsgKey                         4                               

d QUSEC                               likeds(QUSEC)              

d LenCSE                        10i 0 const options(*nopass)     

d CSEQual                       20    const options(*nopass)  

d DSPWaitTime                   10i 0 const options(*nopass)  

d CSEType                       10    const options(*nopass)  

d CCSID                         10i 0 const options(*nopass)  

                                                              

 /copy qsysinc/qrpglesrc,qusec                                

                                                               

dPSDS            sds           429    qualified               

d JobUsr                254    263                            

                                                              

dCmd              s            512                            

dMsgID            s              7    import('_EXCP_MSGID')   

dMsgKey           s              4                            

                                                              

 /free                                                         

                                                              

  QUSBPRV = 0;                                                 

                                                               

  Cmd = 'CLRPFM FILE(SOMEFILE) MBR(' + PSDS.JobUsr + ')';      

  if RunCmd(Cmd) = 1;                                          

     SndMsg('ESC0002' :'OURMSGS   *LIBL' :MsgID :%size(MsgID)  

            :'*ESCAPE' :'*PGMBDY' :1 :MsgKey :QUSEC);          

  endif;                                                       

                                                               

  // Do further processing                                     

                                                               

  *inlr = *on;                                                 

  return;                                                      

                                                               

 /end-free                                                      

 

The program source, named SYSTEM0, is initially similar to the earlier program CMDEXC0 in terms of providing prototypes for the called APIs and declaring variables. There are two differences:

  • The specification bnddir('QC2LE') in the H-spec—This addition is necessary if you will be creating the sample program and your System i is at V5R4 or earlier.
  • The new variable, MsgID—MsgID is used to import the global variable _EXCP_MSGID, which is set by the system API if the CL command being run encounters an error.  _EXCP_MSGID reflects the exception message ID encountered.

The actual running of the command, and related error detection, however, is quite different, though still easy to implement. Rather than the two parameters (command to run and length of the command string) of QCMDEXC, the system API accepts one parameter: the command to run. The length of the command is determined by a null byte and implemented by the options(*string) specification of the prototype. Error detection is also different in that, rather than returning errors as exception messages, the system API indicates that an error has been encountered by using an integer return value of positive 1.

 

Due to no exceptions being returned by the API, there is no need for the program to define a monitor group. After setting the proper command string value to the Cmd variable, the program calls the API and checks the return value of the API for positive 1. If the return value is not 1, the program resumes running after the ENDIF statement. If the return value is 1, the program sends the escape message ESC0002, which then ends the program.

 

To compile and run the program, you can use these commands:

 

CRTBNDRPG PGM(SYSTEM0)

CALL PGM(SYSTEM0)

 

If the file SOMEFILE is not currently in your jobs library list, you will receive the escape message ESC0002 with message replacement text of 'CPF3142' (file not found). If the file SOMEFILE does exist but does not contain a member with the name of the user profile you signed on with, you will receive the escape message ESC0002 with message replacement text of 'CPF3141' (member not found). If the file SOMEFILE does exist and contains a member with the name of the user profile you signed on with, your job log will contain message CPC3101, Member XXXXXX file SOMEFILE in YYYYYY cleared, where XXXXXX is the name of your user profile and YYYYYY is the name of the library containing file SOMEFILE.

 

Due to the system API not using exception messages to indicate failures, you will not find the CPF3142 and CPF3141 error messages in your job log as you did with CMDEXC0. And as ESC0001 points you to the job log, the SYSTEM0 demonstration program uses message ESC0002 (which does not refer you to the job log as there's little that's more aggravating than being told to look "over there" and finding nothing there). For this same reason (the lack of information in the job log), SYSTEM0 also sends the CPF exception message ID as replacement text in message ESC0002. For our demonstration program, with only one file being used, just having the CPF message ID should be sufficient for problem determination. A more complex application may need to use additional replacement text variables—for instance, to clearly identify the file being used if multiple files are involved.

 

Note that you do, however, find this completion message in the job log: CPC3101, Member XXXXX file SOMEFILE in YYYYYY cleared. With the system API completion messages, informational messages and the like will be available. It's just the actual escape message that is removed from the job log.

 

Now let's look at what's required to clear the member using the Process Commands (QCAPCMD) API, which is documented here.

Using the Process Commands (QCAPCMD) API with Escape Messages

h dftactgrp(*no)                                                 

                                                                 

dRunCmd           pr                  extpgm('QCAPCMD')          

d SourceCmd                  65535    const options(*varsize)    

d LenSrcCmd                     10i 0 const                      

d CtlBlk                     65535    const options(*varsize)    

d LenCtlBlk                     10i 0 const                      

d CtlBlkFmt                      8    const                      

d ChgCmd                         1    options(*varsize)          

d LenAvlChgCmd                  10i 0 const                      

d LenRtnChgCmd                  10i 0                            

d QUSEC                               likeds(QUSEC)              

                                                                 

dSndMsg           pr                  extpgm('QSYS/QMHSNDPM')    

d MsgID                          7    const                      

d QualMsgF                      20    const                      

d MsgDta                     65535    const options(*varsize)   

d LenMsgDta                     10i 0 const                      

d MsgType                       10    const                     

d CSE                        65535    const options(*varsize)   

d CSECtr                        10i 0 const                     

d MsgKey                         4                               

d QUSEC                               likeds(QUSEC)             

d LenCSE                        10i 0 const options(*nopass)    

d CSEQual                       20    const options(*nopass)    

d DSPWaitTime                   10i 0 const options(*nopass)    

d CSEType                       10    const options(*nopass)    

d CCSID                         10i 0 const options(*nopass)    

                                                                

 /copy qsysinc/qrpglesrc,qcapcmd                                

 /copy qsysinc/qrpglesrc,qusec                                  

                                                                

dPSDS            sds           429    qualified                 

d JobUsr                254    263                            

                                                              

dCmd              s            512                            

dMsgKey           s              4                            

dNotUsedChr       s              1                            

dNotUsedInt       s             10i 0                         

                                                              

 /free                                                        

                                                               

  QUSBPRV = 0;                                                

                                                              

  QCAP0100 = *loval; // initialize input structure to nulls   

  QCACMDPT = 0;      // Run command                           

  QCABCSDH = '0';    // Ignore DBCS                           

  QCAPA = '0';       // Do not prompt command                 

  QCACMDSS = '0';    // User i5/OS syntax                     

                                                               

  monitor;                                                    

     Cmd = 'CLRPFM FILE(SOMEFILE) MBR(' + PSDS.JobUsr + ')';  

     RunCmd(Cmd :%len(%trim(Cmd)) :QCAP0100 :%size(QCAP0100)  

            :'CPOP0100' :NotUsedChr :0 :NotUsedInt :QUSEC);   

  on-error;                                                   

     SndMsg('ESC0001' :'OURMSGS   *LIBL' :' ' :0              

            :'*ESCAPE' :'*PGMBDY' :1 :MsgKey :QUSEC);         

  endmon;                                                      

                                                              

  // Do further processing                                    

                                                              

  *inlr = *on;                                                 

  return;                                                     

                                                              

 /end-free                                                    

 

The program source, named PCMD0, is again quite similar to the earlier program CMDEXC0 in terms of providing prototypes for the called APIs and declaring variables. These are the differences:

  • Quite a few more parameters for the prototype of QCAPCMD due to significantly more function being available (though we will not be using these additional features)
  • The inclusion of QSYSINC member QCAPCMD from QRPGLESRC to define the Options control block parameter of the API
  • The new variables NotUsedChr and NotUsedInt, which are not used but must be defined as they are prototyped as outputs of the QCAPCMD API

The actual running of the command, and related error detection, is essentially the same as with CMDEXC0. There is additional setup in order to initialize the various options available in the Options control block structure, which are being set to simply run a command, but the approach is the same.

 

To compile and run the program, you can use these commands:

 

CRTBNDRPG PGM(PCMD0)

CALL PGM(PCMD0)

 

If the file SOMEFILE is not currently in your jobs library list, you will receive the escape message ESC0001 and in your job log find CPF3142, File SOMEFILE in library *LIBL not found. If the file SOMEFILE does exist but does not contain a member with the name of the user profile you signed on with, you will receive the escape message ESC0001 and in your job log find CPF3141, Member XXXXXX not found, where XXXXXX is the name of your user profile. If the file SOMEFILE does exist and contains a member with the name of the user profile you signed on with, your job log will contain CPC3101, Member XXXXXX file SOMEFILE in YYYYYY cleared, where YYYYYY is the name of the library containing file SOMEFILE. This is the same output as you experienced with CMDEXC0.

 

The QCAPCMD API can however also provide the same output as the SYSTEM0 demonstration program, as shown in the following program.

Using the Process Commands (QCAPCMD) API Without Escape Messages

h dftactgrp(*no)                                                 

                                                                  

dRunCmd           pr                  extpgm('QCAPCMD')          

d SourceCmd                  65535    const options(*varsize)    

d LenSrcCmd                     10i 0 const                      

d CtlBlk                     65535    const options(*varsize)    

d LenCtlBlk                     10i 0 const                      

d CtlBlkFmt                      8    const                      

d ChgCmd                         1    options(*varsize)           

d LenAvlChgCmd                  10i 0 const                      

d LenRtnChgCmd                  10i 0                            

d QUSEC                               likeds(QUSEC)              

                                                                  

dSndMsg           pr                  extpgm('QSYS/QMHSNDPM')    

d MsgID                          7    const                      

d QualMsgF                      20    const                      

d MsgDta                     65535    const options(*varsize)

d LenMsgDta                     10i 0 const                  

d MsgType                       10    const                  

d CSE                        65535    const options(*varsize)

d CSECtr                        10i 0 const                  

d MsgKey                         4                           

d QUSEC                               likeds(QUSEC)          

d LenCSE                        10i 0 const options(*nopass) 

d CSEQual                       20    const options(*nopass) 

d DSPWaitTime                   10i 0 const options(*nopass) 

d CSEType                       10    const options(*nopass) 

d CCSID                         10i 0 const options(*nopass) 

                                                              

 /copy qsysinc/qrpglesrc,qcapcmd                             

 /copy qsysinc/qrpglesrc,qusec                               

                                                             

dPSDS            sds           429    qualified               

d JobUsr                254    263                              

                                                                

dCmd              s            512                              

dMsgKey           s              4                               

dNotUsedChr       s              1                              

dNotUsedInt       s             10i 0                           

                                                                

 /free                                                           

                                                                

  QUSBPRV = %size(QUSEC);                                       

                                                                

  QCAP0100 = *loval; // initialize input structure to nulls     

  QCACMDPT = 0;      // Run command                             

  QCABCSDH = '0';    // Ignore DBCS                             

  QCAPA = '0';       // Do not prompt command                   

  QCACMDSS = '0';    // User i5/OS syntax                       

                                                                

  Cmd = 'CLRPFM FILE(SOMEFILE) MBR(' + PSDS.JobUsr + ')';      

  RunCmd(Cmd :%len(%trim(Cmd)) :QCAP0100 :%size(QCAP0100)      

         :'CPOP0100' :NotUsedChr :0 :NotUsedInt :QUSEC);       

  if QUSBAVL > 0;                                              

     SndMsg('ESC0002' :'OURMSGS   *LIBL' :QUSEI :%size(QUSEI)  

            :'*ESCAPE' :'*PGMBDY' :1 :MsgKey :QUSEC);          

  endif;                                                        

                                                               

  // Do further processing                                     

                                                               

  *inlr = *on;                                                 

  return;                                                      

                                                               

 /end-free                                                     

 

This program source, named PCMD1, is the same as PCMD0 with the following exceptions:

  • The Bytes provided field of the API error code structure is set to a non-zero value to turn off exceptions from the QCAPCMD API.
  • The monitor, on-error, and endmon statements are replaced by a test for the Bytes available field of the API error code structure being non-zero.
  • The escape message being sent is changed to ESC0002 with the Exception ID field of the API error code structure being used to set the message replacement text variable of ESC0002.

To compile and run the program, you can use these commands:

 

CRTBNDRPG PGM(PCMD1)

CALL PGM(PCMD1)

 

If the file SOMEFILE is not currently in your jobs library list, you will receive the escape message ESC0002 with message replacement text of 'CPF3142' (file not found). If the file SOMEFILE does exist but does not contain a member with the name of the user profile you signed on with, you will receive the escape message ESC0002 with message replacement text of 'CPF3141' (member not found). If the file SOMEFILE does exist and contains a member with the name of the user profile you signed on with, your job log will contain message CPC3101, Member XXXXXX file SOMEFILE in YYYYYY cleared, where XXXXXX is the name of your user profile and YYYYYY is the name of the library containing file SOMEFILE. This is the same output as you experienced with SYSTEM0.

 

By making very minor changes, namely the setting of the Error code Bytes provided field, you can control whether or not exception messages appear in the job log when using QCAPCMD. We will take advantage of this in future articles when we look at how to have the application program recover from errors such as file and/or member not found—and not leave "errors" in the job log when the application program is handling them (a pet peeve of mine that can impact the amount of time needed for problem determination).

Questions?

In the meantime, if you have any API questions, send them to me at This email address is being protected from spambots. You need JavaScript enabled to view it.. I'll see what I can do about answering your burning questions in future columns.

 

 

 

BLOG COMMENTS POWERED BY DISQUS

LATEST COMMENTS

Support MC Press Online

$

Book Reviews

Resource Center

  • SB Profound WC 5536 Have you been wondering about Node.js? Our free Node.js Webinar Series takes you from total beginner to creating a fully-functional IBM i Node.js business application. You can find Part 1 here. In Part 2 of our free Node.js Webinar Series, Brian May teaches you the different tooling options available for writing code, debugging, and using Git for version control. Brian will briefly discuss the different tools available, and demonstrate his preferred setup for Node development on IBM i or any platform. Attend this webinar to learn:

  • SB Profound WP 5539More than ever, there is a demand for IT to deliver innovation. Your IBM i has been an essential part of your business operations for years. However, your organization may struggle to maintain the current system and implement new projects. The thousands of customers we've worked with and surveyed state that expectations regarding the digital footprint and vision of the company are not aligned with the current IT environment.

  • SB HelpSystems ROBOT Generic IBM announced the E1080 servers using the latest Power10 processor in September 2021. The most powerful processor from IBM to date, Power10 is designed to handle the demands of doing business in today’s high-tech atmosphere, including running cloud applications, supporting big data, and managing AI workloads. But what does Power10 mean for your data center? In this recorded webinar, IBMers Dan Sundt and Dylan Boday join IBM Power Champion Tom Huntington for a discussion on why Power10 technology is the right strategic investment if you run IBM i, AIX, or Linux. In this action-packed hour, Tom will share trends from the IBM i and AIX user communities while Dan and Dylan dive into the tech specs for key hardware, including:

  • Magic MarkTRY the one package that solves all your document design and printing challenges on all your platforms. Produce bar code labels, electronic forms, ad hoc reports, and RFID tags – without programming! MarkMagic is the only document design and print solution that combines report writing, WYSIWYG label and forms design, and conditional printing in one integrated product. Make sure your data survives when catastrophe hits. Request your trial now!  Request Now.

  • SB HelpSystems ROBOT GenericForms of ransomware has been around for over 30 years, and with more and more organizations suffering attacks each year, it continues to endure. What has made ransomware such a durable threat and what is the best way to combat it? In order to prevent ransomware, organizations must first understand how it works.

  • SB HelpSystems ROBOT GenericIT security is a top priority for businesses around the world, but most IBM i pros don’t know where to begin—and most cybersecurity experts don’t know IBM i. In this session, Robin Tatam explores the business impact of lax IBM i security, the top vulnerabilities putting IBM i at risk, and the steps you can take to protect your organization. If you’re looking to avoid unexpected downtime or corrupted data, you don’t want to miss this session.

  • SB HelpSystems ROBOT GenericCan you trust all of your users all of the time? A typical end user receives 16 malicious emails each month, but only 17 percent of these phishing campaigns are reported to IT. Once an attack is underway, most organizations won’t discover the breach until six months later. A staggering amount of damage can occur in that time. Despite these risks, 93 percent of organizations are leaving their IBM i systems vulnerable to cybercrime. In this on-demand webinar, IBM i security experts Robin Tatam and Sandi Moore will reveal:

  • FORTRA Disaster protection is vital to every business. Yet, it often consists of patched together procedures that are prone to error. From automatic backups to data encryption to media management, Robot automates the routine (yet often complex) tasks of iSeries backup and recovery, saving you time and money and making the process safer and more reliable. Automate your backups with the Robot Backup and Recovery Solution. Key features include:

  • FORTRAManaging messages on your IBM i can be more than a full-time job if you have to do it manually. Messages need a response and resources must be monitored—often over multiple systems and across platforms. How can you be sure you won’t miss important system events? Automate your message center with the Robot Message Management Solution. Key features include:

  • FORTRAThe thought of printing, distributing, and storing iSeries reports manually may reduce you to tears. Paper and labor costs associated with report generation can spiral out of control. Mountains of paper threaten to swamp your files. Robot automates report bursting, distribution, bundling, and archiving, and offers secure, selective online report viewing. Manage your reports with the Robot Report Management Solution. Key features include:

  • FORTRAFor over 30 years, Robot has been a leader in systems management for IBM i. With batch job creation and scheduling at its core, the Robot Job Scheduling Solution reduces the opportunity for human error and helps you maintain service levels, automating even the biggest, most complex runbooks. Manage your job schedule with the Robot Job Scheduling Solution. Key features include:

  • LANSA Business users want new applications now. Market and regulatory pressures require faster application updates and delivery into production. Your IBM i developers may be approaching retirement, and you see no sure way to fill their positions with experienced developers. In addition, you may be caught between maintaining your existing applications and the uncertainty of moving to something new.

  • LANSAWhen it comes to creating your business applications, there are hundreds of coding platforms and programming languages to choose from. These options range from very complex traditional programming languages to Low-Code platforms where sometimes no traditional coding experience is needed. Download our whitepaper, The Power of Writing Code in a Low-Code Solution, and:

  • LANSASupply Chain is becoming increasingly complex and unpredictable. From raw materials for manufacturing to food supply chains, the journey from source to production to delivery to consumers is marred with inefficiencies, manual processes, shortages, recalls, counterfeits, and scandals. In this webinar, we discuss how:

  • The MC Resource Centers bring you the widest selection of white papers, trial software, and on-demand webcasts for you to choose from. >> Review the list of White Papers, Trial Software or On-Demand Webcast at the MC Press Resource Center. >> Add the items to yru Cart and complet he checkout process and submit

  • Profound Logic Have you been wondering about Node.js? Our free Node.js Webinar Series takes you from total beginner to creating a fully-functional IBM i Node.js business application.

  • SB Profound WC 5536Join us for this hour-long webcast that will explore:

  • Fortra IT managers hoping to find new IBM i talent are discovering that the pool of experienced RPG programmers and operators or administrators with intimate knowledge of the operating system and the applications that run on it is small. This begs the question: How will you manage the platform that supports such a big part of your business? This guide offers strategies and software suggestions to help you plan IT staffing and resources and smooth the transition after your AS/400 talent retires. Read on to learn: