Un EXE que no respeta los parámetros de entrada??

209 views
Skip to first unread message

Fernando D. Bozzo

unread,
Dec 22, 2013, 6:04:33 PM12/22/13
to publice...@googlegroups.com
[Reposteo por un error]
Hola:

Me acabo de encontrar un error extrañísimo, haber si alguien sabe algo. Resulta que si hago esta llamada desde un PRG en modo Desarrollo, el PRG recibe los 8 parámetros (los marco en colores para que se diferencien):


DO tst.prg WITH "MERGE", "C:\Temp\\80115cd9-7b28-40db-b324-f108b0fcaaad.pjx", "c:\DESA\foxbin2prg\foxbin2prg.pjx", "c:\DESA\foxbin2prg\foxbin2prg.pjx#/main/Soporte_MNXcs107", "c:\DESA\foxbin2prg\foxbin2prgpjx/main#cs110", "C:\Temp\b3894431-a073-4ada-8eb9-2f0e80a760b4.pjx", "c:\DESA\foxbin2prg\foxbin2prgpjxmainv115p1cs", "C:\Temp\\9b139b4b-f99b-443a-9f09-46881abb6be5.pjx"

Sí, ya sé que parece raro, pero son parámetros de un merge con nombres temporales


En cambio si hago la misma llamada desde un EXE (el PRG de antes compilado) desde el shell de Windows me devuelve un error:

C:\tst.exe "MERGE" "C:\Temp\\80115cd9-7b28-40db-b324-f108b0fcaaad.pjx" "c:\DESA\foxbin2prg\foxbin2prg.pjx" "c:\DESA\foxbin2prg\foxbin2prg.pjx#/main/Soporte_MNXcs107" "c:\DESA\foxbin2prg\foxbin2prgpjx/main#cs110" "C:\Temp\b3894431-a073-4ada-8eb9-2f0e80a760b4.pjx" "c:\DESA\foxbin2prg\foxbin2prgpjxmainv115p1cs" "C:\Temp\\9b139b4b-f99b-443a-9f09-46881abb6be5.pjx"


Y el error es este, que no se puede capturar:
El comando contiene una frase o palabra clave no reconocida.


El PRG es este, por si alguien quiere hacer el EXE para reproducirlo:

*-- TST.PRG
PARAMETERS p1
,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14,p15,p16,p17,p18,p19,p20,p21,p22,p23,p24,p25
MESSAGEBOX
( "PCOUNT=" + TRANSFORM(PCOUNT()) )
RETURN


Se puede compilar con esto:

BUILD PROJECT tst.pjx FROM tst.prg
BUILD EXE tst.exe from tst.pjx RECOMPILE


¿Alguien tiene idea de porqué a Fox no le gustan estos parámetros cuando se mandan al EXE y porqué tiene que inspeccionar que hay en ellos??

