Reemplazo de WScript.Shell => run con Win32?

2,604 views
Skip to first unread message

Fernando D. Bozzo

unread,
Sep 11, 2015, 6:56:32 AM9/11/15
to Comunidad de Visual Foxpro en Español
Buenos días:

Alguien conoce una rutina que haga lo mismo que el método "run" de la clase "WScript.Shell" del Sistema Operativo?

El problema es que por falta de permisos para usar y ejecutar ese objeto, tengo que encontrar un equivalente que permita ejecutar un programa externo, esperar a que termine y devolver su respuesta (equivalente al ErrorLevel del DOS)

Tendría que ser algo que declare y use DLLs de Windows, y no puede ser el comando RUN de Fox, que no sirve para esto.


Gracias!

Fernando D. Bozzo

unread,
Sep 11, 2015, 6:59:57 AM9/11/15
to Comunidad de Visual Foxpro en Español
Agrego algo más:

ShellExecute() por sí mismo no permite controlar el retorno de la aplicación llamada, así que puede que tenga que una combinación de varias funciones DLL, como waitForSingleObject y similar, lo que lo haría algo complejo :-(

francisco prieto

unread,
Sep 11, 2015, 7:33:23 AM9/11/15
to publicesvfoxpro
Fernando,

Aca te dejo un tip, pero no creo que solucione tu problema

http://www.codeproject.com/Tips/507798/Differences-between-Run-and-Exec-VBScript

Este otro link, sea quizas la solucion, pero vas a tener que probar...

http://www.vbaccelerator.com/codelib/shell/shellex.htm

Saludos,

Pancho
Córdoba
Argentina

Fernando D. Bozzo

unread,
Sep 11, 2015, 7:35:03 AM9/11/15
to publice...@googlegroups.com
Hola Pancho:

El primero es un artículo que explica la diferencia entre Run y Exec, y el segundo es solo la función ShellExecute, que no espera.

Gracias igual!


Staff de Desarrollos EfiMax

unread,
Sep 11, 2015, 7:41:21 AM9/11/15
to publice...@googlegroups.com

Prueba con esto, haber si te funciona:

 

Function LaunchAppAndWait

    Lparameters tcCommandLine, tuFromDir, tcWindowMode

 

    *   tcCommandLine         (R) - command line to launch

    *   tuFromDir             (O) - Run from directory (default - CWD)

    *   tcWindowMode          (O) - Start Application Window mode, one of (HIDE, MIN, MAX, NOR)

    *                               (default - default setting of application)

 

    *   Returns:

    *   0 = CreateProcess didn't start what was asked

    *   1 = Process ran to completion

    *   -1= Process started but user aborted wait.  Danger - app is still running AFAIK

 

    #Define cnINFINITE        0xFFFFFFFF

    #Define cnHalfASecond 500 && milliseconds

    #Define cnTimedOut    0x0102

 

    *   We need some API calls, declare here

 

    *   GetCurrentProcess() returns the pseudohandle of the current process

    Declare INTEGER GetCurrentProcess IN WIN32API AS GetCurrProc

 

    *   WaitForIdleInput() waits until the target process is idle for input

    Declare INTEGER WaitForInputIdle IN WIN32API AS WaitInpIdle ;

       INTEGER nProcessHandle, ;

       INTEGER nWaitForDuration

 

    *   WaitForSingleObject() waits until the handle in parm 1 is signalled

    *   or the timeout period expires

    Declare INTEGER WaitForSingleObject IN WIN32API AS WaitOnAppExit ;

       INTEGER hProcessHandle, ;

       INTEGER dwTimeOut

 

    *   This API call does the work.  The parameters are as follows:

    *      lpszModuleName - ptr-> file name of module to execute.  Since we aren't launching .CPLs, do not use

    *      lpszCommandLine - ptr-> command to execute, as passed to us

    *      lpSecurityAttributesProcess - ptr-> SECURITY_ATTRIBUTES structure for Process.  Pass a null pointer

    *      lpSecurityAttributesThread - ptr-> SECURITY_ATTRIBUTES structure for first thread.  Pass a null pointer

    *      bInheritHandles - whether or not chlid inherits parent handles.  Since no SECURITY_ATTRIBUTES passed, default to FALSE

    *      dwCreateFlags - Process Creation Mode flag set.  We use the default mode at normal priority, ie 0

    *      lpvEnvironment - ptr-> a set of environment strings as if a MULTI_SZ.  We don't set, so pass a null pointer

    *      lpszStartupDir - ptr-> the starting directory.  If none provided to us, pass a null pointer

    *      lpStartInfo - ptr-> a STARTUPINFO structure.  We use one structure member at times.

    *      lpProcessInfo - ptr-> a PROCESS_INFORMATION structure, used to return PID/PHANDLE detail.

    *                     We use one member on return

    Declare SHORT CreateProcess IN WIN32API AS CrPr ;

       STRING lpszModuleName, ;

       STRING @lpszCommandLine, ;

       STRING lpSecurityAttributesProcess, ;

       STRING lpSecurityAttributesThread, ;

       SHORT bInheritHandles, ;

       INTEGER dwCreateFlags, ;

       STRING lpvEnvironment, ;

       STRING lpszStartupDir, ;

       STRING @lpStartInfo, ;

       STRING @lpProcessInfo

 

    If TYPE('tcCommandLine') # 'C'

 

       *   Command line must be a character string

       Return 0

 

    Endif

    If TYPE('tuFromDir') # 'C'

 

       *   If not a character string, pass a null pointer, defaulting to Current Working Dir

       tuFromDir = 0

 

    Else

 

       *   Otherwise, null pad the string

       tuFromDir = tuFromDir + CHR(0)

 

    Endif

    If TYPE('tcWindowMode') # 'C'

 

       *   If not passed, set to null string

       tcWindowMode = ''

 

    Else

 

       *   Translate the passed window mode to uppercase

       tcWindowMode = UPPER(tcWindowMode)

 

    Endif

 

    Local nStartedProcessHandle, uResult, cProcessInfo, cStartUpInfo

 

    *   Make default Structures for the CreateProcess call

    *

    *   ProcessInfo - 4 bytes, a Process handle, a Thread Handle, a (DWORD) ProcessId and a (DWORD) ThreadID

    *                 we save the Process handle and return it to caller in tnReturnProcessHandle

 

    cProcessInfo = REPL(CHR(0),16)

 

    *   StartUpInfo is a 68 byte long complex structure;  we either have 68 bytes with a cb member (byte 1) 68

    *   or with cb of 68, dwFlag low order byte (byte 45) of 1, and low order byte wShowWindow (byte 49) set to

    *   the SW_ value appropriate for the Window Mode desired.

 

    Do CASE

       Case tcWindowMode = 'HIDE'

 

           *   Hide - use STARTF_USESHOWFLAG and value of 0

           cStartUpInfo = CHR(68) + ;

               REPL(CHR(0),43) + ;

               CHR(1) + ;

               REPL(CHR(0),23)

 

       Case tcWindowMode = 'NOR'

 

           *   Normal - use STARTF_USESHOWFLAG and value of 1

           cStartUpInfo = CHR(68) + ;

               REPL(CHR(0),43) + ;

               CHR(1) + ;

               REPL(CHR(0),3) + ;

               CHR(1) + ;

               REPL(CHR(0),19)

 

       Case tcWindowMode = 'MIN'

 

           *   Minimize - use STARTF_USESHOWFLAG and value of 2

           cStartUpInfo = CHR(68) + ;

               REPL(CHR(0),43) + ;

               CHR(1) +  ;

               REPL(CHR(0),3) + ;

               CHR(2) + ;

               REPL(CHR(0),19)

 

       Case tcWindowMode = 'MAX'

 

           *   Maximize - use STARTF_USESHOWFLAG and value of 3

           cStartUpInfo = CHR(68) + ;

               REPL(CHR(0),43) + ;

               CHR(1) +  ;

               REPL(CHR(0),3) + ;

               CHR(3) + ;

               REPL(CHR(0),19)

 

           *   Other options exist - see WINBASE.H for values

       Otherwise

           *   Use default of application

           cStartUpInfo = CHR(68) + REPL(CHR(0),67)

    Endcase

 

    *   Do it now!

    uResult = CrPr(   0, ;

       tcCommandLine, ;

       0, 0, 0, 0, 0, ;

       tuFromDir, ;

       @cStartUpInfo, ;

       @cProcessInfo)

 

    If uResult = 1

       *   CreateProcess() started our app, but we have to wait until it finishes loading

       *   Strip the process handle from the PROCESS_INFORMATION structure

       nStartedProcessHandle = (((ASC(SUBST(cProcessInfo,4,1))*256) + ;

           ASC(SUBST(cProcessInfo,3,1)))*256 + ;

           ASC(SUBST(cProcessInfo,2,1)))*256 + ;

           ASC(LEFT(cProcessInfo,1))

       *   It's been launched;  wait until we're idling along

        =WaitInpIdle(GetCurrProc(),cnINFINITE)

       *   As long as the other process exists, wait for it

       Do WHILE WaitOnAppExit(nStartedProcessHandle, cnHalfASecond) = cnTimedOut

           *   Give us an out in case the other app hangs - lets the user quit via

           If INKEY() = 27

               *   Still running but we aren't waiting - return a -1 as a warning

               uResult = -1

               Exit

           Endif

       Enddo

    Else

       *   Return 0 to indicate failure

       uResult = 0

 

    Endif

    Return uResult

 

    *****************************************+

 

 

Suerte

 

 

 

______________________________________________

Carlos Omar Figueroa López

Servidores Dedicados Windows desde $ 4 USD / dia

http://www.DesarrollosEfiMax.com.mx

francisco prieto

unread,
Sep 11, 2015, 7:44:23 AM9/11/15
to publicesvfoxpro
Saludos,

Pancho
Córdoba
Argentina

francisco prieto

unread,
Sep 11, 2015, 7:46:22 AM9/11/15
to publicesvfoxpro
Ja,

creo que es la misma que te paso Carlos...

Pues esta es su documentacion

oTestRun = NEWOBJECT("api_apprun", "Process.vcx")
oTestRun.icCommandLine  = "NotePad.EXE"
* oTestRun.icLaunchDir  = "c:\test\"
* oTestRun.icWindowMode = "MAX"
oTestRun.LaunchAppAndWait()
** or oTestRun.LaunchApp()

Saludos,

Pancho
Córdoba
Argentina

Fernando D. Bozzo

unread,
Sep 11, 2015, 7:51:16 AM9/11/15
to publice...@googlegroups.com
Hola Carlos:

Casi casi, funciona, pero no devuelve el retorno devuelto por la aplicación llamada, por lo que devuelve 1 tanto si termina bien como si la matás.

Gracias igualmente!



francisco prieto

unread,
Sep 11, 2015, 8:08:35 AM9/11/15
to publicesvfoxpro
Fer,

Por lo que dice la informacion de MSDN, podes llegar a extender la informacion del error que te dio con GetLastError....

Eso si vas a tener que modificarla...

https://msdn.microsoft.com/en-us/library/windows/desktop/ms682425%28v=vs.85%29.aspx

Saludos,

Pancho
Córdoba
Argentina

francisco prieto

unread,
Sep 11, 2015, 8:10:16 AM9/11/15
to publicesvfoxpro
Saludos,

Pancho
Córdoba
Argentina

Fernando D. Bozzo

unread,
Sep 11, 2015, 8:20:48 AM9/11/15
to publice...@googlegroups.com
Gracias Pancho, voy a revisarlo todo.


Mario López

unread,
Sep 11, 2015, 8:35:25 AM9/11/15
to Comunidad de Visual Foxpro en Español
Fernando: yo uso esta rutina, adaptada de News2News si mal no recuerdo:


CLEAR

sCmd = "7za a test1 *.prg"
? sCmd, RunModal(sCmd)      && > 0

sCmd = "7za a test1 nonexistentfile.xxx"
? sCmd, RunModal(sCmd)       && > 1

RETURN



* Ejecuta un comando externo de forma modal y opcionalmente en un directorio distinto

* sCmd : Pathname completo del archivo a ejecutar seguido de sus parámetros (ej: E:\UTILES\PKZIP.EXE -ex& Prueba.zip)
* sDir (opcional) : directorio desde el que se ejecuta el comando
* nShow : 0=No muestra, 1=Muestra ejecución, cierra automáticamente

FUNCTION RunModal (sCmd, sDir, nShow)

LOCAL sStartProcBuf, sProcInfoBuf, nFlags, nRet, nhProc

IF EMPTY(nShow)
    nShow = 1
ENDIF

#DEFINE NORMAL_PRIORITY_CLASS 32
#DEFINE IDLE_PRIORITY_CLASS 64
#DEFINE HIGH_PRIORITY_CLASS 128
#DEFINE REALTIME_PRIORITY_CLASS 1600

* Return code from WaitForSingleObject() if
* it timed out.
#DEFINE WAIT_TIMEOUT 0x00000102

* This controls how long, in milli secconds, WaitForSingleObject()
* waits before it times out. Change this to suit your preferences.
#DEFINE WAIT_INTERVAL 200

DECLARE INTEGER CreateProcess IN kernel32.DLL ;
    INTEGER lpApplicationName, ;
    STRING lpCommandLine, ;
    INTEGER lpProcessAttributes, ;
    INTEGER lpThreadAttributes, ;
    INTEGER bInheritHandles, ;
    INTEGER dwCreationFlags, ;
    INTEGER lpEnvironment, ;
    STRING @lpCurrentDirectory, ;
    STRING @lpStartupInfo, ;
    STRING @lpProcessInformation

DECLARE INTEGER WaitForSingleObject IN kernel32.DLL ;
    INTEGER hHandle, INTEGER dwMilliseconds

DECLARE INTEGER CloseHandle IN kernel32.DLL ;
    INTEGER hObject

DECLARE INTEGER GetLastError IN kernel32.DLL

DECLARE INTEGER GetExitCodeProcess IN kernel32.DLL ;
    INTEGER hHandle, LONG @nExitCode

IF EMPTY(sDir)
    sDir = CURDIR()
ENDIF

* sCmd = sCmd + IIF(!EMPTY(sParm), " " + sParm, "")+ CHR(0)
sCmd = sCmd + CHR(0)
sDir = sDir + CHR(0)
nShow = IIF(VARTYPE(nShow) <> "N"SW_NORMAL, nShow)

* STARTUPINFO is 68 bytes, of which we need to
* initially populate the 'cb' or Count of Bytes member
* with the overall length of the structure.
* The remainder should be 0-filled

*    typedef struct _STARTUPINFO {
*        DWORD   cb;             1
*        LPTSTR  lpReserved;     5
*        LPTSTR  lpDesktop;      9
*        LPTSTR  lpTitle;        13
*        DWORD   dwX;             17
*        DWORD   dwY;             21
*        DWORD   dwXSize;         25
*        DWORD   dwYSize;         29
*        DWORD   dwXCountChars;     33
*        DWORD   dwYCountChars;     37
*        DWORD   dwFillAttribute;41
*        DWORD   dwFlags;         45
*        WORD    wShowWindow;     49
*        WORD    cbReserved2;     51
*        LPBYTE  lpReserved2;     53
*        HANDLE  hStdInput;         57
*        HANDLE  hStdOutput;     61
*        HANDLE  hStdError;         65
*    } STARTUPINFO, *LPSTARTUPINFO;

#define STARTF_USESHOWWINDOW    0x00000001
#define STARTF_USESIZE          0x00000002
#define STARTF_USEPOSITION      0x00000004
#define STARTF_USECOUNTCHARS    0x00000008
#define STARTF_USEFILLATTRIBUTE 0x00000010
#define STARTF_RUNFULLSCREEN    0x00000020  && ignored for non-x86 platforms
#define STARTF_FORCEONFEEDBACK  0x00000040
#define STARTF_FORCEOFFFEEDBACK 0x00000080
#define STARTF_USESTDHANDLES    0x00000100

nFlags = STARTF_USESHOWWINDOW

sStartProcBuf = REPLICATE(CHR(0), 68)
sStartProcBuf = STUFF(sStartProcBuf, 14, long2str (LEN(sStartProcBuf)))
sStartProcBuf = STUFF(sStartProcBuf, 454, long2str (nFlags))
sStartProcBuf = STUFF(sStartProcBuf, 492CHR (nShow) + CHR(0))

* PROCESS_INFORMATION structure is 4 longs,
* or 4*4 bytes = 16 bytes, which we'll fill with nulls.
sProcInfoBuf = REPLICATE(CHR(0), 16)

* Call CreateProcess, obtain a process handle. Treat the
* application to run as the 'command line' argument, accept
* all other defaults. Important to pass the sStartProcBuf and
* sProcInfoBuf by reference.
*    nRet = CreateProcess(0, File2Run, 0, 0, 1, ;
*          NORMAL_PRIORITY_CLASS, 0, 0, @sStartProcBuf, @sProcInfoBuf)

nRet = CreateProcess (0, sCmd, 001, ;
      NORMAL_PRIORITY_CLASS0, @sDir, @sStartProcBuf, @sProcInfoBuf)

* Unable to run, exit now.
IF nRet = 0
    * =MESSAGEBOX("Error occurred. Error code: ", GetLastError())
    CLEAR DLLS CreateProcess, WaitForSingleObject, CloseHandle, GetLastError, GetExitCodeProcess

    RETURN -1
ENDIF

* Extract the process handle from the
* PROCESS_INFORMATION structure.
nhProc = str2long (SUBSTR(sProcInfoBuf, 14))

DO WHILE .T.
    * Use timeout of TIMEOUT_INTERVAL msec so the display
    * will be updated. Otherwise, the VFP window never repaints until
    * the loop is exited.
    IF WaitForSingleObject(nhProc, WAIT_INTERVAL) != WAIT_TIMEOUT
        EXIT
    ENDIF
ENDDO

* Show a message box when we're done.
* =MESSAGEBOX ("Process completed")

* Close the process handle afterwards.
* nRet = CloseHandle (nhProc)
GetExitCodeProcess (nhProc, @nRet)
CloseHandle (nhProc)

CLEAR DLLS CreateProcess, WaitForSingleObject, CloseHandle, GetLastError, GetExitCodeProcess

RETURN nRet



********************
FUNCTION long2str
********************
   * Passed : 32-bit non-negative numeric value (m.longval)
   * Returns : ASCII character representation of passed
   *           value in low-high format (m.retstr)
   * Example :
   *    m.long = 999999
   *    m.longstr = long2str(m.long)

   PARAMETERS m.longval

   PRIVATE i, m.retstr

   m.retstr = ""
   FOR i = 24 TO 0 STEP -8
      m.retstr = CHR(INT(m.longval/(2^i))) + m.retstr
      m.longval = MOD(m.longval, (2^i))
   NEXT
RETURN m.retstr

*******************
FUNCTION str2long
*******************
   * Passed:  4-byte character string (m.longstr)
   *   in low-high ASCII format
   * returns:  long integer value
   * example:
   *   m.longstr = "1111"
   *   m.longval = str2long(m.longstr)

   PARAMETERS m.longstr

   PRIVATE i, m.retval

   m.retval = 0
   FOR i = 0 TO 24 STEP 8
      m.retval = m.retval + (ASC(m.longstr) * (2^i))
      m.longstr = RIGHT(m.longstr, LEN(m.longstr) - 1)
   NEXT

RETURN m.retval


***


HTH,
Mario
---
...

Fernando D. Bozzo

unread,
Sep 11, 2015, 9:08:59 AM9/11/15
to publice...@googlegroups.com

Hola Mario, me parece que es lo que estaba buscando.
En cuanto pueda probarlo te aviso.

Muchas gracias!

Jean Pierre Adonis De La Cruz Garcia

unread,
Sep 11, 2015, 5:26:23 PM9/11/15
to Comunidad de Visual Foxpro en Español
Fernando disculpa que me meta, pero uso siempre este comando y me vota la rspuesta que otros no me vota.

*** Convierte la Imagen en Texto
rut="tesseract sunat.jpg ocr -psm"
oShell = createobject("WScript.Shell")
oShell.Run(rut,0,.t.)
****
Donde "tesseract" es el ejecutable, y el resto es la rutina del mismo ejecutable, y hace el proceso en modo D.O.S. y modo oculto

Fernando D. Bozzo

unread,
Sep 11, 2015, 6:11:21 PM9/11/15
to publice...@googlegroups.com

Hola Jean:

El problema es que en algunas empresas los responsables de seguridad informática deshabilitan el acceso a ciertos objetos del sistema, por eso la búsqueda de un sustituto que no puede deshabilitarse.

Saludos

Jean Pierre Adonis De La Cruz Garcia

unread,
Sep 11, 2015, 6:20:53 PM9/11/15
to Comunidad de Visual Foxpro en Español
Entonces, haber prueba este otro modo, lo tenia en mis otros proyectos guardados antiguamente, quizas pueda ser la solucion.

Declare Long WinExec In kernel32 STRING lpCmdLine , Long nCmdShow

*cCmd = "RegSvr32.exe micontrol.ocx"
cCmd = "calc.exe"
=WinExec(cCmd, 0)

Marco Plaza

unread,
Sep 11, 2015, 7:48:28 PM9/11/15
to Comunidad de Visual Foxpro en Español

Fernando D. Bozzo

unread,
Sep 14, 2015, 8:57:40 AM9/14/15
to Comunidad de Visual Foxpro en Español
Hola chicos:

Quiero agradecerles a todos por las respuestas. De todo lo recopilado aquí, en la web y en documentación de Microsoft, puse hacer una función casi 100% compatible a nivel de parámetros y de funcionalidad con el método "Run" de la clase WScript.Shell del Sistema Operativo trabajando a 32 bits. Aclaro lo de los 32 bits porque no tengo ni idea de si funciona con el compilador de 64 bits de Chen para VFP 9.

El objetivo era poder hacer un método que funcione igual que el método Run de WScript.Shell para los casos en que los Administradores de Sistemas deshabiliten esta clase, y por eso la necesidad.

La función se llama WScriptShell_Run y el código está equí:
http://fox.wikis.com/wc.dll?Wiki~WScriptShellRun~VFP


Muchas gracias! :D



El viernes, 11 de septiembre de 2015, 12:56:32 (UTC+2), Fernando D. Bozzo escribió:

Jean Pierre Adonis De La Cruz Garcia

unread,
Sep 14, 2015, 11:27:08 AM9/14/15
to Comunidad de Visual Foxpro en Español
Excelente aporte mi estimado fernando, se aprende algo nuevo siempre.

Fidel Charny

unread,
Sep 14, 2015, 11:39:42 AM9/14/15
to Comunidad de Visual Foxpro en Español
Fantástico Fernando!!
Ya está probado e incorporado.

Muchas gracias!!

Jorge Galván Pérez

unread,
Sep 14, 2015, 11:49:25 AM9/14/15
to Comunidad de Visual Foxpro en Español
Disculpa Fernando trate de bajar la función WScriptShell_Run pero me dice acceso denagado.

Gracias 

Fernando D. Bozzo

unread,
Sep 14, 2015, 12:10:00 PM9/14/15
to publice...@googlegroups.com
Hola Jorge:

La función está en texto claro y legible directamente, no es un adjunto, por lo que si la podés ver y el problema lo tenés luego al intentar copiarla o lo que sea, entonces el problema lo tenés en ese paso, ya que solo hay que marcar, copiar y pegar en un prg cualquiera.

Saludos.-



Staff de Desarrollos EfiMax

unread,
Sep 14, 2015, 12:26:13 PM9/14/15
to publice...@googlegroups.com

Fernando y como lo ejecutas de manera síncrona, por ejemplo para esperar a que termine un proceso largo, por ejemplo:

 

Resp= WScriptShell_Run("c:\windows\system32\cmd.exe /c dir c:\*.* /s > \temp\dir.txt")

 

Ya que el valor de retorno 0 o -1, sólo me denota si es un comando válido y lo retorna en cuanto regresa el control al VFP, aunque el proceso demorara dos minutos en concluirse.

 

 

 

 

 

 

De: publice...@googlegroups.com [mailto:publice...@googlegroups.com] En nombre de Fernando D. Bozzo


Enviado el: lunes, 14 de septiembre de 2015 05:58 a.m.
Para: Comunidad de Visual Foxpro en Español

Jorge Galván Pérez

unread,
Sep 14, 2015, 2:01:56 PM9/14/15
to Comunidad de Visual Foxpro en Español
Gracias Fernando por responder pero cuando le doy a link para poder copiar el texto de la función me sale

El propietario del sitio web(fox.wikis.com)  a prohibido tu ip

No se si me explique mejor ahora.

Gracias 

Staff de Desarrollos EfiMax

unread,
Sep 14, 2015, 2:05:25 PM9/14/15
to publice...@googlegroups.com

Utiliza un navegador anónimo como https://hola.org/ o https://www.torproject.org/

 

suerte.

 

 

 

______________________________________________

Carlos Omar Figueroa López

Servidores Dedicados Windows desde $ 4 USD / dia

http://www.DesarrollosEfiMax.com.mx

 

 

 

 

De: publice...@googlegroups.com [mailto:publice...@googlegroups.com] En nombre de Jorge Galván Pérez
Enviado el: lunes, 14 de septiembre de 2015 11:02 a.m.
Para: Comunidad de Visual Foxpro en Español
Asunto: [vfp] Re: Reemplazo de WScript.Shell => run con Win32?

 

Gracias Fernando por responder pero cuando le doy a link para poder copiar el texto de la función me sale

Jorge Galván Pérez

unread,
Sep 14, 2015, 2:09:51 PM9/14/15
to Comunidad de Visual Foxpro en Español
Listo Fernando an bloquedao la dirección ip pero es la gente del gobierno de mi país que da el servicio de internet.


Gracias y disculpa
 

Fernando D. Bozzo

unread,
Sep 14, 2015, 2:51:29 PM9/14/15
to publice...@googlegroups.com

Hola:

Como es compatible a nivel parámetros con la que sustituye, en la cabecera está el link que documenta los parámetros, donde uno de ellos indica si debe esperar a que finalice la ejecución (sincrónico)  o no (asincrónico)

Staff de Desarrollos EfiMax

unread,
Sep 14, 2015, 3:19:08 PM9/14/15
to publice...@googlegroups.com

Si, ya lei bien

 

WScriptShell_Run("c:\windows\system32\cmd.exe /c dir c:\*.* /s > \temp\dir.txt",0,.T.)

WScriptShell_Run("c:\windows\system32\cmd.exe /c dir c:\*.* /s > \temp\dir.txt",0,.F.)

 

Sorry y Gracias

Fernando D. Bozzo

unread,
Sep 15, 2015, 8:55:08 AM9/15/15
to Comunidad de Visual Foxpro en Español
Buenas:

Haciendo algunas pruebas, me encontré que cuando se llama pasando solo el nombre de un TXT o un LOG para que lo abra con la aplicación predeterminada, como hace el Run original de WScript.Shell, no lo hace, por lo que tuve que modificarla para que lo haga y ahora sí, cuando se pasa un documento, lo abre con la aplicación predefinida :D

Básicamente ahora lo que hace es intentar lanzar el proceso indicado, pero si lo que se indica no es un proceso, sino un documento con su ruta, entonces vuelve a intentarlo una segunda vez pero con una función distinta (ShellExecuteEx) que se encarga de buscar la aplicación predeterminada para abrir el documento y que a diferencia del ShellExecute de siempre, devuelve un handle al proceso lanzado, lo que luego permite esperar a que termine.

Bueno, dejo nuevamente el link con la función modificada:
http://fox.wikis.com/wc.dll?Wiki~WScriptShellRun~VFP


Me resultó muy interesante, y algo para seguir investigando, el uso de la función sys(2600) que es algo avanzada y en Fox no está bien explicado su funcionamiento para quienes no saben C++, ni tampoco hay ejemplos de su uso. El único ejemplo que encontré estaba en Foxite y por eso puse el link dentro del código, para quienes quieran profundizar más.


Saludos!

InfoLib

unread,
Sep 15, 2015, 10:52:41 AM9/15/15
to Comunidad de Visual Foxpro en Español
Nircmd de www.nirsoft.net creo, puede llegar a servir tal vez...

Carton Jeston (9.0.0.7423)

unread,
Sep 21, 2015, 3:50:20 PM9/21/15
to Comunidad de Visual Foxpro en Español
Ahora mismo tengo el w7-32 para programar y el w10-64 para trastear y en este ultimo no tengo aun instalado el compilador a 64.

Lo que si he hecho ha sido probar en compilar a 32 y si funciona. Teniendo en cuenta que la mayor parte de problemas viene por la sintaxis como uso de store, no creo que de problemas con la version de 64.

Y en el peor de los casos, llegado el momento de dejar definitivamente los 32bits, hay que revisar todos los procedimientos y librerias ;)

