Ver la Versión Completa : [Duda] Impresión códigos de escape por CMD
Kuk
1 de mayo de 2017, 09:33
Las impresoras nunca han sido mi punto fuerte. Hace unos días uno de mis clientes se cambió a Windows 7 x64 y le dejó de funcionar mi DLL compilada en NetExpress 3.1 que imprimía los tickets.
La imresión se hacía de manera clásica:
SELECT PRINT-FILE
ASSIGN TO PRINTER WS-PUERTO
No logré hacerlo funcionar, siempre me daba FS=9. Luego encontré este artículo de MF, según el cual el Run-Time de NetExpress inferior a la versión 5.1 daba este problema: Runtime error 9/013 when attempting to print to LPTn: where the physical printer port is mapped via a NET USE statement on Windows 7 - Enterprise Server Knowledge Base - Enterprise Server - Micro Focus Community (https://community.microfocus.com/microfocus/mainframe_solutions/enterprise_server/w/knowledge_base/18441/runtime-error-9013-when-attempting-to-print-to-lptn-where-the-physical-printer-port-is-mapped-via-a-net-use-statement-on-windows-7)
También en ese artículo dicen de utilizar las rutinas para imprimir vía Windows, pero yo nunca las he usado: Demo - The PC_PRINTER library routines - Net Express/Server Express Knowledge Base - Net Express / Server Express - Micro Focus Community (https://community.microfocus.com/microfocus/cobol/net_express__server_express/w/knowledge_base/2621/demo-the-pc-printer-library-routines)
Así que para solucionar rápidamente el tema, lo que hice fue escribir en un fichero TXT y luego lanzar el comando siguiente en PowerCOBOL:
MOVE SPACES TO TICK-PRINT
STRING "CMD /c Type Print.txt>" LNK-PORT
DELIMITED BY SIZE INTO TICK-PRINT
INVOKE POW-SELF "Execute" USING TICK-PRINT POW-SWHIDE
Y funciona. El problema es que han dejado de funcionar los códigos de escape (apertura de cajón, y comandos de diferentes tamaños de letras).
¿A qué se debe esto, es por el tema de pasar por un TXT en vez de llamar directamente la impresora o se debe configurar la impresora de alguna forma particular?
Gracias de antemano por vuestras respuestas.
Dasije, Rapinto, Nitzer,
Nitzer
1 de mayo de 2017, 14:12
Yo utilizaba el dosprinter, hasta donde recuerdo, con el podias hacer de todo.
Rapinto
2 de mayo de 2017, 00:08
Kuk,
Tive esse problema e, se me recordo bem, tinha a ver com o ficheiro txt.
Não me recordo bem mas penso que tínhamos que utilizar o "LINE SEQUENTIAL" em vez
do SEQUENTIAL.
Um deles não aceita códigos escape.
Saludos,
Rui
Dasije
8 de mayo de 2017, 21:08
Yo en NetCOBOL tengo realizado una rutina para impresión RAW, es el modo de que no filtra los códigos de escape en la impresión.
Es un ejecutable que pasas parametro del archivo de texto y el nombre de la impresora en Windows.
Kuk
8 de mayo de 2017, 23:25
Dasije, estoy intentando armar lo mismo pero en una DLL. Pero tengo problemas que aún no he resulto. Dependiendo del entorno de dónde lo hago (estoy mirando en C++, en NetExpress y directamente en PowerCOBOL) tengo diferentes problemas.
La DLL hecha en C++ me da GetLastError 87 que quiere decir "Parámetro incorrecto". Aunque lo hago según el ejemplo de MSDN, pasando en OpenPrinterA el último parámetro como NULL.
En Power OpenPrinterA pasa bien pero no sé por qué razón en WrtiePrinter me da GetLastError 6 (Handle incorrecto)...
¿Puedes compartir el código de tu programa?
Rapinto, lo escribo desde el principio como LINE-SECUENCIAL que es la opción por omisión.
Dasije
9 de mayo de 2017, 00:23
@OPTIONS BINARY(BYTE)
IDENTIFICATION DIVISION.
PROGRAM-ID PRINT-RAW.
AUTHOR. Doug Brown.
INSTALLATION. FUJITSU COBOL (GENERIC).
SECURITY. COPYRIGHT (C) 1999 FUJITSU SOFTWARE CORPORATION.
*
* Program is passed a text file and printer name and prints the
* file to the printer. It is assumed that the text file may contain
* printer control characters and should be passed to the printer
* "as is" i.e. it is read as a sequential file and passed to the
* printer in blocks.
* The program is designed to be invoked from the command line, or
* from the Windows CreateProcess function, so that it executes
* asynchronously.
* Command line format is:
*
* FSC-SPOOL-FILE.EXE "Text file name" "Printer name"
*
* The quotes are only required if the text file or printer name
* includes spaces.
*-----------------------------------------------------------------
ENVIRONMENT DIVISION.
CONFIGURATION SECTION.
SOURCE-COMPUTER. WINDOWS.
OBJECT-COMPUTER. WINDOWS.
SPECIAL-NAMES.
ARGUMENT-NUMBER IS ARGUMENT-NUMBER
ARGUMENT-VALUE IS ARGUMENT-VALUE
SYMBOLIC CONSTANT
*> Program Copyright Information
PROGRAM-NAME IS "CBLEXEC"
PROGRAM-SOURCE-DATE IS "April 5 1999"
PROGRAM-SERIAL-NUMBER IS "DAB/FSC/000001"
PROGRAM-DESCRIPTION IS
"Fujitsu COBOL Spool Print File"
PROGRAM-COPYRIGHT IS
"Copyright (C) 1999 Fujitsu Software Corporation"
PROGRAM-AUTHOR IS "Doug Brown"
PROGRAM-BUILD-TYPE IS "PRODUCTION"
PROGRAM-CHARACTER-SET IS "ASCII"
PROGRAM-CHARACTER-TYPE IS "SBCS".
*-----------------------------------------------------------------
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT Print-File ASSIGN TO Print-File-Name
ORGANIZATION SEQUENTIAL
FILE STATUS IS Print-File-Status
.
DATA DIVISION.
FILE SECTION.
FD Print-File.
01 Print-Record PIC X(16384).
WORKING-STORAGE SECTION.
* Note: Ensure that Print-Buffer is always the same size
* as Print-Record
01 Print-Buffer PIC X(16384).
01 Print-File-Name PIC X(255) VALUE SPACES.
01 Print-File-Status PIC X(2).
01 Record-Bytes PIC 9(9) COMP-5.
01 Bytes-Written PIC 9(9) COMP-5.
01 Printer-Name PIC X(255) VALUE SPACES.
01 Printer-Handle PIC 9(9) COMP-5.
01 Return-Value PIC S9(9) COMP-5.
01 Doc-Info.
03 pDocName USAGE POINTER.
03 pOutputFile USAGE POINTER VALUE NULL.
03 pDatatype USAGE POINTER.
01 Datatype.
03 PIC X(3) VALUE "RAW".
03 PIC X VALUE X"00".
01 Number-of-Arguments PIC 9(2) COMP-5.
01 End-of-File-Flag PIC 9 VALUE ZERO.
88 END-OF-FILE VALUE 1.
01 Offset PIC 9(5) COMP-5.
01 PRINTER-d.
05 pDatatyp pic x(4) value low-value.
05 pDevMod pic x(4) value low-value.
05 DesiredAccess pic s9(9) comp-5 value 8.
*------------------------------------------------------------------
PROCEDURE DIVISION.
ACCEPT Number-of-Arguments FROM ARGUMENT-NUMBER
* DISPLAY Number-of-Arguments
IF Number-of-Arguments NOT = 2
* <<Check what action is appropriate to notify user of an error>>
DISPLAY "Argumentos incorrectos"
EXIT PROGRAM
END-IF
ACCEPT Print-File-Name FROM ARGUMENT-VALUE
ACCEPT Printer-Name FROM ARGUMENT-VALUE
* Find end of printer name and place a null byte to terminate
* the string.
MOVE FUNCTION LENG (Printer-Name) TO Offset
PERFORM UNTIL Printer-Name (Offset:1) NOT = SPACE
SUBTRACT 1 FROM Offset
END-PERFORM
ADD 1 TO Offset
MOVE X"00" TO Printer-Name (Offset:1)
* Set up the Doc-Info structure for use with the StartDocPrinter
* function.
MOVE FUNCTION ADDR (Print-File-Name) TO pDocName
MOVE FUNCTION ADDR (Datatype) TO pDatatype
* Open the printer.
* <<Insert explanation as to why some functions are called with the
* "A" appended and others are not.>>
CALL "OpenPrinterA" WITH STDCALL
USING BY REFERENCE Printer-Name
BY REFERENCE Printer-Handle
BY VALUE 0
RETURNING Return-Value.
IF Return-Value = 0
DISPLAY "Error en la apertura de la impresora"
EXIT PROGRAM
END-IF
CALL "StartDocPrinterA" WITH STDCALL
USING BY VALUE Printer-Handle
BY VALUE 1
BY REFERENCE Doc-Info
RETURNING Return-Value
IF Return-Value = 0
DISPLAY "Problema de iniciar el documento a imprimir"
EXIT PROGRAM
END-IF
CALL "StartPagePrinter" WITH STDCALL
USING BY VALUE Printer-Handle
RETURNING Return-Value
IF Return-Value = 0
DISPLAY "Problema iniciar página de impresión"
EXIT PROGRAM
END-IF
OPEN INPUT Print-File
IF Print-File-Status NOT = "00"
DISPLAY "No se puede abrir el archivo de impresión"
EXIT PROGRAM
END-IF
* Ensure Print-Record area is initialized to nulls
MOVE LOW-VALUES TO Print-Record
MOVE FUNCTION LENG (Print-Buffer) TO Record-Bytes
* Read ahead so that last record can be detected
READ Print-File
AT END
DISPLAY "No hay datos para imprimir en el fichero"
EXIT PROGRAM
END-READ
IF Print-File-Status NOT = "00"
DISPLAY "Error lectura archivo de impresión (1): " Print-File-Status
EXIT PROGRAM
END-IF
* Move record to buffer so that Print-Record is available for
* the next read
MOVE Print-Record TO Print-Buffer
PERFORM UNTIL END-OF-FILE
* Set Print-Record to LOW-VALUES before reading
MOVE LOW-VALUES TO Print-Record
READ Print-File
AT END
* Last read had the last record, so find last non-null
* byte in record (only want to pass the data in the file
* not the padding nulls at the end of the buffer)
SET END-OF-FILE TO TRUE
MOVE FUNCTION LENG (Print-Buffer) TO Offset
PERFORM UNTIL Print-Buffer (Offset:1) NOT = X"00"
SUBTRACT 1 FROM Offset
END-PERFORM
MOVE Offset TO Record-Bytes
END-READ
IF Print-File-Status = "00"
OR
Print-File-Status = "10" *> At end status
CALL "WritePrinter" WITH STDCALL
USING BY VALUE Printer-Handle
BY REFERENCE Print-Buffer
BY VALUE Record-Bytes
BY REFERENCE Bytes-Written
RETURNING Return-Value
IF Return-Value = 0
DISPLAY "Error imprimir en la impresora"
SET END-OF-FILE TO TRUE
END-IF
ELSE
DISPLAY "Error lectura archivo de impresión (2): " Print-File-Status
SET END-OF-FILE TO TRUE
END-IF
IF NOT END-OF-FILE
* Set up next record to print
MOVE Print-Record TO Print-Buffer
END-IF
END-PERFORM
CLOSE Print-File
CALL "EndPagePrinter" WITH STDCALL
USING BY VALUE Printer-Handle
RETURNING Return-Value
CALL "EndDocPrinter" WITH STDCALL
USING BY VALUE Printer-Handle
RETURNING Return-Value
CALL "ClosePrinter" WITH STDCALL
USING BY VALUE Printer-Handle
RETURNING Return-Value
STOP RUN.
fastpho
9 de mayo de 2017, 00:25
Kuk, yo lo trabajo de la siguiente manera y funciona en cualquier entorno:
SELECT IMPRE
ASSIGN TO FPRINT
ORGANIZATION IS LINE SEQUENTIAL
FILE STATUS IS IMP-STAT.
* ================================================== ==========
* REG-IMPRESOR .
* ================================================== ==========
FD IMPRE IS GLOBAL.
01 REG-IMPRE PIC X(40).
01 REG-IMPRE-1 PIC X(40).
WORKING-STORAGE SECTION.
01 DATA00 PIC X(40) VALUE SPACES.
* Define the work area for getting the current time.
01 LINEA-4.
03 FILLER PIC X(6) VALUE "Fecha:".
03 L4-DD PIC 99.
03 FILLER PIC X VALUE "-".
03 L4-MM PIC 99.
03 FILLER PIC X VALUE "-".
03 L4-SG PIC 99.
03 L4-AA PIC 99.
03 FILLER PIC X(8) VALUE SPACES.
03 FILLER PIC X(6) VALUE "Hora :".
03 L4-H PIC 99.
03 FILLER PIC X VALUE ":".
03 L4-M PIC 99.
01 LINEA-5.
03 FILLER PIC X(2) VALUE SPACES.
03 FILLER PIC X(20) VALUE "COMPROBANTE INTERNO".
01 LINEA-5-1.
03 FILLER PIC X(2) VALUE SPACES.
03 FILLER PIC X(22) VALUE "NO VALIDO COMO TICKET".
01 LINEA-6.
03 FILLER PIC X(7) VALUE "Caja :".
03 L6-NRO-POS PIC 9(3).
03 FILLER PIC X(2) VALUE SPACES.
03 FILLER PIC X(8) VALUE "T/F:".
03 L6-NRO-DOC PIC 999999.
03 FILLER PIC X(3) VALUE SPACES.
03 FILLER PIC X(4) VALUE "V :".
03 L6-NROVDR PIC 9(03).
01 LINEA-10-1.
03 FILLER PIC X(40) VALUE "Codigo Descripcion Precio".
* CORTA TICKET EN COMANDERA <ESC> "i"
01 M-3 IS GLOBAL.
03 M-3-1 PIC X VALUE X"1B".
03 M-3-2 PIC X VALUE X"69".
* esc p m t1 t2 abre cajon m: 0 o 1 t1 t2 segundos
01 M-4 IS GLOBAL.
03 M-4-1 PIC X VALUE X"1B".
03 M-4-2 PIC X VALUE X"70".
03 FILLER PIC X(3) VALUE "011".
PROCEDURE DIVISION.
DISP-REC SECTION.
MOVE "LPTTIC" TO FPRINT.
OPEN OUTPUT IMPRE. MOVE ZEROS TO W-ROW.
MOVE FUNCTION CURRENT-DATE TO LINEA-FECHA-AUX. MOVE L1-D TO L4-DD. MOVE L1-M TO L4-MM. MOVE L1-A TO L4-AA. MOVE L1-S TO L4-SG.
ACCEPT CURR-TIME FROM TIME. MOVE CURR-HH TO L4-H. MOVE CURR-MM TO L4-M.
IMPRIME-CABECERA.
MOVE SPACES TO DATA00. MOVE DATA00 TO REG-IMPRE. WRITE REG-IMPRE.
MOVE LINEA-5 TO DATA00. MOVE DATA00 TO REG-IMPRE. WRITE REG-IMPRE.
MOVE LINEA-5-1 TO DATA00. MOVE DATA00 TO REG-IMPRE. WRITE REG-IMPRE.
MOVE SPACES TO DATA00. MOVE DATA00 TO REG-IMPRE. WRITE REG-IMPRE.
*CORTAL PAPEL
MOVE M-3 TO REG-IMPRE. WRITE REG-IMPRE.
*ABRE CAJON.
MOVE M-4 TO REG-IMPRE. WRITE REG-IMPRE.
*//////////////////////////////////////////////////////////
CLOSE IMPRE.
INVOKE POW-SELF "Execute" USING "IMPRIME.BAT" POW-SWHIDE.
El bat lo que es hacer un copy sobre el puerto serie (com1,com2)
copy lpttic com1:
La impresora declarada en windows debe ser generic solo texto
Kuk
9 de mayo de 2017, 08:58
Dasije, ¿puedes pasarme las LIB-s también o usas el fichero COBOL85.CBR con OpenPrinterA=winspool.drv etc?
fastpho, actualmente estoy haciendo algo parecido pero no me funciona con los códigos de escape.
fastpho
9 de mayo de 2017, 14:41
Kuk te subo un ejemplo completo esta echo cobol97 a ver si te sirve
Dasije
10 de mayo de 2017, 16:48
En el rar que te ha pasado fastpho incluye la LIB.
Igualmente es la misma rutina que yo uso, solo que yo he separado y traducido lo que realmente me interesaba.
Saludos.
Kuk
10 de mayo de 2017, 17:55
Amigos, he aquí un "poltergeist" :D Los códigos de escape de antes siempre han funcionado, hasta que el cliente cambio de Windows. He mirado los códigos de escape en la página de Epson, y ahora aparecen otros, introduciendo los cuales todo ha vuelto a la normalidad. :yoquese:
No entiendo cómo es posible, tratándose de la misma impresora y los mismos controladores (provenientes del CD que vino con la impresora). :tonto:
vBulletin v3.8.7, Derechos ©2000-2026, Jelsoft Enterprises Ltd.