Gracias :-(

Fernando D. Bozzo

unread,
Dec 22, 2013, 6:33:53 PM12/22/13
to publice...@googlegroups.com
Es peor todavía, si le paso un único parámetro PCOUNT() devuelve 0

C:\>tst.exe "c:\DESA\foxbin2prg\foxbin2prg.pjx#/main/Soporte_MNX#cs:107c:\DESA\foxbin2prg\foxbin2prg.pjx#/main#cs:110C:\Temp\\b3894431-a073-4ada-8eb9-2f0e80a760b4.pjxc:\DESA\foxbin2prg\foxbin2prg.pjx#/main/v1.15p1#cs:100C:\Temp\\9b139b4b-f99b-443a-9f09-46881abb6be5.pjx"

No me esperaba esto de Fox :'(

HernanCano

unread,
Dec 22, 2013, 6:47:20 PM12/22/13
to publice...@googlegroups.com
Fernando:
He creado un .BAT que voy ejecutando con un parámetro, con dos, etc.... y cuando llego al sexto, me marca error.

Lo único que veo es que hasta el quinto ya son 256 caracteres.

Fernando D. Bozzo

unread,
Dec 22, 2013, 7:04:04 PM12/22/13
to publice...@googlegroups.com
Justamente, un BAT los captura todos (tengo uno) y el PRG desde la ventana de comandos también, pero el EXE no!
Estaba haciendo un parser y de pronto veía que no me llegaban todos los parámetros, y probando me encontré con esto.
Que mal! Y lo peor es que ahora mismo no se me ocurre como resolverlo, ya que los parámetros no los puedo modificar, porque vienen de una herramienta SCM.
Me voy a dormir, a ver si mañana se me ocurre algo.

Gracias.

Marco Plaza

unread,
Dec 22, 2013, 7:22:05 PM12/22/13
to publice...@googlegroups.com
Hola Fernando, los parámetros deben separase por espacios , y siempre se envían como cadenas de texto.

Aquí te mando el enlace a la solución explicada en detalle y código de ejemplo:

http://www.berezniker.com/content/pages/visual-foxpro/how-pass-parameters-vfp-exe

Saludos

Ricardo Pina

unread,
Dec 22, 2013, 7:23:28 PM12/22/13
to Grupo VFP
Hola Fernando

Bueno, si la almohada no te da una solución te doy una idea mientras se te ocurre algo mejor
En vez de pasar todos los parámetros (veo que puden ser muchos) puedes irlos adjuntando en un txt y luego solo pasas el txt como parámetro.

Saludos
--
            

                   Ricardo Pina

Desarrollo y Servicios Informáticos

                  Profesionales
               www.dsip.com.ar

 

 

Daniel Sánchez

unread,
Dec 22, 2013, 11:27:14 PM12/22/13
to Comunidad de Visual Foxpro en Español

Se me ocurrió lo mismo que ha Ricardo Pina, un archivo de texto conteniendo los datos que necesitas o un archivo ini o una tabla con los datos en campo memo y el lugar de pcount abrirías la tabla y un reccount para saber con cuantos parámetros trabajarías..

Saludos

Fernando D. Bozzo

unread,
Dec 23, 2013, 2:57:04 AM12/23/13
to publice...@googlegroups.com
Hola Marco:

En los ejemplos que puse, las partes que corresponden a la ejecución desde el EXE tienen los parámetros delimitados por " (comillas dobles), justamente porque pueden contener espacios dentro.

En el primer ejemplo el EXE recibe la misma cantidad de parámetros que el PRG, y en el segundo ejemplo el EXE recibe un único parámetro con todo en uno y PCOUNT() dice 0!

Por lo que veo Fox tiene algún problema cuando dentro de esos parámetros recibe combinaciones especiales de caracteres o se hace lío interpretándolas, ya que en distintas pruebas obtengo distintos resultados, desde el error que puse hasta que solo me reconozca algunos parámetros del inicio y saltee el resto.

Además todo está muy por debajo de los límites de variables que soporta Fox, que es 16 MB en una variable o 8 KB en una única línea de comando. Si tomo la llamada al EXE con sus parámetros, la longitud es muy inferior a esos 8192 caracteres.

Fernando D. Bozzo

unread,
Dec 23, 2013, 3:01:56 AM12/23/13
to publice...@googlegroups.com
Hola Ricardo:

Los parámetros realmente no superan los 8, y cada uno, como se ve en los ejemplos coloreados, está por debajo de los 256 caracteres, así que está todo muy por debajo de los límites de Fox, y en la documentación no veo que se mencione ninguna restricción al respecto.

Lo de pasarlos a un TXT quisiera evitarlo, porque implicaría tener que escribir al disco, luego leer desde el disco y luego borrar el archivo temporal, lo que son 3 accesos a disco por cada archivo que el SCM me entregue y sólo para tratar los parámetros.

Voy a seguir buscando opciones que en lo posible sean solo en memoria, pero si encuentro veo ninguna es probable que pruebe tu opción.

Gracias!

HernanCano

unread,
Dec 23, 2013, 4:25:26 AM12/23/13
to publice...@googlegroups.com
Disculpa, Fernando.

Probablemente no viste el segundo renglón de mi mensaje; si sí lo viste, Ok. ignóra éste.

Lo único que veo es que hasta el quinto ya son como 250 caracteres.

Considero que hay algún límite.

Fernando D. Bozzo

unread,
Dec 23, 2013, 4:31:07 AM12/23/13
to publice...@googlegroups.com
Hola Hernán, parece que estás en lo cierto. Acabo de leer en otros foros que alguien menciona algo que dijo Tammar Granor sobre un límite cercano a los 240 caracteres desde la línea de comandos DOS.

No entiendo cómo pueden haber puesto un límite así de corto para Fox, cuando un simple BAT recibe lo que le mandes sin problemas.

En fin, una solución probable que debería funcionar es hacer un archivo WSH (o VBS) que instancie mi objeto FoxPro y le mande los parámetros directamente. Al final voy a tener que depender de otro archivo más.

Intenté buscar a ver si había alguna rutina Win32 que me devuelva la llamada completa hecha desd la ventana de comandos, pero por ahora no encontré nada.

Gracias!

Fernando D. Bozzo

unread,
Dec 23, 2013, 4:33:08 AM12/23/13
to publice...@googlegroups.com
... lo de instanciar el objeto FoxPro no va a poder ser, ya que solo puede instanciar objetos COM+ que se deben registrar.

Que horrible esto.

Fernando D. Bozzo

unread,
Dec 23, 2013, 5:13:34 AM12/23/13
to publice...@googlegroups.com
Acabo de encontrar esto en la ayuda, pero parece que aplica al revés también:

RUN|! command string is too long (Error 1411)

The command string included with the RUN command is too long. The maximum length allowed is approximately 240 characters.

Guillermo Gimenez

unread,
Dec 23, 2013, 5:30:51 AM12/23/13
to publice...@googlegroups.com
Fer, te escribi un correo privado a fdb...@gmail.com, solo quería confirmar si te llego. Gracias

Saludos
Guille
--------------------------------------------
El lun 23-dic-13, Fernando D. Bozzo <fdb...@gmail.com> escribió:

Asunto: Re: [vfp] Re: Un EXE que no respeta los parámetros de entrada??
Para: publice...@googlegroups.com
Fecha: lunes, 23 de diciembre de 2013, 7:13

Guillermo Gimenez

unread,
Dec 23, 2013, 5:32:29 AM12/23/13
to publice...@googlegroups.com
jajaja... ahi me llego tu respuesta. Gracias!
--------------------------------------------
El lun 23-dic-13, Guillermo Gimenez <guille...@yahoo.com.ar> escribió:

Asunto: Re: [vfp] Re: Un EXE que no respeta los parámetros de entrada??
Para: publice...@googlegroups.com
Fecha: lunes, 23 de diciembre de 2013, 7:30

Mario López

unread,
Dec 23, 2013, 10:05:16 AM12/23/13
to publice...@googlegroups.com
@Fernando: no es lo ideal, pero probé así y funciona:

* Obtengo la linea completa de comandos
* Adaptado de http://www.news2news.com/vfp/?example=51&function=78

PARAMETERS p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14,p15,p16,p17,p18,p19,p20,p21,p22,p23,p24,p25

DECLARE INTEGER GetCommandLine IN kernel32
DECLARE INTEGER GlobalSize IN kernel32;
    INTEGER hMem

DECLARE RtlMoveMemory IN kernel32;
As CopyMemory;
    STRING @Destination, INTEGER Source,;
    INTEGER nLength

sPar = ""
FOR nPar = 1 TO 25
    xPar = EVALUATE([p] + TRANSFORM(nPar))
    IF ! EMPTY(xPar)
        sPar = sPar + " " + xPar
    ENDIF
NEXT

CLEAR
? "Parametros desde PARAMETERS: " + sPar

nAddress = GetCommandLine()  && returns an address in memory
nBufsize = GlobalSize(nAddress)

* allocating and filling a buffer
IF nBufsize <> 0
    sBuffer = REPLICATE(CHR(0), nBufsize)
    = CopyMemory(@sBuffer, nAddress, nBufsize)
ENDIF

sBuffer = STRTRAN(sBuffer, CHR(0), "")
? "Parametros desde GetCommandLine: " + sBuffer

WAIT WINDOW "Pulse Enter para salir"

RETURN

***

El EXE lo tuve que llamar de una manera no muy estándar:
_getcommandline "'MERGE' 'C:\Temp\\80115cd9-7b28-40db-b324-f108b0fcaaad.pjx' 'c:\DESA\foxbin2prg\foxbin2prg.pjx' 'c:\DESA\foxbin2prg\foxbin2prg.pjx#/main/Soporte_MNXcs107' 'c:\DESA\foxbin2prg\foxbin2prgpjx/main#cs110' 'C:\Temp\b3894431-a073-4ada-8eb9-2f0e80a760b4.pjx' 'c:\DESA\foxbin2prg\foxbin2prgpjxmainv115p1cs' 'C:\Temp\\9b139b4b-f99b-443a-9f09-46881abb6be5.pjx'"

Por si no se ven bien las comillas, encomillo TODOS los parámetros entre comillas dobles, y después cada parámetro entre comillas simples; desde VFP esta cadena la tendría que evaluar con algo así como EVAL + GETWORDNUM para obtener cada parámetro individual.

HTH
Mario
----

Carlos Boemo

unread,
Dec 23, 2013, 10:07:46 AM12/23/13
to publice...@googlegroups.com
C:\Temp\\ las 2 barras?

Fernando D. Bozzo

unread,
Dec 23, 2013, 10:19:16 AM12/23/13
to publice...@googlegroups.com
Es correcto Carlos, el SCM me lo devuelve así, y yo le quito la barra sobrante. No sé porqué será.

Fernando D. Bozzo

unread,
Dec 23, 2013, 10:21:31 AM12/23/13
to publice...@googlegroups.com
Hola Mario, parece buena tu solución y la voy a probar ahora.

Mientras tanto me había hecho un vbscript para llamar a mi EXE, que aunque no me guste la idea de meter un tercero de por medio, era un único acceso al disco.
Lo dejo por si a alguien le sirve y para que vean como funciona:

Dim WSHShell
Dim oVFP9, nExitCode, cEXETool, cCMD, nDebug
Set WSHShell = WScript.CreateObject("WScript.Shell")
Set oVFP9 = CreateObject("VisualFoxPro.Application.9")
nExitCode
= 0
nDebug
= 0

If WScript.Arguments.Count = 0 Then
    nExitCode
= 1
   
MsgBox "Sin parámetros"
Else
   
If nDebug = 1 Then
        cEXETool    
= Replace(WScript.ScriptFullName, WScript.ScriptName, "tst_diff.bat")
        cCMD        
= chr(34) & cEXETool & chr(34) & " " & chr(34) & WScript.Arguments(0) & chr(34)
   
Else
        cEXETool    
= Replace(WScript.ScriptFullName, WScript.ScriptName, "foxpro_plasticscm_dm.exe")
        cCMD        
= "DO " & chr(34) & cEXETool & chr(34) & " WITH " & chr(34) & WScript.Arguments(0) & chr(34)
   
End If


   
For I = 1 To WScript.Arguments.Count - 1
       cCMD    
= cCMD & "," & chr(34) & WScript.Arguments(I) & chr(34)
   
Next

   
If nDebug = 1 Then
       
MsgBox cCMD, 0, "PARÁMETROS ENVIADOS"
       
WSHShell.Run( cCMD )
   
Else
        oVFP9
.DoCmd( cCMD )
        nExitCode
= oVFP9.Eval("_SCREEN.ExitCode")
   
End If
End If

WScript.Quit(nExitCode)



Pruebo lo tuyo y te comento.

Saludos.-

Fernando D. Bozzo

unread,
Dec 23, 2013, 11:06:21 AM12/23/13
to publice...@googlegroups.com
Mario... ESPECTACULAR!! Funciona de lujo y me evita llamar a otro programa.

Este fué mi programa de prueba, que ahora parece un 4x4, donde cuando recibe los parámetros normales los usa, y cuando no los recibe pone la doble tracción (tu rutina) :-)


