PDA

Ver la Versión Completa : Comando S.O.


fjcg02
24-06-2004, 13:04:01
Hola a todos
Mi pregunta es al siguiente
¿ Se puede ejecutar un comando del SO y redireccionarlo a una variable?
ejemplo -> Ventana cmd , ejecutar c:\dir
... y que el resultado quede en una variable.

Puede parecer raro, pero no es dir el comando que quiero utilizar.

Gracias por vuestra colaboración.

Un saludo

Gydba
24-06-2004, 13:19:03
Buen día,

No sé para que te puede servir algo así. Pero a razón de no entrometerme demasiado tenés la posibilidad, con algunos comandos, de redireccionar la salida a un archivo. Ejemplo: "dir > archivo.txt". De esta manera lo podrías levantar luego desde Delphi en lo que vos quieras.

Pero no creo que sea puntualmente lo que buscas.

fjcg02
24-06-2004, 13:33:12
Exacto , es lo que necesito, pero ¿ se puede hacer desde un ejecutable y dejar la salia en una variable ?

Gracias por responder.


Un saludo

jachguate
24-06-2004, 13:47:05
¿Cual es el comando que te interesa?

Gydba
24-06-2004, 13:49:49
Buenas,

Si es eso lo que buscas si se puede. Deberías hacer un programa que ejecute lo que necesitas en línea de comandos y que luego obtenga la salida del archivo.

Fijáte en este hilo que hay un ejemplo de WinExec:
http://www.clubdelphi.com/foros/showthread.php?t=10722&highlight=winexec

Para leer el archivo y poder manipularlo con facilidad podrías utilizar un TStringList. De todas formas en este foro se habló bastante de este tipo de temas, quizás sea más útil que te des una vuelta por la búsqueda del foro.

fjcg02
24-06-2004, 14:21:25
Creo que me vale más que suficientemente. Todo el desarrollo por encima ya lo prepararé con calma.

Busqué en los foros antiguos, pero a veces es difícil a bote pronto acertar con las palabras claves a utilizar y que encuentres lo que quieres, sobre todo cuando andas un poco despistado.

Gracias por vuestra ayuda, me habeis dado luz.

Un saludo

fjcg02
24-06-2004, 14:36:57
¿Cual es el comando que te interesa?

Para alimentar tu curiosidad.
Quiero hacer un programa que controle los accesos a mi pc. Hice ayer una pregunta en el foro pero creo que la planteé mal porque nadie me ha respondido.
Al grano, creo que algunos 'compañeros' se conectan a mi pc y me extraen ficheros que son de mi propiedad, que utilizo como diarios de incidencias - soy responsable de un departamento y tengo problemas con un par de 'rebeldes' -. Como no me hacen caso los administradores del sistema - yo no lo soy - ni tengo potestad para instalarme programas de auditoría, ... me hice un script que se lanza cada 5 minutos con el comando arp -a >> fichero. En el fichero busco las macadress de los equipos desde los que creo que se conectan. Esto, hace que se me abra una ventana cmd cada 5 minutos, que se me 'cuela' en el escritorio y me hace perder letras en la aplicación en la que estoy trabajando ( word, excel, correo), ... lo que útlimamente ya me está cansando.
Quiero una solución un poco más elegante - seguro que hay alguna manera muuuucho más sencilla - , y como de sistema no controlo mucho, se me ocurrió la 'brillante' idea.
O sea, que aquí estoy dándole vueltas al tema.

Por cierto, quiero pillarles 'in fraganti' para por lo menos sacarles los colores y pillarles con mi disco mapeado, porque lo denuncié y no me han hecho demasiado caso. Como mi orgullo ha salido herido, pues eso.... pero sin que la sangre llegue al río.

Perdonad la chapa, pero cuando alquien viola tu intimidad, pues eso, te calientas y el derecho al pataleo es lo único que nos queda.


Un saludo a todos

jachguate
24-06-2004, 16:19:06
Para alimentar tu curiosidad.
No es por simple curiosidad... habrán algunos comandos que se pueden tratar de una forma o de otra...

En el caso del arp, ya lo tenes redireccionado a un fichero, por lo que no necesariamente tenes que "asignar el resultado a una variable" como lo habias planteado.

