PDA

Ver la Versión Completa : [Sintaxis] Compratir variable con un EXE de PowerCOBOL


Recato53
9 de febrero de 2017, 16:44
Recato53, si no quieres que sea una DLL sino un EXE... :piensa: Puedes intentar hacer un MOVE al RETURN-CODE en el EXE, y en el programa llamante recibes dicho valor en el campo RETURNING. Pruébalo y nos cuentas.

Buenas tardes.

Según me indicas puedo programar RETURN-CODE y recogerlo con RETURNING, me puedes hacer llegar un ejemplo, no consigo que esto me funciones.

Muchas gracias.
Un saludo.

Kuk
9 de febrero de 2017, 17:33
Recato53, lo que puedes hacer es pasar un puntero de una variable en tu DLL que será recuperado por el EXE en la CMD-LINE.

Es decir, en tu DLL defines una variable y llamas al EXE:

WORKING-STORAGE SECTION.
01 EXT-INDICADOR PIC X(2).

PROCEDURE DIVISION.

INVOKE POW-SELF "ExecuteSync" USING EXT-INDICADOR

IF EXT-INDICADOR = "SI"
INVOKE POW-SELF "DisplayMessage"
USING "¡Hay conexión!" 64

ELSE
INVOKE POW-SELF "DisplayMessage"
USING "¡NO hay conexión!" 48
END-IF


En tu EXE que comprueba la conexión, en la WORKING Global defines:


01 GLB-CMD IS GLOBAL PIC X(260).
01 FILLER REDEFINES GLB-CMD
05 PTR-VAR IS GLOBAL POINTER.
05 FILLER PIC X(256).


Y en el evento "Opened" haces lo siguiente:


MOVE "CommandLine" OF POW-SELF TO GLB-CMD


En el evento "Click" de tu botón que llama a la rutina de comprobación de la conexión, añades la LINKAGE SECTION y mapeas la variable de retorno. Ejemplo:


ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 FUNC PIC X(20).
01 NUM1 PIC S9(9) COMP-5.
01 NUM2 PIC S9(9) COMP-5.
01 NUM3 PIC S9(9) COMP-5.
01 RESP PIC S9(9) COMP-5.

LINKAGE SECTION.
01 EXT-VARIABLE PIC X(2). *> <== VARIABLE COMPARTIDA
PROCEDURE DIVISION.

MOVE "mluser" TO FUNC

CALL FUNC WITH STDCALL USING BY VALUE NUM1
BY VALUE NUM2
BY VALUE NUM3
RETURNING RESP

SET ADDRESS OF EXT-VARIABLE TO PTR-VAR

IF RESP = ZEROS
MOVE "NO" TO EXT-VARIABLE

ELSE
MOVE "SI" TO EXT-VARIABLE
END-IF

Recato53
10 de febrero de 2017, 21:01
Buenas tardes KUK.
Muchisimas gracias por tu interés. He probado la programación que me indicas y no consigo que funcione.

Creo que me he explicado mal. Te cuento otra vez mi problema.

Tengo una DLL que llama a un EXE.
El programa EXE tiene que devolver un valor y desde la DLL recogerlo.

La programación de la DLL

WORKING-STORAGE SECTION.
01 EXT-VARIABLE PIC X(2).
PROCEDURE DIVISION.
PRINCIPAL SECTION.
INVOKE POW-SELF "ExecuteSync" USING "CONEXION.EXE" POW-SWNORMAL.
IF EXT-VARIABLE = "SI"
INVOKE POW-SELF "DisplayMessage" USING "¡Hay conexión!" 64
ELSE
INVOKE POW-SELF "DisplayMessage" USING "¡NO hay conexión!" 48
END-IF


La programación del programa EXE

WORKING-STORAGE SECTION.
*********************************
01 CONEXION PIC X(20).
01 FUNCION PIC X(24).
01 RESP PIC S9(9) COMP-5.
*********************************
01 GLB-CMD IS GLOBAL PIC X(260).
01 VALOR REDEFINES GLB-CMD GLOBAL.
05 PTR-VAR POINTER.
05 PIC X(256).
LINKAGE SECTION.
01 EXT-VARIABLE PIC X(2).
PROCEDURE DIVISION.
PRINCIPAL SECTION.
MOVE "CommandLine" OF POW-SELF TO GLB-CMD
MOVE "InternetCheckConnectionA" TO FUNCION
MOVE "http://www.google.es" TO CONEXION