un saludo

Esteban H

unread,
Sep 21, 2015, 7:11:16 PM9/21/15
to publice...@googlegroups.com

Hola Carton.

Tu prueba de compilarlo en 32 no es lo q necesita Fernando, de hecho ya lo hizo, lo q necesita es vos q tenes la librería de Chen la verdadera prueba sería q lo compilaras en 64 x supuesto q usando un Win64 y ver si la librería funciona…

 

Saludos.

 

Esteban.

 

De: publice...@googlegroups.com [mailto:publice...@googlegroups.com] En nombre de Carton Jeston (9.0.0.7423)
Enviado el: lunes, 21 de septiembre de 2015 04:50 p.m.
Para: Comunidad de Visual Foxpro en Español
Asunto: [vfp] Re: Reemplazo de WScript.Shell => run con Win32?

 

Ahora mismo tengo el w7-32 para programar y el w10-64 para trastear y en este ultimo no tengo aun instalado el compilador a 64.

Carton Jeston (9.0.0.7423)

unread,
Sep 22, 2015, 1:26:56 AM9/22/15
to Comunidad de Visual Foxpro en Español, er...@yahoo.com.ar

Se que necesita la prueba en 64 pero quise hacer un avance en 32 con el compilador de Chen para ver si usaba alguna funcion incompatible. Por cierto, Fernando en ningun momento dijo haber hecho la prueba en 32 con el compilador, asi que se sobreentiende que compila con foxpro estandar que es a 32 ;)

