RE:Ayuda con el comando Shell!!!
LA FUNCION SHELL
La función Shell se utiliza para ejecutar un programa ajeno a la aplicación que se está ejecutando. Imaginemos que tenemos una aplicación Visual Basic que necesita, por ejemplo, establecer una comunicación telefónica, y que esa comunicación telefónica nos la realiza un programa desarrollado en C++ , llamado MARCADOR.EXE que funciona perfectamente y no queremos desaprovechar. Imaginemos que ese programa tiene la posibilidad de introducirle el número telefónico que debe marcar como un parámetro. Este parámetro se le introduce, supongamos, añadiendo el número al nombre del programa ejecutable. Por ejemplo:
MARCADOR.EXE 1234567
En nuestra aplicación Visual Basic introduciremos una línea invocando la función Shell seguida del nombre (y Path) del ejecutable y del parámetro que le vamos a introducir al ejecutable:
Shell "C:\VB\MARCADOR.EXE 080"
Mediante esta línea, lo que hacemos es ejecutar el programa MARCADOR.EXE e introducirle como parámetro el número a marcar. Resultado: el programa MARCADOR.EXE llama al número 080 (Bomberos), y una vez establecida la llamada podemos pasarle a ese Organismo datos o lo que nuestra aplicación haga.
Veamos que dice la Ayuda de VB respecto a la Función Shell:
Ejecuta un programa ejecutable.
Sintaxis Variable = Shell ( rutaDeAcceso [, estiloDeVentana] )
donde:
Variable es identificador de la tarea (ID)
rutaDeAcceso es el nombre del programa por Ejecutar (con su Path) y cualquier argumentos o conmutadores (switches) de línea de comando requeridos; puede incluir directorio o carpeta y unidad de disco. También puede ser el nombre de un documento que se ha asociado con un programa ejecutable.
estiloDeVentana es el número correspondiente al estilo de la ventana en la cual se va a ejecutar el programa. En Microsoft Windows, si se omite estiloDeVentana, el programa se inicia minimizado con enfoque.
El argumento con nombre estiloDeVentana tiene estos valores:
Constante Valor Descripción
vbHide 0 Se oculta la ventana y se pasa el foco a la ventana oculta.
vbNormalFocus 1 La ventana recupera el foco y vuelve a su posición y tamaño
original.
vbMinimizedFocus 2 La ventana se muestra como un icono con foco.
vbMaximizedFocus 3 La ventana se maximiza con foco.
vbNormalNoFocus 4 La ventana vuelve al tamaño y posición más recientes. La
ventana activa actual permanece activa.
vbMinimizedNoFocus 6 La ventana se muestra como un icono. La ventana activa actual permanece activa.
Comentarios
Si la función Shell ejecuta con éxito el archivo nombrado, devuelve la identificación de la tarea (ID) del programa iniciado. La ID de la tarea es un número exclusivo que identifica el programa en ejecución. Este número debe ser un Long. Si la función Shell no puede iniciar el programa nombrado, ocurrirá un error. Si desea conocer el ID de la tarea, realice una aplicación con un botón (cmbCalculadora) y un label (label1). Ponga en ese botón en su procedimiento click, el siguiente código. - Observe que esta aplicación inicia la calculadora de Windows -
Private Sub cmbCalculadora_Click()
Dim variable As Long
variable = Shell("C:\windows\calc.exe", 1)
label1.Caption = Str(variable)
End Sub
Posiblemente lo único que le importe sea el ejecutar esa aplicación, sin dar mayor importancia al ID de la tarea. Utilice una línea con la siguiente expresión :
Shell ("C:\windows\calc.exe"), 1
(Observe en las dos formas de ejecutar la función Shell, que la colocación de los paréntesis y la coma separadora es distinto.
El programa a ejecutar puede ser un programa Windows caso anterior de la calculadora) o un programa DOS.
Nota La función Shell ejecuta otros programas de manera asíncrona. Esto quiere decir que no se puede esperar que un programa iniciado con Shell termine su ejecución antes de que se ejecuten las instrucciones que siguen a la función Shell en la aplicación. Esto es un gran inconveniente de la función Shell. Excepto en contadas ocasiones, siempre es necesario conocer cuando se ha terminado de ejecutar el programa iniciado mediante Shell. Y no es ese el único problema. La mayoría de los programas DOS que se ejecutan con Shell no se cierran automáticamente. Esto significa que si podemos evitar el uso de Shell debe evitarse. Pero si es completamente necesario, tampoco pasa nada. Pero hay que controlar, tanto la terminación del proceso DOS como su cierre.
Podemos usar para ello APIs. No las hemos explicado todavía. Por eso, y adelantar un poco como se trabaja con ellas, vamos a presentar, sin grandes explicaciones, lo que hay que hacer para poder detectar que se ha terminado de ejecutar el programa DOS y para cerrarlo. Verá mas APIs mas adelante.
El programa DOS elegido para este ejemplo es el popular ARJ.EXE, un compresor de datos que, sin ánimo de publicidad, es uno de los mejores que existen. Pero trabaja solamente en DOS. Se utiliza un Procedimiento que he llamado ExecCmdNoFocus, para detectar que el proceso abierto para comprimir o descomprimir ha finalizado, y proceder a cerrarlo.
La declaración de las Apis y Constantes (En la sección de Declaraciones de un Módulo) es la siguiente:
Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As _ String, ByVal lpWindowName As String) As Long
Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hwnd As Long, _ ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal _ bInheritHandle As Long, ByVal dwProcessID As Long) As Long
Declare Function GetExitCodeProcess Lib "kernel32" (ByVal hProcess As Long, lpExitCode _ As Long) As Long
Declaramos las constantes
Public Const WM_CLOSE = &H10
Public Const STILL_ACTIVE = &H103
Public Const PROCESS_QUERY_INFORMATION = &H400
El Procedimiento podemos ponerlo en el Módulo anterior o en el formulario. Variará el tipo de declaración de las APIs:
Public Sub ExecCmdNoFocus(ByVal CmdLine As String)
(CmdLine es el parámetro que le vamos a pasar cuando invoque este procedimiento).
'Este procedimiento inicia un proceso en DOS y espera a que termine
'Una vez terminado este proceso, cierra la ventana, que se mostrará minimizada y sin foco
Declaramos las variables locales en ese procedimiento
Dim hProcess As Long 'handle del proceso donde se invoca la función Shell
Dim RetVal As Long 'Valor donde la función GetExitCode coloca el resultado
Dim winHwnd As Long ' manipulador de la ventana que contenga el Caption
‘Finalizado - ARJ
Dim RetValls As Long 'valor de retorno de PostMessage
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, False, Shell(CmdLine, _
vbMinimizedNoFocus))
Do
GetExitCodeProcess hProcess, RetVal
Sleep 100
'en este apartado comprueba si está abierta la ventana "Finalizado - ARJ"
winHwnd = FindWindow(vbNullString, "Finalizado - ARJ")
If winHwnd <> 0 Then
RetValls = PostMessage(winHwnd, WM_CLOSE, 0&, 0&)
End If
Loop While RetVal = STILL_ACTIVE
End Sub
La ventana DOS del ARJ tiene el Caption Finalizado - ARJ cuando ya ha terminado el proceso. En el procedimiento ExecCmdNoFocus se analiza si esa ventana está presente (prueba de que ARJ ya ha terminado, pues antes de terminar tiene otro Caption).
Para llamar a ese procedimiento hay que citarle por su nombre (ExecCmdNoFocus) que como lo hemos declarado Public en un Módulo, podemos llamarle desde cualquier parte de la aplicación. Debemos pasarle el parámetro CmdLine, que será el programa que vamos a ejecutar con Shell y los parámetros adicionales que este programa necesite (En este caso, el programa es ARJ.EXE y a continuación debe indicársele el nombre del archivo ya comprimido, a continuación a para que añada mas ficheros a ese archivo, y a continuación el nombre de ese fichero o ficheros a añadir :
El parámetro CmdLine del procedimiento es todo lo que va entre paréntesis.
ExecCmdNoFocus ("C:\DirA\ARJ.EXE a C:\DirB\Fichero1.Ext")