LPARAMETERS p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14,p15,p16,p17,p18,p19,p20,p21,p22,p23,p24,p25

#DEFINE CR CHR(13)
SET SAFETY OFF

TRY
    LOCAL lsBuffer
, lnAddress, lnBufsize, lnPcount
    lnPcount    
= PCOUNT()
   
    IF lnPcount
= 0    && Fox no los ve... pero están ahí :)

       
* Obtengo la linea completa de comandos
       
* Adaptado de http://www.news2news.com/vfp/?example=51&function=78

        DECLARE INTEGER
GetCommandLine IN kernel32
        DECLARE INTEGER
GlobalSize IN kernel32 INTEGER hMem
        DECLARE
RtlMoveMemory IN kernel32 As CopyMemory STRING @Destination, INTEGER Source,
INTEGER nLength

        lnAddress
= GetCommandLine()  && returns an address in memory
        lnBufsize
= GlobalSize(lnAddress)

       
* allocating and filling a buffer
        IF lnBufsize
<> 0
            lsBuffer
= REPLICATE(CHR(0), lnBufsize)
           
= CopyMemory(@lsBuffer, lnAddress, lnBufsize)
        ENDIF

        lsBuffer
= CHRTRAN(lsBuffer, CHR(0)+'"', " ")

        FOR I