Fernando D. Bozzo

unread,
Sep 22, 2015, 2:40:17 AM9/22/15
to publice...@googlegroups.com
Hola chicos:

Lo que necesito realmente ya está, que es la función que pude armar. Solo quice dejar claro, para quienes les sea útil, que solo la probé en 32 bits (con el compilador de VFP original) y que en 64 podría no funcionar porque hace manejo manual de punteros de memoria, que podrían funcionar distinto o no funcionar en 64 bits. Realmente no necesito más nada.

Muchas gracias a todos! :D


Message has been deleted

Edwin Juarez

unread,
Oct 20, 2018, 2:00:41 PM10/20/18
to Comunidad de Visual Foxpro en Español

Reviviendo este POST.
No me envía los parámetros para el cmd ú otro exe que quiera usar.
Según me di cuenta se da cuando la cadena del comando para los parámetros tiene los caracteres > (salida a una cadena) y | (palotes para continuar el comando en una sóla línea).
El archivo prg que uso es este.

Por favor si me pudiera echar una mano se lo agradecería
Un abrazo

*!* ? CreateProcess("c:\windows\Notepad.exe",;

*!* ["c:\westwind\wconnect\wcscripts\test.wcs"],1,.T.)

*/? CreateProcess1("c:\windows\Notepad.exe","",1,.T.)

