Quote

Hi Jack,

We have a common include file that allows us to use Alphalan’s CPC function to copy print files to the user’s PC instead of printing them to a printer.

As an exercise, I have tried doing the same thing using a convoluted routine in A-Shell and although it works quite well, I am sure there must be a simpler way?

Thanks for any suggestions when you have time.

Joe
Code
        ! Alphalan version using CPC

        IF AS'IN'USE=0                        &
           PLINE="CPC  "+GOTOPP+"/D"          &
        :  XCALL STRIP,PLINE                  &
        :  XCALL AMOS,PLINE

        ! A-Shell version using FTP
  
        ! Will need the following included in the calling program
        !
        ! ++include ashinc:ashell.def
        !
        ! map1 AS'IN'USE,B,1,1
        ! map1 AS'SPEC,s,40
        ! map1 AS'STATUS,f,6
        ! map1 AS'LOCPATH,s,160
        !
        ! map1 AS'DDB
        !      map2 AS'DEV,s,6
        !      map2 AS'FILNAM,s,32
        !      map2 AS'EXT,s,8
        !      map2 AS'PRJ,s,3
        !      map2 AS'PRG,s,3
        !
        ! map1 AS'PROFILE,S,160
  
        ! First, get Windows Filespecs for the Filename (Contained in GOTOPP)
         AS'SPEC = GOTOPP
         xcall miamex, MX_FSPEC, AS'SPEC, AS'LOCPATH, "", 6, AS'DDB, AS'STATUS
        
         ! Strip off Base Miame Path from Filename
         I = instr(1,AS'LOCPATH,"\"+AS'DEV)
         IF I#0  AS'LOCPATH=AS'LOCPATH[I;160]
  
         ! Change all \ characters to /
         I = 0
 
      REPLACE'LOOP:
        X = I + 1
        I = instr(X,AS'LOCPATH,"\")
        if I = 1 AS'LOCPATH = "/" + AS'LOCPATH[2,-1]
        if I > 1 AS'LOCPATH = AS'LOCPATH[1,I-1] + "/" + AS'LOCPATH[I+1,-1]
        if I # 0  GOTO REPLACE'LOOP
 
        ! Next, find local transfer directory to use
        ? TAB(-10,AG_GETENV);"ATELOCALDIR";chr(127);

        input "",AS'PROFILE
 
        ! If no default local directory specified, use base ATE directory

        IF AS'PROFILE=""                                &
           ? TAB(-10,AG_GETENV);"ATE";chr(127);         &
        :  input "",AS'PROFILE
  
        ! Transfer file to default local directory
        ? TAB(-10,AG_FTP);"0"+AS'LOCPATH;chr(126);      &
          AS'PROFILE+"\"+AS'FILNAM+"."+AS'EXT;chr(127);
        xcall ACCEPN,A
 
        ! Erase Print File from Server Side
        KILL GOTOPP
  
        RETURN
Hi Joe,

There are several ways to skin this cat. If you're willing to do a little bit of setup, then the simplest approach from the program standpoint would be to just create a print queue that did what you wanted. That way you could use XCALL SPOOL, file$, printer$ in all cases, and just vary the printer$ according to the action desired.

To create a printer on the server side (call it ATEDISK) that sends the file to the user's PC in a specified directory, create this file on the server in [1,7] ...

Code
    ;ATEDISK.PQI
    DEVICE = AUXLOC:ATEDISK
and this file on the user's PC in the 001007 directory within the ATE installation tree...

Code
    ;ATEDISK.PQI
    DEVICE = DISK:%MIAME%\printfiles
When you spool a file to the ATEDISK printer on the server, the server's ATEDISK.PQI would redirect it to the ATE printer called ATEDISK and then it would use the second init file above to redirect it to the specified directory. Note that we are using %MIAME% rather than %ATE% in this case because %ATE% only has meaning on the server side; on the client side, it's just %MIAME%, although likely that would be C:\ATE if you installed into the normal directory. (Obviously you could specify any local directory there after the "DEVICE = DISK:". See http://www.microsabio.net/dist/doc/conref/00ashref.htm#!devicedisk.htm for more info on the DISK: pseudo device.)

The only downside of this method is that you have to get the ATEDISK.PQI file to the client first (as a one-time operation). You could do that with a ZTXFER command which ran in your application startup, or perhaps from a utility menu. You could also make the spooler init file do that transfer by creating an SBX invoked via a COMMAND=SBX:xxx entry in the server-side printer init file. But in that case, you might as well just bypass the ATE-side printer definition and just transfer the print file, which would be another option. I don't have an off-the-shelf SBX for that, but it would be very simple to write one, in which case your printer init on the server would look something like...

Code
    COMMAND=SBX:TOPC.SBX,<optional parameters>
... where TOPC.SBX was the name of the print filter SBX that performs the transfer. (See http://www.microsabio.net/dist/doc/conref/00ashref.htm#!ashellprocessing.htm in the doc for details on print filters.)

Note that if you are dealing with a local A-Shell/Windows instance rather than an ATE session, the DEVICE=DISK: mechanism remains the same and you don't need to worry about the host-to-client transfer.

Yet another approach would be to just send the file to APEX, which automatically archives every print file it receives, in Documents\APEX. The user could still print it, or just close the viewer. Or, while viewing one file, you could click on the folder icon in the APEX toolbar and open up a previously archived print file. and let the user decide whether to print it or save it on their PC. Note that the files get -# suffixes so as to keep separate multiple instances of the same print file name. Also note that the archived files are retained for a period specified in the Settings > Preview Preferences dialog.
For this model, your server-side printer init file just needs:

Code
    DEVICE=AUXLOC:
    APEX=ON
(The APEX=ON is only there to force APEX on, in case it isn't on by default in the Preview Preferences.)

Yet another approach, which matches up more closely with your existing CPC method would to use XCALL AMOS to execute the ZTXFER.LIT command on the server to transfer the file, something like:

Code
    XCALL AMOS, "SYS:ZTXFER.LIT "+PRTFILE$+" %ATE%\printfiles", 0, 1
Note that we need to execute this in-process if we want the %ATE% environment variable to be recognized, hence the ,1 and the end. And executing LIT commands in-process generally requires the full filespec, i.e. with the SYS: and .LIT so AMOS doesn't think it could be a CMD, DO, or RUN. (For some reason, I had trouble with the above if I didn't set the qflag parameter to 0, not sure why.) You may want to append a /ATE to the "SYS:ZTXFER.LIT" to force it to use the ATE internal transfer channel rather than {S}FTP, since the latter is likely to be slower for simple printfiles and possibly have firewall or other configuration complications.

ZTXFER.LIT uses ATEAPX.SBX, which must be in the BAS: account. For less overhead, you could just XCALL it directly, i.e.

Code
    XCALL ATEAPX, PRTFILE$, "%ATE%\printfiles", "", 0, STATUS
Note that ATEAPX creates a log file, OPR:ATEAPX.LOG, which you may find useful.

(If that doesn't provide enough options, I can probably think of some others.)

P.S. As an aside, I don't think it is necessary to adjust the directory separators for Windows' sake. Under UNIX they definitely have to be "/", but I believe most Windows-related functions will accept them either way.