Printer Redirection

I'm starting the progress of migrating RM Cobol (Linux) to RM Cobol/Visual Cobol(Linux) with Eclipse (Windows)


The problem I've encountered is if the Cobol Code has the "ASSIGN TO PRINTER" clause the program in RM/VC redirects the report to a file called "LPT1", which I know is a throwback to the older Parallel printers. Normally "ASSIGN TO PRINTER" just directs the report to the file name specified before the ASSIGN clause, which we could handle via redirection in Linux. That doesn't appear to work with RM/VC. I've even tried using "ASSIGN" to a file, but the file only had 6 of the 80 lines the report should've had. I should mention that the LPT1 is the complete report, but I really need to control where this file is created and what it is called.

Any Ideas?

  • There are several solutions:

    1) The simple short term solution is to use a NET USE command to associate LPT1 with a network printer, such as:

    net use lpt1 \\usauv-print01\usaup-rndprinter

    The major problem with this solution is that it communicates directly with the printer, bypassing Windows print spooling.

    2) In order to use the print spooler with VisualCOBOL, there are two, possibly three, solutions.  One requires that the standard COBOL I/O verbs be replaced with calls to a set of standard COBOL subprograms.  For example, the following sequence:

              OPEN  OUTPUT PRINTCAL.

              WRITE PRINTF-R FROM TEST-RECORD.

              CLOSE PRINTCAL.

    Would be replaced with:

         *    OPEN   OUTPUT PRINTCAL.

              CALL "PC_PRINTER_OPEN" USING PRINT-HANDLE, DOCUMENT-TITLE,

                  by value 4, by value 0 RETURNING STATUS-CODE.

         *    WRITE PRINTF-R FROM TEST-RECORD.

              CALL "PC_PRINTER_WRITE" USING PRINT-HANDLE, TEST-RECORD,

                  by value 23 RETURNING STATUS-CODE.

         *    CLOSE       PRINTCAL.

              CALL "PC_PRINTER_CLOSE" USING PRINT-HANDLE.

    The only troubling part about this solution is that the length of the record must be passed to the PC_PRINTER_WRITE routine.  We probably already know this for fixed length records, but variable length ones will be more difficult.

    3) Another solution is to use the printer_redirection tunable.  To do this, we would need to create a configuration file with the following contents:

    set printer_redirection=TRUE

    Then an environment variable needs to be set to indicate that this configuration file is to be read at start up:

    Set COBCONFIG_= C:\Dev\KenlygenTests\TestPrinter22\TestPrinter22\print.cfg

    The documentation says that this will work in both native and managed code, although setting the COBCONFIG_ environment variable will not be necessary using managed code.  

    4) Finally, the documentation on printer_redirection states that the COBOL callable subprogram PC_PRINTER_REDIRECTION_PROC can be used to change the printer redirection to the spooler, but I have not attempted to verify this.

  • We are using a 3rd Party Spooler in Linux, and use ENV variables to allow our users to choose which of 64 printers they would like their reports on ... so most of your ideas really don't fit.

    I tried using the "set printer_redirection=TRUE", unfortunately the report still ended up in the file LPT1.

    I just need to set it so that "ASSIGN TO PRINTER" writes to a file of my choosing, which I normally control with Linux scripts.

    Thanks for the quick response!

    Eric Boatman

  • Verified Answer

    Oh right.  I read that you are using Linux but then forgot.

    The first thing that you should realize is that you can put the file name after the PRINTER in the SELECT:

    select filename-1 assign to printer data-name-1

    Another thing to look at is the ASSIGN-PRINTER directive.  Here's a bit from the documentation:

    This directive has no effect if you specify a filename as part of the ASSIGN TO PRINTER clause.

    ASSIGN-PRINTER"filename" causes the output to be directed to the filename specified. The filename can be fully specified, including a path-name, base-name, and extension.

    ASSIGN-PRINTER() results in the same behavior as including the following COBOL statement:

    select filename-1 assign to printer filename-1

    That is, the filename used in your COBOL program is also used as the filename for your output. If the internal filename is too long for your operating system to handle, it is truncated to the maximum length the operating system allows.

    By default, the filename does not include an extension, but you can specify an extension by using the PRINT-EXT directive.

    Hope this helps!

  • The assign-printer() compiler directive will cause the behavior of "assign to printer" to match RM/COBOL behavior, that is, the access name for the file will be the same as the COBOL file-name.  To map this file name with an environment variable, use the environment variable name "dd_file-name", where file-name is your COBOL file name.  For example,  if pf01 is your COBOL file name, set the environment variable name "dd_pf01" to the value of the printer file access name.

  • The assign-printer() compiler directive will cause the behavior of "assign to printer" to match RM/COBOL behavior, that is, the access name for the file will be the same as the COBOL file-name.  To map this file name with an environment variable, use the environment variable name "dd_file-name", where file-name is your COBOL file name.  For example,  if pf01 is your COBOL file name, set the environment variable name "dd_pf01" to the value of the printer file access name.

  • The assign-printer() compiler directive will cause the behavior of "assign to printer" to match RM/COBOL behavior, that is, the access name for the file will be the same as the COBOL file-name.  To map this file name with an environment variable, use the environment variable name "dd_file-name", where file-name is your COBOL file name.  For example,  if pf01 is your COBOL file name, set the environment variable name "dd_pf01" to the value of the printer file access name.

  • I forgot to mention that on Linux, the parentheses may need to be escaped (assign-printer\(\)) or replaced with quotes to resolve shell issues.

  • Another good solution for shell issues with parentheses would to be to embed the assign-printer() directive in the source program with a $SET statement.  That way, you won't forget to specify it on future compilations and completely avoid the shell interactions.

  • Thanks for all your suggestions ...

    I could not get, $set assign-printer($Linux.Environment.Variable), to work.

    But I did get , ASSIGN TO PRINTER"$Linux.Environment.Variable", to work.

    I'm probably going to use the "ASSIGN TO PRINTER" method, just because I know we have reports that print multiple documents to multiple printers, and that will give me that degree of control.

    I'm not sure what I did wrong with the compiler directive method, hopefully this thinking won't come back to haunt me later.

  • Thanks for all your suggestions ...

    I could not get, $set assign-printer($Linux.Environment.Variable), to work.

    But I did get , ASSIGN TO PRINTER"$Linux.Environment.Variable", to work.

    I'm probably going to use the "ASSIGN TO PRINTER" method, just because I know we have reports that print multiple documents to multiple printers, and that will give me that degree of control.

    I'm not sure what I did wrong with the compiler directive method, hopefully this thinking won't come back to haunt me later.