lcCommand = [tasklist | find "notepad" > "Notepadproces.txt"]

? CreateProcess1("c:\windows\System32\cmd.exe", lcCommand, 1, .T.)

RETURN

************************************************************************

* wwAPI :: Createprocess

****************************************

*** Function: Calls the CreateProcess API to run a Windows application

*** Assume: Gets around RUN limitations which has command line

*** length limits and problems with long filenames.

*** Can do everything EXCEPT REDIRECTION TO FILE!

*** Pass: lcExe - Name of the Exe

*** lcCommandLine - Any command line arguments

*** Return: .t. or .f.

************************************************************************

FUNCTION Createprocess1(lcExe,lcCommandLine,lnShowWindow,llWaitForCompletion)

LOCAL hProcess, cProcessInfo, cStartupInfo

DECLARE INTEGER CreateProcess IN kernel32 as ApiCreateProcess;

STRING lpApplicationName,;

STRING lpCommandLine,;

INTEGER lpProcessAttributes,;

INTEGER lpThreadAttributes,;

INTEGER bInheritHandles,;

INTEGER dwCreationFlags,;

INTEGER lpEnvironment,;

STRING lpCurrentDirectory,;

STRING lpStartupInfo,;

STRING @lpProcessInformation

cProcessinfo = REPLICATE(CHR(0),128)

