Opened 14 years ago
Last modified 10 years ago
#1118 accepted enhancement
System function returning the answer
Reported by: | Pedro Gea | Owned by: | Pedro Gea |
---|---|---|---|
Priority: | high | Milestone: | Mantainance |
Component: | System | Version: | head |
Severity: | critical | Keywords: | |
Cc: |
Description
Se solicita la implementación de una alternativa a las funciones System
o WinSystem
que permita hacer llamadas al sistema operativo y que canalice las respuestas de la llamada.
De las dos funciones actuales sólo System
es capaz de ejecutar comandos del sistema operativo como dir
o copy
. Sería deseable que esto fuese siempre así.
El siguiente código funciona con System
pero no con WinSystem
:
Real System("dir c:\\ > c:\\temp\\dir.txt"); Real System("del c:\\temp\\dir.txt");
Sin embargo ninguna es capaz de devolver la respuesta de la llamada, ni siquiera del error de la llamada devolviendo siempre:
- System:
ERROR: [] [2]=No such file or directory No se pudo ejecutar el mandato: <...>
- WinSystem:
ERROR: [] Error del Sistema Operativo Creando el proceso <...> El sistema no puede encontrar el archivo especificado.
A continuación se adjunta una implementación en código TOL de la función buscada que se apoya en la construcción de archivos temporales:
Text AnsSystem(Text cmd) { Text batFile = TmpDir<<"ans.bat"; Text ansFile = TmpDir<<"ans.txt"; Text errFile = TmpDir<<"ans.err.txt"; Real FileDelete(batFile); Real FileDelete(ansFile); Real FileDelete(errFile); Text WriteFile(batFile, cmd<<" > "<<Qt(ansFile)<<" 2> "<<Qt(errFile)); Real WinSystem(batFile, False, True); Text ans = ReadFile(ansFile); Text err = ReadFile(errFile); If(TextLength(err), Write("[AnsSystem] "<<err,"E")); Real FileDelete(batFile); Real FileDelete(ansFile); Real FileDelete(errFile); ans };
Entiendo que sobre el modo de encaminar la respuesta y los errores hay distintas formas y quizá podría implementarse una variedad de la función que no mostrase el error sino que lo devolviese, algo semejante a Tcl_Eval
devolviendo un conjunto con un real que indique el éxito de la llamada y un texto con la respuesta o el mensaje de error de la llamada.
Esta función podría implementarse como System_Eval
o algo así.
Attachments (2)
Change History (18)
comment:1 Changed 14 years ago by
Component: | Kernel → System |
---|---|
Owner: | changed from Víctor de Buen Remiro to Jorge |
Status: | new → assigned |
comment:2 Changed 14 years ago by
Priority: | normal → high |
---|---|
Severity: | normal → critical |
Changed 13 years ago by
Attachment: | tclexec.tcl added |
---|
Changed 13 years ago by
Attachment: | tclexec.tol added |
---|
comment:3 Changed 13 years ago by
En los archivos adjuntos se da una solución multiplataforma basada en Tcl, un ejemplo de uso es:
Set TclExec( [["svn", "ls"]] );
retorna un conjunto de 3 elementos:
Text errorCode
: cadena que contiene el código interno del error o NONE si no hay errorText errorInfo
: cadena que contiene una traza del error según la pila de evaluación de TclText Output
: cadena que contiene la salida del comando tal y como se mostraría al ejecutarlo desde una consola de comandos.
comment:4 Changed 13 years ago by
El siguiente ejemplo contiene una función exec basada en popen y pclose que puediera servir de base para la implementación en TOL.
Hay que verificarlo en windows todavía.
#include <string> #include <iostream> #include <stdio.h> #ifdef WIN32 #define popen _popen #define pclose _pclose #endif std::string exec(const char* cmd) { FILE* pipe = popen(cmd, "r"); if (!pipe) return "ERROR"; char buffer[128]; std::string result = ""; while(!feof(pipe)) { if(fgets(buffer, 128, pipe) != NULL) result += buffer; } pclose(pipe); return result; } int main( int argc, char*argv[] ) { if ( argc == 1 ) { std::cout << "nothing to execute\n"; return 0; } std::string output; std::string cmd; for ( int i = 1; i < argc; i++ ) { cmd += '"'; cmd += argv[i]; cmd += "\" "; } std::cout << "executing: " << cmd << "\n"; output = exec( cmd.c_str() ); std::cout << output << "\n"; return 0; }
comment:5 Changed 13 years ago by
Owner: | changed from Jorge to Humberto Carralero |
---|
comment:6 Changed 13 years ago by
comment:7 Changed 13 years ago by
Owner: | changed from Humberto Carralero to Jorge |
---|---|
Status: | assigned → accepted |
comment:8 Changed 13 years ago by
comment:9 Changed 13 years ago by
En windows los argumentos con espacio se protegen con \"...\", en cambio en linux hay que escapar los espacios '\ ', la función pudiera encargarse de protegerlos si esto no vienen protegidos.
comment:10 Changed 13 years ago by
comment:12 Changed 13 years ago by
comment:13 Changed 13 years ago by
Es necesario revisar el funcionamiento de PExec para que devuelva el estado (3er. argumento) a 0 si hubo errores y reencamine los errores a la salida (2o. argumento).
También es necesario evitar la aparición de la ventana de la consola en Windows.
comment:14 Changed 10 years ago by
Owner: | changed from Jorge to Pedro Gea |
---|
comment:15 Changed 10 years ago by
Se separa parte del cuerpo del método void BSetPExec::CalcContens()
y se traslada a un procedimiento en BSys (BSys::PExecQuiet
) que es donde se encuentran las funcionalidades con llamadas al sistema operativo.
Se redirige la salida estándar de errores de la llamada a pexec
a un archivo para poder capturarla y así detectar las llamadas con errores. Se usa un mecanismo similar al que usa WinSystem para capturar los errores de las llamadas precedidas por cmd
.
Sin embargo, no parece que hay forma de evitar que la ventana de la consola aparezca al ejecutar PExec
con Windows.
Para evitar la ventana de la consola, se crea un nuevo procedimiento en BSys (BSys::WinSystemQuiet
) parecido al de PExec
y que permite realizar la llamada y obtener las salidas sin mostrar la ventana.
Se crea un nuevo par de funciones AnsSystem
y AnsSystemQuiet
que permiten realizar llamadas al sistema operativo y obtener su respuesta y que se redirigen a BSys::WinSystemQuiet
y BSys::PExecQuiet
según el sistema operativo sea Windows o no.
La primera: AnsSystem
devuelve la salida estándar de la llamada y muestra los errores en caso de haberlos.
La segunda: AnsSystemQuiet
devuelve un conjunto con el estado de la llamada al proceso y las salidas estándar y de errores. Con esta función TOL no muestra los errores.
TOL es un sistema multiplataforma por lo que hay que tender a dar soluciones que funciones de forma independiente del sistema operativo. Redirecciono este ticket a Jorge por ese motivo.