= 1 TO OCCURS("'", lsBuffer) / 2
            STORE STREXTRACT
(lsBuffer, "'", "'", I*2-1, 0) TO ([p] + TRANSFORM(I))
            lnPcount    
= lnPcount + 1
        ENDFOR
       
        RELEASE lsBuffer
, lnAddress, lnBufsize
    ENDIF


    LOCAL loEx AS EXCEPTION
    MESSAGEBOX
( "Pcount=" + TRANSFORM(PCOUNT()) ;
       
+ CR + 'p1=(' + TRANSFORM(LEN(EVL(p1,''))) + ') ' + EVL(p1,'') ;
       
+ CR + 'p2=(' + TRANSFORM(LEN(EVL(p2,''))) + ') ' + EVL(p2,'') ;
       
+ CR + 'p3=(' + TRANSFORM(LEN(EVL(p3,''))) + ') ' + EVL(p3,'') ;
       
+ CR + 'p4=(' + TRANSFORM(LEN(EVL(p4,''))) + ') ' + EVL(p4,'') ;
       
+ CR + 'p5=(' + TRANSFORM(LEN(EVL(p4,''))) + ') ' + EVL(p5,'') ;
       
+ CR + 'p6=(' + TRANSFORM(LEN(EVL(p4,''))) + ') ' + EVL(p6,'') ;
       
+ CR + 'p7=(' + TRANSFORM(LEN(EVL(p4,''))) + ') ' + EVL(p7,'') ;
       
+ CR + 'p8=(' + TRANSFORM(LEN(EVL(p5,''))) + ') ' + EVL(p8,'') )