cStartupInfo = GetStartupInfo(lnShowWindow)

IF !EMPTY(lcCommandLine)

lcCommandLine = ["] + lcExe + [" ]+ lcCommandLine

ELSE

lcCommandLine = ""

ENDIF

*!* #DEFINE CREATE_NEW_CONSOLE 16

*!* #DEFINE NORMAL_PRIORITY_CLASS 32

#DEFINE CREATE_NEW_CONSOLE 0x00000010

#DEFINE NORMAL_PRIORITY_CLASS 0x00000020

lngdwCreationFlags = CREATE_NEW_CONSOLE + NORMAL_PRIORITY_CLASS

lnResult = ApiCreateProcess(lcExe, lcCommandLine, 0, 0, 1, lngdwCreationFlags, 0, 0, cStartupInfo, @cProcessInfo)

IF lnResult = 0

RETURN .F.

ENDIF

*lnResult = ApiCreateProcess(lcExe,lcCommandLine,0,0,1,0,0,;

SYS(5)+CURDIR(),cStartupInfo, @cProcessInfo)

lhProcess = CHARTOBIN( SUBSTR(cProcessInfo,1,4) )

*/lhProcess = Buf2dword(LEFT(cProcessInfo, 4))

*/lhProcess = str2long (SUBSTR(cProcessInfo, 1, 4))