CALL FUNCION WITH STDCALL USING
by reference CONEXION
by value 1
by value 0
returning RESP
END-CALL

SET ADDRESS OF EXT-VARIABLE TO PTR-VAR

IF RESP = ZEROS
MOVE "NO" TO EXT-VARIABLE
ELSE
MOVE "SI" TO EXT-VARIABLE
END-IF.


Cuando ejecuto el programa da un error.

Kuk
10 de febrero de 2017, 23:12
Recato53, pruebalo así:


ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 EXT-VARIABLE PIC X(2).
01 WS-PROGRAMA.
05 WS-NOMBRE PIC X(13) VALUE "CONEXION.EXE ".
05 WS-PTR POINTER.

PROCEDURE DIVISION.

MOVE FUNCTION ADDR(EXT-VARIABLE) TO WS-PTR

INVOKE POW-SELF "ExecuteSync" USING WS-PROGRAMA POW-SWNORMAL.

IF EXT-VARIABLE = "SI"
INVOKE POW-SELF "DisplayMessage" USING "¡Hay conexión!" 64

ELSE
INVOKE POW-SELF "DisplayMessage" USING "¡NO hay conexión!" 48
END-IF

Recato53
11 de febrero de 2017, 10:50
Buenos días.

Sique sin funcionar estos programas.
Donde se produce el ERROR es en código del programa.EXE, hay algo que no esta correctamente programado y no encuentro lo que es.

Muchas gracias

Un saludo.

Kuk
11 de febrero de 2017, 19:32
Recato53, ahora que lo pienso es normal... :tonto: Estamos compartiendo memoria en 2 procesos diferentes, y esto no es posible. Para ello hay que reservar de la memoria compartida (shared memory) que es independiente y se controla por el SO.

Si sigues queriendo hacerlo así puedo mirar cómo se hace, habrá que llamar unas API-s de Windows. Pero en realidad, me sigue pareciendo lo más fácil


sea crear un fichero CONEXION.COB e importarlo en cada módulo (EXE/DLL) del proyecto donde lo necesites, luego hacer un CALL vulgar y corriente.
sea dejarlo todo igual salvo que en vez de un EXE que sea una DLL que se abrirá con CallForm o OpenForm.

Recato53
12 de febrero de 2017, 10:52
Me gustaría que se pudiera hacer como inicialmente me comentaste.

Ahora lo tengo resuelto con un archivo Temp.

En el programa EXE creo un archivo Temp con los valores que me interesan.
En la DLL abro el archivo Temp y leo los valores.

Es una solución un poco rudimentaria, pero funciona.

Un saludo.

Kuk
12 de febrero de 2017, 18:19
Recato53, aquí tienes lo que necesitas, lo he comprobado y funciona. En realidad es un ejemplo de cómo compartir memoria entre 2 procesos.

En el programa llamante hacemos:


ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 hMapFile BINARY-LONG.
01 ADR POINTER.
01 nADR REDEFINES ADR
PIC S9(9) COMP-5.
01 LastError PIC S9(9) COMP-5.

LINKAGE SECTION.
01 InternetRC PIC S9(4) COMP-5.

PROCEDURE DIVISION.

*> CREAMOS LA MEMORIA
CALL "CreateFileMappingA" WITH STDCALL USING BY VALUE -1 *> INVALID_HANDLE_VALUE
BY VALUE 0 *> NULL
BY VALUE 4 *> PAGE_READWRITE
BY VALUE 0
BY VALUE 4 *> TAMAÑO MEMORIA EN BYTES
BY CONTENT "VarComp" & X"00" *> NOMBRE DE LA MEMORIA
RETURNING hMapFile

*> COMPROBAMOS LA REFERENCIA
IF hMapFile = ZEROS
INVOKE POW-SELF "DisplayMessage"
USING "Error creando Memoria Compartida" 16