Cuando lanzas el comando, si lo haces con ShellExecute, podes enviarle sw_hide en el parámetro nShowCmd, de manera que la ventana de consola no sea visible, y seguir tratando el archivo generado por la captura de la salida estándar al concluir su ejecución.

Al grano, creo que algunos 'compañeros' se conectan a mi pc y me extraen ficheros que son de mi propiedad

Esto se combate con acceso restringido a los recursos compartidos o con otras técnicas que te protejan "a priori" de los intrusos.... un programa que te diga quien ser robó tu información, no será muy util... :rolleyes:

Hasta luego.

;)

fjcg02
25-06-2004, 08:18:54
Hola amigos ( me tomo la libertad de trataros como tal ... ;) )

He estado haciendo pruebas con el tema este de marras y me dice que el fichero donde redirecciono la salida no existe, por lo que parece que no se ejecuta el comando.
Pistas:
- strCommand contiene 'arp -a > c:\borrar.txt', confirmado.
- Si pongo SW_SHOW arranca una ventana porque la veo abrirse y cerrarse.
- Y poco más. Muestro las líneas para comprobar que lo hago bien.
En la ayuda no he encontrado documentación de winexec.
Utilizo Delphi 7

Agradecería cualquier sugerencia o similar.
Adjunto el código


****************************************************
procedure TFormMain.comprobar;
var n: integer; strCommand : String; zCommand : array[0..79] of Char;
begin
strCommand:= EComando.Text+' > '+FileListBox2.Directory+Esalida.text;
winexec(StrPCopy(zCommand, StrCommand), SW_HIDE);
Salida.LoadFromFile(ESAlida.Text);
For n:=0 to Salida.Count-1 do
showmessage(Salida[n]);
end;

Error: Cuando hace el LoadFromFile dice que el fichero que tiene ESalida.Text no existe.
****************************************************


Un saludo a todos

jmoran
25-06-2004, 10:12:16
Hola,

He hecho la prueba que mencionabas y no se crea el fichero porque winexec no interpreta bien la orden, si la ejecutas desde el dos arp -a > c:\result.txt funciona sin problemas pero parece que winexec interpreta el > y el nombre de fichero como parametros de arp y no del sistema, genera un error y no crea el fichero destino.

Si pruebas a ejecutar un bat (WinExec('c:\proceso.bat',.SW_..); y dentro del bat tienes arp -a > c:\result.txt, lo genera sin problemas.

Puedes modificar el código para que autogenere el bat y lo ejecute.

Con respecto a arp, puedes usar tambien net file, que te da la lista de ficheros propios abiertos por otras máquinas en la red, indicando el usuario que lo hace y todo.

fjcg02
25-06-2004, 11:47:25
Gracias, lo porbaré en cuanto pueda.

Un saludo

fjcg02
28-06-2004, 11:54:56
Todo probado y funcionando OK.

Gracias por todo.

Un saludo
PD: Si alguien tiene una idea más elegante al respecto, estaré encantado de recibir sugerencias...

jachguate
28-06-2004, 18:07:09
jmorán tiene toda la razón al respecto del redireccionamiento.

Te queda la opción de, en lugar de ejecutar un bat, invocar al interprete de comandos, que si interpretará correctamente la redirección y creará el archivo de texto.

El nombre del interprete se almacena en la variable de entorno COMSPEC, y le podes invocar con el parámetro /c.

algo como:

ShellExecute('c:\windows\command.com /c comando >archivo.txt', sw_hide);


Hasta luego.

;)

luigidean
30-08-2004, 02:54:25
He estado mirando este hilo y me ha parecido bastante interesante. He probado la ultima solucion que da jachguate pero a mi no me va. La que si me funciona es la que ponen mas arriba de pasar la cadena a un archivo .bat y luego ejecutar ese archivo .bat con el shellexecute.

Saludos y perdon por escribir como que 3 meses despues de la ultima respuesta de jachguate :rolleyes:

seoane
31-08-2004, 23:29:04
Si estas utilizando windows 2000 o windows XP en vez de command.com debes de utilizar cmd.exe, aunque lo mas correcto seria obtener el nombre y la direccion del interprete de comandos usando la variable de entorno COMSPEC

luigidean
02-09-2004, 00:49:33
No se lo que estoy haciendo mal pero me sigue sin funcionar. Lo que yo tengo en mi programa es esto:

ShellExecute(form1.Handle,'Open','c:\winnt\system32\cmd.exe /c dir >prueba.txt',nil,nil,SW_HIDE);

He buscado el fichero prueba.txt por el disco duro y no aparece por ningun lado.

saludos

seoane
02-09-2004, 17:07:41
En la función ShellExecute el nombre del ejecutable y los parámetros se pasan por separado. La forma correcta seria la siguiente:


ShellExecute(handle,nil,'cmd.exe','/c dir >c:\prueba.txt',nil,SW_HIDE);


Hasta luego

seoane
02-09-2004, 17:59:36
Estaba echándole otro vistazo a este hilo, y si lo que se quería al principio era recoger la salida de un programa, se puede hacer sin usar el interprete de comandos para que redirija su salida a un archivo y luego leer ese archivo.

Aquí os dejo un ejemplo de cómo recoger la salida del comando dir y colocarla en un Tmemo. En el formulario debe de haber un boton y un memo llamado memo1.


function IsWinNT: boolean;
var osv: OSVERSIONINFO;
begin
osv.dwOSVersionInfoSize := sizeof(osv);
GetVersionEx(osv);
result:= osv.dwPlatformId = VER_PLATFORM_WIN32_NT;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
buf: array[0..4095] of byte;
si: STARTUPINFO;
sa: SECURITY_ATTRIBUTES;
sd: SECURITY_DESCRIPTOR;
pi: PROCESS_INFORMATION;
newstdin,newstdout,read_stdout,write_stdin: THandle;
exitcod,bread,avail: Cardinal;
begin
if IsWinNT then
begin
InitializeSecurityDescriptor(@sd,SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl(@sd, true, nil, false);
sa.lpSecurityDescriptor := @sd;
end
else
sa.lpSecurityDescriptor := nil;
sa.nLength := sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle := true;
// Tuberias
if CreatePipe(newstdin,write_stdin,@sa,0) then
begin
if CreatePipe(read_stdout,newstdout,@sa,0) then
begin
GetStartupInfo(si);
with si do
begin
dwFlags := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;
wShowWindow := SW_HIDE;
hStdOutput := newstdout;
hStdError := newstdout;
hStdInput := newstdin;
end;
fillchar(buf,sizeof(buf),0);
GetEnvironmentVariable('COMSPEC',@buf,sizeof(buf)-1);
strcat(@buf,' /c dir');
if CreateProcess(nil,@buf,nil,nil,TRUE,CREATE_NEW_CONSOLE,nil,nil,si,pi) then
begin
memo1.lines.Clear;
GetExitCodeProcess(pi.hProcess,exitcod);
PeekNamedPipe(read_stdout,@buf,sizeof(buf)-1,@bread,@avail,nil);
while (exitcod = STILL_ACTIVE) or (bread > 0) do
begin
if (bread > 0) then
begin
fillchar(buf,sizeof(buf),0);
if (avail > sizeof(buf)-1) then
while (bread >= sizeof(buf)-1) do
begin
ReadFile(read_stdout,buf,sizeof(buf)-1,bread,nil);
memo1.lines.text := memo1.lines.Text + StrPas(@buf);
fillchar(buf,sizeof(buf),0);
end
else
begin
ReadFile(read_stdout,buf,sizeof(buf)-1,bread,nil);
memo1.lines.text := memo1.lines.Text + StrPas(@buf);
end;
end;
GetExitCodeProcess(pi.hProcess,exitcod);
PeekNamedPipe(read_stdout,@buf,sizeof(buf)-1,@bread,@avail,nil);
end;
end;
CloseHandle(read_stdout);
CloseHandle(newstdout);
end;
CloseHandle(newstdin);
CloseHandle(write_stdin);
end;
end;


Hasta luego

verm83
13-09-2004, 22:47:30
Este código que nos muestra seoane es muy válido, y funciona a la perfección, pero intento darle una pequeña vuelta de tuerca, y no sé cómo. Me explico: el programa muestra en el memo la salida del comando msdos, pero una vez éste acabado. Mi intención era mostrar en tiempo real lo que devuelve el comando, al igual que parar la ejecución del mismo en caso de no interesarme su ejecución.

¿Alguien podría echarme un cable?

Gracias anticipadas ;)