IF llWaitForCompletion

#DEFINE WAIT_TIMEOUT 0x00000102

DECLARE INTEGER WaitForSingleObject IN kernel32.DLL ;

INTEGER hHandle, INTEGER dwMilliseconds

lngdwMilliseconds = 200

*!* DO WHILE WaitForSingleObject(lhProcess, lngdwMilliseconds) = WAIT_TIMEOUT

*!* DOEVENTS

DO WHILE .T.

*** Update every 100 milliseconds

*!* IF WaitForSingleObject(lhProcess, lngdwMilliseconds) != WAIT_TIMEOUT

lnRet = WaitForSingleObject(lhProcess, lngdwMilliseconds)

IF lnRet != WAIT_TIMEOUT

EXIT

ELSE

DOEVENTS

ENDIF

ENDDO

ENDIF

DECLARE INTEGER CloseHandle IN kernel32.DLL ;

INTEGER hObject

CloseHandle(lhProcess)

RETURN IIF(lnResult=1,.t.,.f.)

*/

FUNCTION getStartupInfo(lnShowWindow)

LOCAL lnFlags

* creates the STARTUP structure to specify main window

* properties if a new window is created for a new process

IF EMPTY(lnShowWindow)

lnShowWindow = 1

ENDIF

*| typedef struct _STARTUPINFO {

*| DWORD cb; 4

*| LPTSTR lpReserved; 4

*| LPTSTR lpDesktop; 4

*| LPTSTR lpTitle; 4

*| DWORD dwX; 4

*| DWORD dwY; 4

*| DWORD dwXSize; 4

*| DWORD dwYSize; 4

*| DWORD dwXCountChars; 4

*| DWORD dwYCountChars; 4

*| DWORD dwFillAttribute; 4

*| DWORD dwFlags; 4

*| WORD wShowWindow; 2

*| WORD cbReserved2; 2

*| LPBYTE lpReserved2; 4

*| HANDLE hStdInput; 4

*| HANDLE hStdOutput; 4

*| HANDLE hStdError; 4

*| } STARTUPINFO, *LPSTARTUPINFO; total: 68 bytes

 