EXIT PROGRAM
END-IF

*> OBTENEMOS EL PUNTERO
CALL "MapViewOfFile" WITH STDCALL USING BY VALUE hMapFile
BY VALUE H"0F001F" *> FILE_MAP_ALL_ACCESS
BY VALUE 0
BY VALUE 0
BY VALUE 4 *> TAMAÑO MEMORIA EN BYTES
RETURNING ADR


*> SI NO HEMOS OBTENIDO EL PUNTERO, MIRAMOS POR QUE
IF ADR = NULL
CALL "GetLastError" WITH STDCALL RETURNING LastError

INVOKE POW-SELF "DisplayMessage"
USING "Error creando Memoria Compartida" LastError 16

CALL "CloseHandle" WITH STDCALL USING BY VALUE hMapFile

ELSE
*> SI TENEMOS EL PUNTERO, MAPEAMOS A LA VARIABLE
SET ADDRESS OF InternetRC TO ADR
END-IF

MOVE POW-FALSE TO "Enabled" OF CmCommand1

INVOKE POW-SELF "ExecuteSync" USING "INTERNET.EXE"

MOVE POW-TRUE TO "Enabled" OF CmCommand1

IF InternetRC = 1
INVOKE POW-SELF "DisplayMessage"
USING "¡Hay conexión a Internet!" 64

ELSE
INVOKE POW-SELF "DisplayMessage"
USING "NO hay conexión a Internet..." 48
END-IF

*> ELIMINAMOS LA MEMORIA CREADA
CALL "CloseHandle" WITH STDCALL USING BY VALUE hMapFile



En el programa llamado hacemos:


ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 hMapFile BINARY-LONG.
01 ADR POINTER.
01 nADR REDEFINES ADR
PIC S9(9) COMP-5.
01 LastError PIC S9(9) COMP-5.

01 CONEXION PIC X(30).
01 ST-INTERNET PIC S9(9) COMP-5.
01 FUNC PIC X(24).

LINKAGE SECTION.
01 InternetRC PIC S9(4) COMP-5.
PROCEDURE DIVISION.

MOVE "http://www.google.es" & X"00" TO CONEXION

MOVE "InternetCheckConnectionA" TO FUNC

CALL FUNC WITH STDCALL USING
by reference CONEXION
by value 1
by value 0
returning ST-INTERNET
END-CALL

*> ACCEDEMOS A LA MEMORIA CREADA
CALL "OpenFileMappingA" WITH STDCALL USING BY VALUE H"0F001F" *> FILE_MAP_ALL_ACCESS
BY VALUE 0
BY CONTENT "VarComp" & X"00" *> NOMBRE DE LA MEMORIA
RETURNING hMapFile

IF hMapFile = ZEROS
INVOKE POW-SELF "DisplayMessage"
USING "Error accediendo a la Memoria Compartida" 16

EXIT PROGRAM
END-IF

*> OBTENEMOS EL PUNTERO
CALL "MapViewOfFile" WITH STDCALL USING BY VALUE hMapFile
BY VALUE H"0F001F" *> FILE_MAP_ALL_ACCESS
BY VALUE 0
BY VALUE 0
BY VALUE 4
RETURNING ADR

IF ADR = NULL
CALL "GetLastError" WITH STDCALL RETURNING LastError

INVOKE POW-SELF "DisplayMessage"
USING "Error obteniendo puntero de Memoria Compartida" LastError 16

ELSE
SET ADDRESS OF InternetRC TO ADR

MOVE ST-INTERNET TO InternetRC
END-IF


Incluyo el proyecto por si a caso ;)

Recato53
12 de febrero de 2017, 19:00
El archivo .rar, se descarga con una extensión que no se puede descomprimir.

Kuk
12 de febrero de 2017, 19:20
Recato53, a mi me funciona... De todos modos, simplemente renombralo en INTERNET.rar a mano.

Recato53
14 de febrero de 2017, 17:18
Funciona correctamente. Muchas gracias
Implementare esta solución en algunos procesos que tenia con ficheros temporales.