Opened 15 years ago
Last modified 11 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 15 years ago by
| Component: | Kernel → System |
|---|---|
| Owner: | changed from Víctor de Buen Remiro to Jorge |
| Status: | new → assigned |
comment:2 Changed 15 years ago by
| Priority: | normal → high |
|---|---|
| Severity: | normal → critical |
Changed 14 years ago by
| Attachment: | tclexec.tcl added |
|---|
Changed 14 years ago by
| Attachment: | tclexec.tol added |
|---|
comment:3 Changed 14 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 14 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 14 years ago by
| Owner: | changed from Jorge to Humberto Carralero |
|---|
comment:6 Changed 14 years ago by
comment:7 Changed 14 years ago by
| Owner: | changed from Humberto Carralero to Jorge |
|---|---|
| Status: | assigned → accepted |
comment:8 Changed 14 years ago by
comment:9 Changed 14 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 14 years ago by
comment:12 Changed 14 years ago by
comment:13 Changed 14 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 11 years ago by
| Owner: | changed from Jorge to Pedro Gea |
|---|
comment:15 Changed 11 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.