#DEFINE STARTF_USESTDHANDLES 0x0100

#DEFINE STARTF_USESHOWWINDOW 1

#DEFINE SW_HIDE 0

#DEFINE SW_SHOWMAXIMIZED 3

#DEFINE SW_SHOWNORMAL 1

lnFlags = STARTF_USESHOWWINDOW

RETURN binToChar(80) +;

binToChar(0) + binToChar(0) + binToChar(0) +;

binToChar(0) + binToChar(0) + binToChar(0) + binToChar(0) +;

binToChar(0) + binToChar(0) + binToChar(0) +;

binToChar(lnFlags) +;

binToWordChar(lnShowWindow) +;

binToWordChar(0) + binToChar(0) +;

binToChar(0) + binToChar(0) + binToChar(0) + REPLICATE(CHR(0),30)

************************************************************************

FUNCTION CharToBin(lcBinString,llSigned)

****************************************

*** Function: Binary Numeric conversion routine.

*** Converts DWORD or Unsigned Integer string

*** to Fox numeric integer value.

*** Pass: lcBinString - String that contains the binary data

*** llSigned - if .T. uses signed conversion

*** otherwise value is unsigned (DWORD)

*** Return: Fox number

************************************************************************

LOCAL m.i, lnWord

lnWord = 0