CATCH TO loEx
    MESSAGEBOX
( loEx.MESSAGE,0+16+4096,"Error",30000 )
ENDTRY

RETURN


Mil gracias!




El lunes, 23 de diciembre de 2013 16:05:16 UTC+1, Mario López escribió:

Mario López

unread,
Dec 23, 2013, 11:15:19 AM12/23/13
to publice...@googlegroups.com
@Fernando: me alegro que funcione, y gracias a vos por colaborar con toda la comunidad VFP con tus herramientas,
yo solo aporté mi granito de arena :)

Saludos y Felices Fiestas!
Mario
---

HernanCano

unread,
Dec 23, 2013, 1:59:04 PM12/23/13
to publice...@googlegroups.com
Listo, Fernando. Muy bien!!!

¿Me recuerdas cómo el la llamada, la ejecución del .EXE que funciona bien?

Fernando D. Bozzo

unread,
Dec 23, 2013, 2:21:47 PM12/23/13
to publice...@googlegroups.com
Hernán, no entiendo tu pregunta. Estás respondiendo sobre la solución, el código está ahí mismo.

Si me decís cuál es tu duda exactamente seguro que puedo decirte algo más.

Además el mensaje está marcado como solución, por lo que en el acceso por la web (no correo), se ve con una ventana verde que no podés dejar de ver :-)

HernanCano

unread,
Dec 23, 2013, 2:33:32 PM12/23/13
to publice...@googlegroups.com

>>> (solucionado) .... se ve con una ventana verde que no podés dejar de ver...

Sí, correcto.

>>>... la solución, el código está ahí mismo...

Está bien.... no lo analicé adecuadamente.

Fernando D. Bozzo

unread,
Dec 23, 2013, 2:49:25 PM12/23/13
to publice...@googlegroups.com
Hernán, igualmente, y por si quedan dudas, te hago un resumen del problema.

Resulta que estoy haciendo un programa que hace de interfaz entre una herramienta SCM (Plastic, control de código fuente) y FoxBin2prg para cuando elijo hacer un Diff (ver diferencias entre 2 versiones de un archivo) o un Merge (mezclar cambios de 2 versiones) sobre binarios de Fox (pjx,vcx,scx,frx,lbx,etc) me regenere automáticamente las versiones texto o binarias según sea conveniente. Para esto, al momento de elegir alguna de esas 2 operaciones la herramienta SCM me devuelve como parámetros los nombres de los archivos de origen, destino, base y otros enlaces simbólicos (los que tienen los caracteres raros del ejemplo que puse al principio), y con estos parámetros debo llamar a mi programa interfaz del Diff/Merge.
El problema era que mi programa FoxPro no recibía bien esos parámetros, o recibía una parte o daba errores, por lo que descubrí, con ayuda del foro, que FoxPro tiene un límite de longitud total de parámetros (todos sumados) de aproximadamente 240 caracteres para las llamadas a un EXE ejecutado con el equivalente al comando RUN de Fox, y entonces se comenzaron a dar ideas de como resolver esta limitación, se barajó la posibilidad de :
- Guardar los parámetros en un archivo y luego leer ese archivo
- De ejecutar un segundo programa tipo script (vbscript) de Windows que recibe los parámetros sin problemas y desde el que podía re-enviar esos parámetros al ejecutable cargando mi programa mediante automatización de VisualFoxPro.Application
- Finalmente la mejor solución la aportó Mario, mediante unas llamadas a funciones Win32 que me permiten leer los parámetros independientemente de lo que reciba Fox en los suyos, y de ahí que la rutina define las funciones y sobreescribe los parámetros dentro del CASE obteniéndolos del buffer lsBuffer, que es un string que contiene todos los parámetros delimitados por comillas simples, con lo cuál solo quedó parsear y asignar.

Espero que ahora quede más claro lo que pasó y como se resolvió. Si todavía hay alguna duda, preguntame.
Este hilo fue genial.


Saludos.-
Reply all
Reply to author
Forward
0 new messages