FOR m.i = 1 TO LEN(lcBinString)

lnWord = lnWord + (ASC(SUBSTR(lcBinString, m.i, 1)) * (2 ^ (8 * (m.i - 1))))

ENDFOR

IF llSigned AND lnWord > 0x80000000

lnWord = lnWord - 1 - 0xFFFFFFFF

ENDIF

RETURN lnWord

* wwAPI :: CharToBin

***********************************************************************

FUNCTION BinToChar(lnValue)

****************************************

*** Function: Creates a DWORD value from a number

*** Pass: lnValue - VFP numeric integer (unsigned)

*** Return: binary string

************************************************************************

Local byte(4)

If lnValue < 0

lnValue = lnValue + 4294967296

EndIf

byte(1) = lnValue % 256

byte(2) = BitRShift(lnValue, 8) % 256

byte(3) = BitRShift(lnValue, 16) % 256

byte(4) = BitRShift(lnValue, 24) % 256

RETURN Chr(byte(1))+Chr(byte(2))+Chr(byte(3))+Chr(byte(4))

* wwAPI :: BinToChar

************************************************************************

FUNCTION BinToWordChar(lnValue)

****************************************

*** Function: Creates a DWORD value from a number

*** Pass: lnValue - VFP numeric integer (unsigned)

*** Return: binary string

************************************************************************

RETURN Chr(MOD(m.lnValue,256)) + CHR(INT(m.lnValue/256))

*Some of that code originated from Christof Wollenhaupt with a number of modifications made to support wait operations and easier access to the command line parameters.

*To support piping etc. wwIPStuff.dll (part of West Wind Internet Protocols or West Wind Client Tools) includes a wrapper that does something like this:

************************************************************************

* wwAPI :: CreateprocessEx

****************************************

*** Function: Calls the CreateProcess API to run a Windows application

*** Assume: Gets around RUN limitations which has command line

*** length limits and problems with long filenames.

*** Can do Redirection

*** Requires wwIPStuff.dll to run!

*** Pass: lcExe - Name of the Exe

*** lcCommandLine - Any command line arguments

*** Return: .t. or .f.

************************************************************************

FUNCTION CreateProcessEx(lcExe,lcCommandLine,lcStartDirectory,;

lnShowWindow,llWaitForCompletion,lcStdOutputFilename)

DECLARE INTEGER wwCreateProcess IN wwIPStuff.DLL AS _wwCreateProcess ;

String lcExe, String lcCommandLine, INTEGER lnShowWindow,;

INTEGER llWaitForCompletion, STRING lcStartupDirectory, STRING StdOutFile

IF EMPTY(lcStdOutputFileName)

lcStdOutputFileName = NULL

ENDIF

IF EMPTY(lcStartDirectory)

lcStartDirectory = CHR(0)

ENDIF

IF !EMPTY(lcCommandLine)

lcCommandLine = ["] + lcExe + [" ]+ lcCommandLine

ELSE

lcCommandLine = ""

ENDIF

IF llWaitForCompletion

lnWait = 1

ELSE

lnWait = 0

ENDIF

IF EMPTY(lnShowWindow)

lnShowWindow = 4

ENDIF

lnResult = _wwCreateProcess(lcExe,lcCommandLine,lnShowWindow,lnWait,;

lcStartDirectory,lcStdOutputFileName)

RETURN IIF(lnResult == 1, .t. , .f.)

ENDFUNC

*/

FUNCTION buf2dword (lcBuffer)

RETURN;

Asc(SUBSTR(lcBuffer, 1,1)) + ;

Asc(SUBSTR(lcBuffer, 2,1)) * 256 +;

Asc(SUBSTR(lcBuffer, 3,1)) * 65536 +;

Asc(SUBSTR(lcBuffer, 4,1)) * 16777216

ENDFUNC

*/

*******************

Edwin Juarez

unread,
Oct 20, 2018, 2:03:17 PM10/20/18
to Comunidad de Visual Foxpro en Español
Tampoco funciona cuando los coloco entre comillas dobles las rutas de acceso que tienen espacios.
Ejemplo: "C:\Backup DATA\CARPETA\" 

RETURN Chr(byte(1))+<font color="#00

Fernando D. Bozzo

unread,
Oct 20, 2018, 2:06:27 PM10/20/18
to Comunidad de Visual Foxpro en Español
Hola Edwin:

Ya que reviviste este hilo de 2015, por qué no aprovechás la función que comenté en este mensaje, más arriba:



Saludos.-

byte(4) = BitRShift(lnValue, 24) % 256</f

Edison Ramirez

unread,
Oct 20, 2018, 3:43:01 PM10/20/18
to publice...@googlegroups.com
Lol pero si solo es mostrar la información de un texto 

Germán Fabricio Valdez

unread,
Oct 20, 2018, 9:16:28 PM10/20/18
to Comunidad de Visual Foxpro en Español
objShell = CreateObject("WScript.Shell")
objShell.Run("notepad.exe",,.t.)

esto funciona bien en visual foxpro advance 10 64bits
Reply all
Reply to author
Forward
0 new messages