Windows Script Host para Desarrolladores Visual FoxPro
Windows Script Host para Desarrolladores Visual FoxPro
Pgina 1 de 23
| Home | Worldwide
Buscar en Microsoft.com:
Ir
Home Productos y Tecnologas MSDN Suscripciones Arquitectura Centros de Desarrollo Informacin Tcnica MSDN Acadmico Universidad .NET Eventos MSDN Media Center Comunidad Online Partnering y Certificacin TechNet Soporte Tcnico
Descargue el cdigo fuente (19 Kb).
Introduccin
Si frecuenta algunos de los muchos foros y grupos de noticias acerca de VFP, debe haber visto ltimamente un nmero de referencias a Windows Script Host ( WSH). El WSH es una poderosa herramienta que puede poner a trabajar desde VFP y ayuda a simplificar el cdigo. De hecho, para lograr algunas de las cosas que puede hacer con l, podra incluso tener que escribir una DLL en C. En realidad, Windows Script Host puede separarse en dos reas diferentes. Primero, el componente de scripting que le permite escribir programas usando VBScript o JScript. stos puede ejecutarse bajo el control de uno de los ejecutables del scripting host, y pueden ser utilizados para crear objetos COM a travs de compilacin con el compilador de WSH. Segundo, una serie de objetos COM que son incluidos con la distribucin de WSH que expone varias funcionalidades importantes de Windows que de otra forma requeriran el uso de la API de Win32. Es este juego de objetos COM el que es inmediatamente de mayor inters para el desarrollador VFP, ya que pueden ser usados dentro del contexto de una aplicacin VFP. El propsito de este artculo no es el de ser un curso de WSH. Eso requerira un libro, y de hecho, existe al menos uno sobre el tema. Mencionaremos los detalles del libro ms adelante en esta nota junto con otras referencias que puede examinar. Lo que haremos aqu es una resea sobre WSH y qu ha sido diseado para hacer. Inclusive, tampoco intentaremos ser definitivos acerca de los objetos y sus PEMs. Nos limitaremos a las cosas que no se pueden hacer con VFP, o aquellas que solucionan, de alguna manera, falencias de comandos existentes.
Qu es WSH
WSH fue diseado para cubrir una necesidad que exista desde la primer encarnacin de Windows: archivos por lotes propios. Ciertamente, los archivos por lotes tradicionales de DOS an pueden usarse, pero hacerlo requiere que se abra una ventana de comandos y lo que puede lograr es considerablemente ms complejo que lo que podra con un lenguaje de programacin de ms alto nivel. WSH tambin
http://www.microsoft.com/spanish/msdn/comunidad/mtj.net/voices/art03.asp
26/04/2006
Pgina 2 de 23
provee acceso a muchas de las funciones internas de Windows (lo que no es posible desde DOS) y lo hace a travs de dos lenguajes de scripting, VBScript y JScript, desde Windows mismo o a travs de la consola (la ventana de DOS). Esta funcionalidad se accede a travs de los ejecutables WSCRIPT.EXE, que ejecuta scripts como aplicaciones Windows, y CSCRIPT.EXE, que lo hace como aplicaciones de consola. Si usamos scripting en nuestro trabajo? Por supuesto! Luego de dos catstrofes de red, donde los supuestos backups no existan (contrariamente a lo que nos haban dicho), destruyeron literalmente aos de trabajo, movimos nuestros directorios de desarrollo a discos locales. Ahora, diariamente, utilizamos un script para copiar el trabajo de vuelta a la red. De esta forma obtenemos doble proteccin. Si mis discos locales estallan, existen copias en la red, y en el caso de que tanto nuestras mquinas como la red estallaran, supuestamente, existen copias de resguardo en cinta. Pero como juega VFP en esto? Ya que WSH expone su funcionalidad como un objeto COM, cualquier aplicacin que pueda usar COM puede aprovecharlo. Como VFP no tiene problemas en ese rea, es otra herramienta que merece consideracin.
http://www.microsoft.com/spanish/msdn/comunidad/mtj.net/voices/art03.asp
26/04/2006
Pgina 3 de 23
Si utiliza el Instalador de Visual Studio, la opcin pos-instalacin no est disponible. En este caso, deber utilizar el mismo cdigo para hacerlo desde su aplicacin. Tratar de instalar Windows Script Host desde el ejecutable auto-extrable apropiado es algo seguro an si ya est instalado en sus sistema; tenga en cuenta que registrar un nmero de componentes, por lo que bajo windows NT y 2000 el usuario debe ser capaz de crear entradas en la Registry bajo HKEY_CLASSES_ROOT. En un ambiente seguro, no todos los usuarios tendrn los premisos necesarios para hacerlo. Dentro de lo posible, trate de instalar con un usuario que tenga permisos de Administrador local. La segunda "contra" es que hay una sobrecarga adicional al usarlo que no ocurrira de otra manera. Esto es causado principalmente por la sobrecarga de llamar a un servicio COM. El objeto debe ser instanciado, y luego manipulado. Cada referencia a un mtodo, propiedad o coleccin expuesta por los objetos COM de WSH involucra pasar datos a travs de una interfaz COM. En general, la llamada a COM agrega una sobrecarga que una llamada directa a la API o a una funcin nativa de VFP no incurrira, y tardar ms en completarse que utilizar un comando de FoxPro equivalente, a veces por un orden de magnitud. Sin embargo habr circunstancias en que los comandos nativos carecen de una funcionalidad presente en WSH, o simularla lleva a una carga adicional que anula este tema. En cualquier caso, la decisin final queda en usted. Determine si el cdigo adicional para instalarlo o el tiempo adicional de proceso es significativo o no.
Arrancando
Esto termina la introduccin. Si quiere comenzar antes de seguir con el resto de este artculo, aqu hay ms recursos que puede investigar. Actualmente, el mejor (en nuestra opinin) libro sobre WSH es The Windows Script Host Programmers Reference de Dino Esposito, publicado por Wrox Press (ISBN 1-861002-65-3). Sin embargo, est orientado hacia el programador VB/VBA/VBScript. Si no los conoce, o simplemente no sabe a esta altura si WSH es para usted o no, hay otras referencias, gratuitas. La MSDN Library viene con dos archivos, vbscrip5.chm y wsh.chm, que contienen la informacin en la que se basa este artculo. Una suscripcin gratuita por un ao a esta biblioteca est disponible para los usuarios registrados de VFP. Vea http://msdn.microsoft.com/subscriptions/offer/faq.asp para ms detalle. Vbscrip5.chm contiene una introduccin a VBScript y tambin informacin sobre WSH. Desde el punto de vista de los mismos componentes COM, y scripting detallado usando VBScript, The VBScript Programmer's Reference, tambin de Wrox Press (ISBN 1-861002-71-8), provee un resumen comprensivo sobre VBScript y los componentes COM de WSH, con ejemplos concretos sobre cmo usarlos para lograr un nmero de tareas. Su Apndice trae una tremenda cantidad de informacin, incluyendo resmenes de los componentes COM de WSH, los modelos de objetos de los browsers IE4 e IE5, ADO y el lenguaje VBScript. La direccin del sitio web de Wrox es: http://www.wrox.com. Finalmente, hay una cantidad de sitios web dedicados a WSH, y tecnologa de Windows Scripting en general. El no-oficial WSH FAQ Site, http://wsh.glazier.co.nz/, es un recurso tremendo. Microsoft ha dedicado un rea de su servicio MSDN Online a las tecnologas de Windows Scripting; http://msdn.microsoft.com/scripting/default.htm?/scripting/windowshost/default.htm es la entrada a todas ellas.
http://www.microsoft.com/spanish/msdn/comunidad/mtj.net/voices/art03.asp
26/04/2006
Pgina 4 de 23
En la primer parte hicimos una introduccin general a Windows Script Host. Ahora entraremos en algunas aplicaciones prcticas con VFP. Asumiremos que ya tiene el WSH instalado, pero no que haya profundizado en ninguno de los recursos y documentacin que mencionamos antes. Todos los ejemplos que siguen pueden ser ejecutados directamente desde la ventana de comandos de VFP. Decidir cul de los objetos de WSH describir primero fue, para nosotros, una decisin simple y clara. El Shell de Windows es el punto central del Windows mismo. Cada vez que lanza un programa usted est, de una forma u otra, interactuando con el Shell. Incluso, an antes de que su aplicacin corra por primera vez, su programa de instalacin interacta con l. As que parece por completo apropiado comenzar esta parte discutindolo. Una nota es adecuada en este punto. El objeto Shell expuesto por WSH no es el mismo que el objeto Shell.Application. Aunque hay cierta funcionalidad superpuesta, son objetos completamente distintos. Las tcnicas descriptas aqu se aplican slo al objeto de WSH. El objeto COM WScript.Shell expone mtodos para mantener accesos directos, identificar carpetas relativas al sistema sin importar cuestiones de instalacin, e interactuar con documentos y aplicaciones externas.
http://www.microsoft.com/spanish/msdn/comunidad/mtj.net/voices/art03.asp
26/04/2006
Pgina 5 de 23
Una vez que obtuvo la ubicacin del escritorio, el siguiente paso es crear el archivo de enlace al acceso directo. Puede hacerlo creando un objeto Link (enlace). oLink = oShell.CreateShortcut(lcdesktop + "\Mi Super Aplicacin.lnk") El cdigo de arriba devuelve un objeto referenciado al archivo de enlace, pero realmente no pone nada en el escritorio o en un grupo de programas. Antes de que esto ocurra, hay ms trabajo que hacer. Primero debe indicar el destino del acceso directo (el ejecutable), indicar qu icono usar, cul es el directorio de inicio, fijar el tipo de ventana, indicar argumentos o parmetros especiales, y si desea, una tecla de mtodo abreviado. El cdigo de abajo asigna valores a cada uno de stos: * Indica el destino. lcFile es nombre de archivo con la ruta completa oLink.TargetPath = lcfile * Fija el icono oLink.IconLocation = lcfile * Fija el directorio de trabajo oLink.WorkingDirectory = JUSTPATH(lcfile) * Fija el estilo de ventana como maximizada oLink.WindowStyle = 3 * Cualquier argumento opcional oLink.Arguments = "" && En este caso nada * Tecla opcional de mtodo abreviado oLink.Hotkey = "" && Cualquier cadena comenzando con Ctrl+Alt+ [ letra ] * Guarda el acceso directo oLink.Save() Una vez que invoca el mtodo Save, su acceso directo est listo. Hay una cosa ms para aclarar. La propiedad WindowStyle es usualmente una de las constantes definidas abajo.
http://www.microsoft.com/spanish/msdn/comunidad/mtj.net/voices/art03.asp
26/04/2006
Pgina 6 de 23
SW_HIDE 0 && La ventana no se muestra, sea cauto con esto SW_SHOWNORMAL 1 SW_MINIMIZED 2 SW_MAXIMIZED 3
Es bastante fcil, verdad? Este no es el nico tipo de acceso directo que el Shell puede crear. Pruebe lo siguiente: * Crea un acceso directo oLink = oShell.CreateShortcut( lcdesktop + "\Portada del VFUG.url" ) * Fija el destino oLink.TargetPath = "http://www.vfug.org" * Guarda oLink.Save() Ahora tiene en el escritorio un hipervnculo a la portada del Virtual FoxPro User Group. Las diferencias son bien fciles de aseverar. Primero, el acceso directo tiene la extensin "url" en lugar de "lnk". Segundo, la nica propiedad que debemos indicar es la ruta de destino; en este caso, la URL. Hay otra cosa para notar. Si el enlace ya existe, obtiene una referencia al mismo. Esto le permite modificar los existentes.
No "corra" todava
Otro mtodo til del Shell es la habilidad de ejecutar otra aplicacin. Si, ya sabemos que el comando RUN de VFP puede hacer lo mismo, pero el Shell puede hacer ms. Primero, el comando RUN slo puede ejecutar programas. Si le pasa al mtodo Run del Shell el nombre de un archivo, ste lo abrir en la aplicacin apropiada. Segundo, el mtodo Run tambin puede esperar a que el programa termine. La sintaxis es muy directa. oShell.Run( archivo, estado de la ventana, [ espera para terminar ]) As que para ejecutar C:\Mydir\Mytext.txt en una ventana normal y esperar a que sea cerrada: oShell.Run("C:\Mydir\Mytext.txt", SW_NORMAL, .T.) Para continuar procesando: oShell.Run("C:\Mydir\Mytext.txt", SW_NORMAL, .F.)
http://www.microsoft.com/spanish/msdn/comunidad/mtj.net/voices/art03.asp
26/04/2006
Pgina 7 de 23
oShell.Run("C:\Mydir\Mytext.txt", SW_NORMAL) Funcionarn bien. Note que aqu se aplican las mismas constantes mostradas previamente. Una vez que la aplicacin se ha iniciado, a veces es necesario traerla al frente para darle prioridad y dirigir a ella la interfaz de usuario. El mtodo AppActivate permite asignar el foco del sistema a una ventana basndose en su ttulo. AppActivate acepta un solo parmetro: el ttulo de la ventana a traer al frente. El criterio de seleccin es resuelto como sigue: Si el ttulo coincide exactamente con el indicado, esa ventana es trada al frente. Si ninguna coincide exactamente, Windows revisa para ver si alguna comienza con la cadena indicada. No se garantiza ningn orden o nivel de coincidencia; la primer ventana comenzando con la cadena es trada al frente. Si ninguna comienza con la cadena, se revisan nuevamente para ver si alguna termina con la strin; la primera que termine con ella es trada al frente. Si no hay coincidencia alguna, la funcin devuelve .F. Adems de traer la aplicacin al frente, Wscript.Shell provee un mecanismo para dirigir las pulsaciones de tecla a la aplicacin que est al frente. SendKeys le permite enviar todas salvo un pequeo juego de teclas de sistema reservadas, como Ctrl-Alt-Del y Alt-PrtSc, hacia la aplicacin del frente. Esto le da al objeto Wscript.Shell la habilidad de interactuar con otra aplicacin de la misma manera en que KEYBOARD le permite a una aplicacin VFP enviarse teclas a s misma. La ejecucin de un script contina mientras el mismo corre como una tarea en segundo plano. Ahora pongamos todo esto junto para enviar teclas a una aplicacin. Como se describi arriba, necesitaremos ejecutar una aplicacin, activarla, y finalmente enviarle las pulsaciones de tecla deseadas. Sin embargo, hay un pequeo problema: A la aplicacin le lleva un lapso pequeo para estar activa. Si no lo consideramos, VFP terminar enviando las teclas a s mismo, lo que no es deseable. El objeto WSH mismo tiene un mtodo, Sleep, que permite a un script detenerse brevemente para lograr esto. Sin embargo, en VFP no tenemos acceso a l. De todas maneras, este mtodo mapea una llamada de la API que podemos llamar simplemente. El siguiente cdigo (que puede escribir en un nuevo archivo de programa), ejecuta y luego activa la aplicacin Notepad, y finalmente le enva teclas. DECLARE Sleep IN Win32API; INTEGER dwMilliseconds oShell.Run("Notepad") oShell.AppActivate("Sin ttulo - Bloc de notas") = Sleep(100) && Detiene al VFP por una dcima de segundo oShell.SendKeys("Esto manda una frase al Bloc de notas desde VFP.~") Habr notado la tilde al final de la cadena que estamos pasando. Representa la tecla Enter. Para una lista de los carcteres especiales disponibles en WSH, lea sobre el mtodo SendKeys en el archivo WSH.CHM de la biblioteca MSDN. Antes de terminar esta parte, debemos notar que lo mencionado arriba slo ha sido probado desde la ventana de comandos o un archivo de
http://www.microsoft.com/spanish/msdn/comunidad/mtj.net/voices/art03.asp
26/04/2006
Pgina 8 de 23
programa con el cdigo necesario resaltado y ejecutndolo a travs del men de contexto. A pesar de que parece funcionar como se describe, recomendamos a todo lector que lo pruebe por si mismo. El Shell tambin soporta un mtodo PopUp() que despliega los mismos dilogos que la funcin MessageBox() de VFP, pero con un parmetro de tiempo de expiracin. Desafortunadamente, mientras el cuadro de dilogo expira apropiadamente al ejecutarlo desde un archivo VBScript, no lo hace desde VFP.
http://www.microsoft.com/spanish/msdn/comunidad/mtj.net/voices/art03.asp
26/04/2006
Pgina 9 de 23
El parmetro opcional forzar puede ser .T. .F. y determina si carpetas con el atributo de slo lectura son borradas o no. El nico error que puede ocurrir es que no exista la carpeta indicada por la cadena pasada. GetDrive - Devuelve un objeto drive. oDrive = oFSO.GetDrive("C:\") GetFile y GetFolder - Devuelven un objeto archivo o carpeta desde el FileSystemObject. Ninguno soporta meta carcteres. oFile = oFSO.GetFile("C:\UnaCarpeta\UnArchivo.txt") oFolder = oFSO.GetFolder("C:\") GetSpecialFolder - Devuelve objetos de las carpetas de Windows, Windows/System o la de temporales de Windows. Para recuperar estos valores: 0 - La carpeta Windows 1 - La carpeta Windows/System 2 - La carpeta temporal de Windows Son los valores a pasar. Por ejemplo, para obtener la carpeta de temporales de Windows: loFolder = oFSO.GetSpecialFolder(2) Devuelve una referencia a un objeto con la carpeta de archivos temporales de Windows. El Windows Script Host Programmers Reference indica que el valor devuelto es una cadena; sin embargo, la ltima versin en el sitio de Microsoft devuelve un objeto. Los objetos carpeta se describen ms adelante en esta seccin. Esto no debe confundirse con los mtodos del objeto del Shell de WSH SpecialFolders descriptos en la seccin anterior. Usar un parmetro distinto de los listados arriba generar un error. MoveFile - Tiene dos usos: mover y renombrar. La sintaxis bsica es: oFSO.MoveFile(< archivo origen >, < archivo destino >) MoveFolder - Este mtodo tambin tiene dos usos. Primero, como su nombre lo indica, realizar un recorte y pegado, moviendo una carpeta a una ubicacin diferente. Segundo, y quizs ms importante, puede renombrar una carpeta existente. Si utiliza MoveFolder con una sintaxis como la siguiente: oFSO.MoveFolder("C:\Origen", "D:\Destino") Es similar a usar el Explorador de Windows para cortar y pegar entre las carpetas de origen y destino. Nuevamente, no se muestra dilogo de
http://www.microsoft.com/spanish/msdn/comunidad/mtj.net/voices/art03.asp
26/04/2006
Pgina 10 de 23
progreso. Lo mismo es cierto para la sintaxis: oFSO.MoveFolder("C:\Origen", "C:\Destino\Origen") Sin embargo, si usara: oFSO.MoveFolder("C:\Origen", "C:\Destino") La carpeta "fuente" es renombrada como "Destino". Esto, por supuesto, es de uso limitado ya que puede lograr lo mismo con el objeto carpeta. Ahora que hemos cubierto los mtodos, miremos los objetos.
http://www.microsoft.com/spanish/msdn/comunidad/mtj.net/voices/art03.asp
26/04/2006
Pgina 11 de 23
He aqu algunas otras propiedades del objeto drive que puede encontrar tiles. Salvo que se indique especialmente, son de slo lectura. AvailableSpace y FreeSpace - Son dos propiedades separadas. AvailableSpace devuelve el espacio disponible para el usuario. FreeSpace, el espacio total libre. Desafortunadamente, stos y TotalSpace ms abajo, no siempre devuelven valores correctos. Como DISKSPACE() en VFP, limitan el valor de retorno a 2 gigabytes bajo Win9x. Bajo Windows 2000 y Windows Me, trabajan correctamente. Esto est documentado en el artculo Q225032 de la Base de Conocimientos de Microsoft. FileSystemProperty - Una cadena representando el nombre del sistema de archivos. Por ejemplo: FAT32. RootFolder - Devuelve un objeto representando la carpeta raz del drive. SerialNumber - El nmero de serie del disco. ShareName - El nombre compartido del drive, si se corresponde. Devuelve una cadena vaca en una computadora no conectada en red. TotalSize - El tamao total de drive. Sin embargo, existe el mismo problema con esta propiedad bajo Win9x que con AvailableSpace y FreeSpace. VolumeName - (Lectura/Escritura) Aunque puede obtener el nombre del volumen con la funcin ADIR(), no puede cambiarlo. Como esta propiedad es de lectura y escritura, esta limitacin no est presente aqu.
Carpetas/Archivos Colecciones/Objetos
Como las Carpetas y Archivos comparten tantos mtodos y propiedades, es apropiado que los describamos al mismo tiempo. A menos que se indique de otra manera, lo que discutamos aqu se aplica a ambos objetos. Sin embargo hay una diferencia particular que debe ser tenida en cuenta inmediatamente. Una carpeta puede contener dos colecciones: Subcarpetas y Archivos, por las que puede iterar. Naturalmente, un objeto Archivo no tiene colecciones. Para iterar por ellos: oFolder = oFSO.GetFolder("C:\") FOR EACH oSub IN oFolder.SubFolders ? oSub.Name NEXT FOR EACH oFile IN oFolder.Files ? oFile.Name NEXT Esto desplegar la propiedad Name de cada subcarpeta y archivo en la carpeta. Tanto la coleccin de Carpetas como la de Archivostienen propiedades Count e Items. La propiedad Count devuelve el nmero de tems en la coleccin. La propiedad Item devuelve una referencia al objeto cuando su nombre es indicado. Por ejemplo: oFolder = oFSO.GetFolder("C:\") oSubFolders = oFolder.SubFolders
http://www.microsoft.com/spanish/msdn/comunidad/mtj.net/voices/art03.asp
26/04/2006
Pgina 12 de 23
Asumiendo que tiene una referencia a un archivo o carpeta, puede usar las funciones de manejo de bits de VFP para modificar los atributos. Sin embargo, no intente modificar el atributo directorio, ya que es de slo lectura. Para alternar la propiedad read-only (slo lectura) de un archivo, por ejemplo: * Se aplica a un objeto archivo o carpeta OFile.Attributes = BITXOR(oFile.Attributes, READONLY) DateCreated, DateLastAccessed, DateLastModified - Propiedades de slo lectura que devuelven un valor datetime. Note que estas propiedades no estn disponibles para carpetas raz. La fecha de la ltima modificacin est disponible en VFP; sin embargo, WSH brinda un mtodo eficiente de leer esa informacin ya que slo una llamada a una funcin es requerida antes de tener el dato datetime para comparar. Este tipo de comparacin es necesaria si est usando una programa "lanzador" para copiarla nueva versin de un archivo desde un drive de red. Con WSH todo lo que necesita, luego de crear el objeto FileSytemObject, es: oLocal = oFSO.GetFile(lclocal) oRemote = oFSO.GetFile(lcremote) IF oRemote.DateLastModified > oLocal.DateLateModified * Copiar el archivo ENDIF Drive - Devuelve un objeto drive representando el drive en que est un archivo o carpeta. IsRootFolder - Se aplica slo al objeto carpeta. Es n valor lgico que indica si sta es o no la raz. Name - Propiedad de lectura y escritura para un archivo o carpeta. Puede usarse en VFP para modificar el nombre de un directorio. El valor
http://www.microsoft.com/spanish/msdn/comunidad/mtj.net/voices/art03.asp
26/04/2006
Pgina 13 de 23
devuelto es slo el nombre del archivo o carpeta y no incluye la ruta. Para cambiar el nombre de un directorio, una vez que tiene el objeto referencia a la carpeta, simplemente: oFolder.Name = lcNuevoNombre Realiza el truco. ParentFolder - Devuelve un objeto representando la carpeta padre de un archivo o carpeta. Path - Devuelve la ruta completa de un archivo o carpeta. ShortName - El nombre corto (8 carcteres mximos como nombre primario y tres mximos como extensin). Es equivalente al nombre de archivo MS-DOS. ShortPath - El nombre corto de la ruta como se usara en MS-DOS. Size - El tamao total de un archivo o carpeta. En el caso de las carpetas, acceder a esta propiedad puede tomar algo de tiempo ya que se calcula el tamao total de todas las subcarpetas y sus archivos. Esto puede ser til al copiar a otro dispositivo, ya que elimina la necesidad de crear una rutina recursiva para hacerlo. Type - El tipo como aparecer en el Explorador de Windows.
http://www.microsoft.com/spanish/msdn/comunidad/mtj.net/voices/art03.asp
26/04/2006
Pgina 14 de 23
NEXT Hay un par de cosas para notar aqu. Primero, el objeto drive devuelto por el mtodo no es el mismo devuelto por el mtodo GetDrive() de Scripting.FileSystemObject. Segundo, que el objeto es de tipo enumerado con base cero. La propiedad Count, por lo tabto, devuelve el nmero tems, pero el valor mximo legal que puede tomarse es uno menos que el total ya que la enumeracin comienza en cero en lugar de uno. Esta informacin es similar a la devuelta por ANETRESOURCES(), excepto que no se requiere ningn nombre de red y no devuelve impresoras. WSH provee mtodos para mapear y remover drives. La sintaxis para mapear un drive es: oNet.MapNetworkDrive( letra del drive, recurso compartido[[, actualizar perfil], usuario, contrasea]) Arriba, slo el drive y recurso compartido, como cadenas, son requeridos. El parmetro actualizar perfil es un valor lgico, indicando si el mapeo es almacenado o no en la informacin del perfil, y es automticamente restaurado (mapeado) cuando la computadora vuelve a encenderse. Los parmetros usuario y contrasea deben ser pasados para permitir el mapeo de drives que no han sido accedidos previamente. Naturalmente, como WSH brinda un mtodo para mapearlos, tambin tiene otro para desconectar los drives de red. La sintaxis es: oNet.RemoveNetworkDrive( nombre [, forzar ][, [ actualizar perfil ]]) El parmetro name toma dos formas: el nombre local o el remoto. Cul usa depende de si el drive est o no mapeado. Si lo est, entonces el parmetro debe ser la letra del drive. Si por el contrario slo est conectado al servidor sin estar mapeado, entonces toma el nombre remoto. Por ejemplo, si utiliza la opcin Desconectar Unidad de Red del Explorador de Windows, desmapea el drive, pero an est conectado al servidor. En este caso, use el nombre remoto para desconectarse. El parmetro forzar, al pasarse en .T., remueve el recurso est o no en uso. Actualizar perfil tambin es un valor lgico y puede usarse, al pasarse en .T. para remover el mapeo automtico del drive cuando la computadora se reinicia. Desafortunadamente no existe un mtodo en WSH para recuperar los drives a los que un usuario se ha mapeado en el pasado. Si se conocen los nombre de los recursos compartidos, esto no representa un problema. Sin embargo, si no se conocen, puede serlo. Para resolverlo, debe usar la API de Windows. Ed cre una clase, NetResource, para lograrlo. Como las estructuras involucradas requieren punteros a cadenas embebidos, su clase CLSHeap tambin es necesaria. Ambos archivos estn disponibles para descarga aqu y tambin puede hallarse en diversos recursos web especializados en VFP.
http://www.microsoft.com/spanish/msdn/comunidad/mtj.net/voices/art03.asp
26/04/2006
Pgina 15 de 23
FOR lni = 0 TO oPrinters.Count-1 ? oPrinters.Item(lni) && Muestra NEXT FOR lni = 1 TO oPrinters.Count-1 ? oPrinters.Item(lni) && Muestra NEXT
Esta informacin, sin embargo, es idntica a la devuelta por la funcin APRINTERS(). Los otros cuatro mtodos vinculados con impresoras no tiene equivalente directo en VFP. Son: AddPrinterConnection, AddWindowsPrinterConnection, RemovePrinterConnection, y SetDefaultPrinter. Los dos primeros parecen, y son, similares. La forma ms fcil de ver y entender las diferencias es verlos a ambos lado a lado: oNet.AddPrinterConnection( puerto, nombre remoto [[, actualizar perfil], usuario, contrasea]) AddPrinterConnection() mapea una impresora de red a un nombre de dispositivo local - puerto fsico o identidad de dispositivo, que puede ser usado por aplicaciones DOS y Windows. El primer argumento, puerto, especifica el nombre del dispositivo local a ser asociado con la impresora de red; puede usar un nombre de puerto como LPT1: (el rango de puertos soportados vara segn la versin del sistema operativo; en general, al menos 8 dispositivos LPT puede ser mapeados, y este nmero puede ser incrementado esditando las entradas del registro asociadas con los nombre de dispositivos, o en WinNT/Win2K, usando el cuadro de Puertos del Panel de Control. El segundo argumento, remote name, es el nombre de red asociado con el dispositivo de impresin. ste debe ser un UNC, en la forma \\NombreServidor\RecursoCompartido; NombreServidor ser el nombre NetBios de un sistema en su red, o bajo Windows NT o Windows 2000, puede ser la direccin IP del servidor. RecursoCompartido ser un nombre nico publicado por el servidor que identifica el dispositivo compartido en, algunos casos controlado por , la mquina servidora. Esta convencin de nombres se aplica an al usar otros clientes que el MSNetwork Client; un servidor administrado por NetWare managed server tendr el noombre \\NombreServidorImpresoras\NombreCola desde el entorno de NetWare. Determinar el nombre desde NDS puede ser un poco complicado; contacte a su administrador de red si el UNC de la impresora no es inmediatamente aparente. Actualizar perfil es una valor lgico que indica si el mapeo del dispositivo debe restaurarse cada vez que Windows se reinicia, Si la conexin de la impresora debe ser una asociacin permanente, necesita para .T. Usuario y contrasea son parmetros opcionales; si son especificados, son pasados al servidor o sus servicios de autenticacin para establecer la conexin. Si no se especifican, el nombre de y contrasea de Windows (o la autenticacin de dominio si est en un entorno de dominio) sern pasados para pedir acceso a la impresora. Si la impresora es compartida desde un sistema Windows, especialmente NT o Win2K, es probable que los controladores de la impresora estn almacenados en el servidor, y automticamente se carguen al conectar. Los sistemas Win9x usualmente slo tienen a mano controladores Win9x para la impresora compartida; un NT o Win2K con toda probabilidad le pida que seleccione un controlador y lo cargue de un disco provisto por el fabricante, o del juego de controladores que vienen con el sistema operativo. Las impresoras compartidas por un
http://www.microsoft.com/spanish/msdn/comunidad/mtj.net/voices/art03.asp
26/04/2006
Pgina 16 de 23
sistema no-MS, como un servidor de impresin administrado por NetWare, usualmente no tienen a mano controladores para un sistema Windows; deber identificar e instalar el controlador para el nuevo dispositivo cuando sea referenciado por un sistema. * Windows NT/2000 oNet.AddWindowsPrinterConnection(nombre remoto) AddWindowsPrinterConnection bajo WinNT y Win2K permite a Windows conectarse a una impresora remota sin asignarle un puerto. Ser slo direccionable como una Impresora Windows - las sesiones DOS no podrn accederlas. Asume que tomar el controlador apropiado de la impresora del recurso compartido; sino, y ningn controlador est preinstalado, ser pedida la seleccin de un controlador apropiado para la Impresora Windows. * Windows 9x/Me oNet.AddWindowsPrinterConnection( nombre remoto, controlador[, puerto] ) Bajo Win9x y WinME, el comportamiento de AddWindowsPrinterConnection() vara dramticamente. Primero, un controlador explcito debe ser especificado al agregar una impresora; una falla en hacerlo ocasionar que la llamada a la funcin falle. Opcionalmente, un puerto local debe ser asignado a la conexin; si lo es, la impresora ser visible para Win16 y las VDMs virtuales y las aplicaciones Win32. Si falla en especificar el resultado del puerto resultar en que el dispositivo sea invisible para las VDMs.
RemovePrinterConnection
Adems de crear nuevos mapeos de impresora, puede liberar aquellos asignados al sistema local como impresoras de red. RemoveNetWorkPrinter hace exactamente sto: oNet.RemovePrinterConnection( strNombre [,Forzar] [,Actualizar]) Strname es el nombre de la impresora que desea desasociar del sistema local. Si us AddWindowsPrinterConnection, se especifica el UNC del recurso compartido. Si us AddPrinterConnection, se debe especificar el puerto mapeado al dispositivo. Forzar indica que la impresora debe desconectarse incondicionalmente sin importar la condicin o actividad de la cola. Si existe alguna duda, Forzar debe pasarse en .T. Actualizar indica si el desmapeo es una desconexin permanente o no - en otras palabras, ya no se volver a tratar de mapear la impresora al reiniciarse Windows. Uselo para desconectar permanentemente un impresora de red adosada automticamente.
http://www.microsoft.com/spanish/msdn/comunidad/mtj.net/voices/art03.asp
26/04/2006
Pgina 17 de 23
Mientras la documentacin indica que este mtodo slo funciona con impresoras remotas, esto es incorrecto. Funciona tambin con impresoras locales, siempre que las mismas hayan sido instaladas. Ahora, supongamos que quiere cambiar la impresora predeterminada, y luego restaurar la original. El cdigo de abajo supone que el nombre de su impresora es "MyPrinter". lcdefault = SET('PRINTER", 2) && Obtiene la impresora predeterminada actual oNet.SetDefaultPrinter("MyPrinter") REPORT FORM Myreport.frx TO PRINTER NOCONSOLE oNet.SetDefaultPrinter(lcdefault) El intrprete de expresiones regulares Cuando empezamos este artculo explicamos que una manera de saber si WSH ya estaba instalado era chequear la presencia de el ProgID del Intrprete de expresiones regulares en la registry. Por lo tanto, parece adecuado que concluyamos con l. En el transcurso, usaremos ejemplos que pueden ser implementados ms directa y fcilmente a travs de las funciones de cadena de FoxPro. El propsito de estos ejemplos no es de ninguna manera sugerir que la funcionalidad del intrprete deba ser utilizada en su lugar. Estos ejemplos intentan simplemente demostrar el "cmo" y explicar el "porqu" del intrprete, y en honor a la claridad, han sido enormemente simplificados. No es nuestra intencin aqu demostrar un gran nmero de posibilidades, o incluso comenzar a cubrirlas. Hay tantas combinaciones posibles que cualquier intento sera intil. Lo que cubriremos es el uso fundamental del intrprete, dando algunos ejemplos del mundo real y dejando el resto librado a su imaginacin. Lo alentamos sinceramente a acceder al menos al archivo de ayuda VBScrip5.chm que lo cubre. Su uso, junto con su propia experimentacin con el objeto en VFP, le brindar muchos ms ejemplos de los que nosotros podamos proveerle. Finalmente, si tiene problemas con el intrprete, pregunte en cualquiera de los foros en lnea. Se estar preguntando que son exactamente las expresiones regulares. En pocas palabras, son cualquier cadena que sigue un patrn predeterminado. El intrprete puede fcilmente hacer modificaciones y validaciones sobre esas cadenas, como mostraremos en breve. Esto puede usarse para algo como validad una direccin de email o una URL segn el formato apropiado. Mostraremos eso y ms. En primer lugar, sin embargo, obtengamos una referencia al objeto que har todo esto posible: oRE = CREATEOBJECT("VBScript.RegExp")
Propiedades y Mtodos
Aunque cubriremos al menos la mayora de las propiedades y mtodos del intrprete, el grueso de esta seccin se concentrar en una sola propiedad: el pattern (patrn). Sin lugar a dudas la propiedad pattern es el nudo. Si no logra un buen entendimiento de sta, entonces las restantes propiedades y mtodos tendrn poco o ningn uso. Por el contrario, cuanto mejor comprenda estos patrones, tanto ms til encontrar el intrprete. La propiedad pattern representa a la cadena y las caractersticas de ella que deben interpretarse. Esto es hecho por una representacin simblica de la cadena. Mencionamos antes la validacin de una direccin de email. Veamos primero el formato de una direccin, y luego el patrn que corresponde con ella.
http://www.microsoft.com/spanish/msdn/comunidad/mtj.net/voices/art03.asp
26/04/2006
Pgina 18 de 23
La direcciones de email toman el siguiente formato: una o ms palabras, el smbolo "@", una o ms palabras, un punto, luego una palabra. Por ejemplo, las siguientes son variantes de esto: [email protected] [email protected] [email protected] Verificar que estas direcciones son correctas en Fox requerira verificar para estar seguro que: tanto la "@" como el "." Estn incluidos, que la "@" viene antes que el ".", que estn separados por una palabra, y que ninguno de ambos es el primero ltimo carcter de la cadena. Para chequearlo deberamos escribir una funcin como la que sigue: FUNCTION VerifyEFormat LPARAMETER tceMailAddr LOCAL llresult, lnatpt, lndotpt llresult = .F. lnatpt = AT("@", tceMailAddr) lndotpt = AT(".", tceMailAddr) IF lnatpt > 0 AND lndotpt > 0 IF lnatpt < lndotpt IF lnatpt > 1 llresult = (lndotpt < LEN(tceMailAddr)) ENDIF ENDIF ENDIF RETURN llresult ENDFUNC Ahora, asumiendo que el objeto RegExp ya ha sido creado, haramos lo mismo que arriba con los siguiente: oRE.Pattern = "\w+\@\w+\.\w+" llresult = oRE.Test(tceMailAddr) Como probablemente adivin, el mtodo Test() devuelve un valor lgico basado en que el parmetro coincida con el pattern. Sin ambrago, puede estar rascndose la cabeza sorprendido acerca del pattern mismo. Re-examinemos nuestra descripcin original acerca de ste: "una o ms palabras, el smbolo "@", una o ms palabras, un punto, luego otra palabra." La barra invertida, como puede haberse imaginado, es un indicador de que lo que sigue debe ocurrir. Por ejemplo"\@" y "\." Indican que esos smbolos deben estar en la cadena, en los puestos indicados. Qu hay de "\w+", entonces? Aqu es donde se vuelve confuso. La "w" y algunos otros carcteres tienen un significado especial, mientras otros no. Por ejemplo, si quiere determinar si una palabra comienza con la letra "a", deber indicar el pattern: oRE.Pattern = "\a\w+" ? oRE.Test("awesome") && Muestra .T.
http://www.microsoft.com/spanish/msdn/comunidad/mtj.net/voices/art03.asp
26/04/2006
Pgina 19 de 23
? oRe.Test("wonderful") && Muestra .F. "\w+" indica que cualquier secuencia de carcteres alfanumricos pued aparecer, incluyendo espacios y tabuladores. De la misma forma, "\w" significa cualquier carcter. En nuetro ejemplo usando la direccin de email, entonces, "\w+" es usado para indicar el nombre, el dominio y el tipo. En caso de que est preguntndose como hace para determinar que una palabra comienza con "w" con el intrprete, debe usar "[w]". As: oRE.Pattern = "[w]" ? oRE.Test("awesome") && Muestra .F. ? oRe.Test("wonderful") && Muestra .T. Antes de irnos demasiado lejos, veamos todos los carcteres y su significado para la propiedad Pattern. Carcter \ ^ * + ? Descripcin Indica que el prximo carcter es un carcter especial o debe ser tomado como literal. Por ejemplo, "w" busca el carcter "w". "\w" busca cualquier palabra (ver abajo). Usado para indicar un NO lgico para los caracteres que siguen. Ver los ejemplos que siguen. Toma el carcter inmediatamente precedente cero o ms veces. Por ejemplo, "wo*" concuerda con "w" o con "woo". Toma el carcter inmediatamente precedente una o ms veces. Por ejemplo "wo+" concuerda con "woo" pero no con "w". Toma el carcter inmediatamente precedente cero o una vez. Por ejemplo, "ve?" concuerda con "ve" en "avena".
. (punto) Toma cualquier carcter con excepcin de uno de nueva lnea. x|y {n} {n.} {n,m} [xyz] [^xyz] [x-z] [^m-z] \b \B Toma cualquier carcter. Pro ejemplo, "z|food" concuerda con "z" "food". "zood", sin embargo, no coincide. "(z|f)ood" conincide con "zood" "food". n es cero o mayor. Toma exactamente n veces. "o{2}" no coincide con la "o" en "Koala," pero si con las dos "oes" en "zoolgico". n es cero o mayor. Toma al menos n veces. Por ejemplo, "o{2,}" no conincide con la "o" en "Koala" y coincide con todas las "oes" en "zooooom". "o{1,}" es lo mismo que "o+". "o{0,}" es igual a "o*". m y n son mayores o iguales a cero. Toma al menos n veces y como mximo m. "o{1,3}" coincide con las 3 "oes" en "zoooooom". "o{0,1}" es lo mismo que "o?". Un juego de caracteres. Cualquiera de los caracteres entre corchetes coincide. "[abc]" coincide slo con la "a" en "pao". Un juego de caracteres que no debe coincidir. Coincide cualquier carcter no incluido. "[^abc]" coincide con la "p" en "pao". Un rango de caracteres a ser incluidos en el juego. Concuerda con cualquier carcter en el rango especificado. "[a-m]" coincide con cualquier carcter alfabtico en minscula en el rango de la "a" a la "m". Un rango de caracteres que no deben coincidir. Toma cualquier carcter no especificado en el rango. Por ejemplo, "[m-z]" toma cualquier carcter que no est en el rango de "m" a "z". Toma el lmite de una palabra. Esta es la posicin entre una palabra y un espacio o signo de puntuacin. Por ejemplo, "er\b" coincide con "er" en "tener" pero no con "er" en "verbo". Toma el lmite de no-palabra, o dicho de otra forma, la posicin en la cadena. "an*t\B" coincide con "ant" en "nunca antes".
http://www.microsoft.com/spanish/msdn/comunidad/mtj.net/voices/art03.asp
26/04/2006
Pgina 20 de 23
\d \D \s \S \w \W
Toma un nico carcter numrico. Lo mismo que [0-9]. Toma un nico carcter no-numrico. Lo mismo que [^0-9]. Toma cualquier espacio en blanco incluyendo un espacio, tabulador, salto de pgina, etc. Lo mismo que "[ \f\n\r\t\v]". Toma cualquier carcter que no sea un espacio. Lo mismo que "[^ \f\n\r\t\v]". Toma cualquier carcter de palabra incluyendo el guin bajo. Lo mismo que "[A-Za-z0-9_]". Toma cualquier carcter de no-palabra. Lo mismo que "[^A-Za-z0-9_]".
Debemos aclarar que la tabla de arriba no est completa. Hay definiciones adicionales de patrones que pueden encontrarse en el archivo de ayuda mencionado previamente. Segn esto, si quisiramos verificar que una URL fue ingresada como www.dominio.tipo, el patrn sera: oRE.Pattern = "w{3}\.\w+\.\w+" ? oRE.Test("www.vfug.org") && Muestra .T. Cualquier entrada que no comience con "www" ser rechazada. Igualq ue cualquiera con un espacio, tilde o guin o cualquier otro carcter no listado en la tabla superior que se aplique a las partes del dominio o tipo de la cadena. Obviamente, el nmero de posibilidades para la propiedad Pattern es virtualmente ilimitado. Aunque veamos algunas otras ms adelante en esta seccin, y ya que hay otras propiedades y mtodos para cubrir, dejaremos la discusin en este punto.
Otras propiedades
IgnoreCase - Este es un valor lgico indicando si en los casos que el patrn toma maysculas minsculas si stas deben ser ignoradas. El valor por omisin de esta propiedad es .F. Global - Otro valor lgico indicando si el patrn buscado debe aplicarse a toda la cadena. Nuevamente, el valor por omisin es .F.. Es usada comnmente en conjunto con el mtodo Replace, que veremos enseguida.
Mtodos
Execute - Verifica cada parte de la cadena y almacena los resultados exitosos en la coleccin de coincidencias. Para ilustrarlo, volvamos a nuestro ejemplo del mtodo Test con la direccin de email. Intencionalmente, dejamos fuera la posibilidad de que la direccin contenga un punto a la izquierda del smbolo "@". Ahora, para verificarlo en cdigo VFP, deberamos agregar ms cdigo, pero el intrprete lo seguira evaluando como coincidiendo con el criterio especificado. Por qu? Simplemente porque el patrn provisto coincidi, comenzando luego del primer punto. Con un poco de manipulacin del patrn, podemos realmente extraer porciones de la coincidencia. Si modificamos el patrn para ser "(\w+)@(\w+)\.(\w+)", cada tem encerrado en parntesis ser almacenado en la coleccin submatches de matches (coincidencias). Para entenderlo, probablemente sea ms fcil dar un ejemplo: oRE.Pattern = "(\w+)@(\w+)\.(\w+)" IF oRe.Test("[email protected]")
http://www.microsoft.com/spanish/msdn/comunidad/mtj.net/voices/art03.asp
26/04/2006
Pgina 21 de 23
oMatches = oRE.Execute("[email protected]") FOR EACH oMatch IN oMatches ? oMatch.Value && Muestra [email protected] FOR EACH lcsub IN oMatch.Submatches ? lcsub NEXT NEXT Las tres iteraciones del bucle interior mostrarn ""name", "domain", y "com" en ese orden. Replace - Este mtodo hace una o dos cosas. Primero, como el nombre sugiere, reemplaza una cadena por otra. Segundo, puede intercambiar pares de palabras ms. Mejor que ejemplos de sintaxis, pruebe lo siguiente desde la ventana de comandos. lcstring = "Es la hora de que todos los hombres buenos vengan a ayudar a su pas." oRE.Pattern = "hombres" ? oRE.Replace(lcstring, "ciudadanos") Qu tal un ejemplo del mundo real sobre intercambio? Qu pasara si tuviese un archivo de texto (SDF) con la fecha en formato "MM/DD/AAAA"? Bsicamente tiene dos alternativas. Primero puede agregar los datos directamente a un cursos con el tipo de datos como C (8). Luego agregarlo a una tabla real. Esta eleccin requiere extraer la cadena, y mover de lugar los caracteres usando las funciones de VFP como SUBSTR(). Sin embargo, con el mtodo Replace, esta tarea es ms fcil. Digamos que hay un solo campo fecha, incrustado en alguna parte de la lnea, y que luce as: "Algunos datos de caracter09.00mas caracteres02/01/2001mas sobrantes" Lo que tenemos arriba es la fecha profundamente incrustada en la cadena. Consideremos ahora que deberamos hacer primero. Primero deberamos poner cdigo fijo para el inicio y el largo de la fecha. Luego deberamos intercambiar las piezas de un lado al otro, eliminar las barras, y luego volver a grabarlo. Aqu hay cdigo que hace eso sobre la cadena de arriba. * lcString es la cadena mostrada antes lcDate = SUBSTR( lcString, 39, 8 ) lcDtart = LEFT( lcString, 38 ) lcFinish = SUBSTR( lcString, 47 ) lcString = lcStart + RIGHT( lcDate, 4 ) + LEFT( lcDate, 2 ) +; SUBSTR( lcDate, 4, 2 ) + lcFinish Es un montn de trabajo. Antes de que alguien piense: "Bueno, qu hay con DTOS(CTOD(lcdate))?", considere que la computadora en que corra este cdigo puede no tener la fecha configurada como AMERICAN MDY. Esto fueron cuatro lneas de cdigo, tres variables, ms seis llamadas a funciones. Hace que lo anterior sea la opcin ms fcil. Considere lo siguiente: oRE.Pattern = "(\d+)\/(\d+)\/(\d+)"
http://www.microsoft.com/spanish/msdn/comunidad/mtj.net/voices/art03.asp
26/04/2006
Pgina 22 de 23
lcString = oRE.Replace( lcString, "$3$1$2") Se preguntar porqu funciona esto. El signo pesos representa el comienzo de una palabra. En el patrn, las tres instancias de (\d+) son las palabras, la indicacin de las barras (\/) no. Por tanto la cadena "$3$1$2" indica que la palabra 3 va primero, la palabra 1 segunda, y la palabra 1 tercera, y terminamos con "20010201", que se agrega a la tabla muy prolijamente. Ahora se preguntar que pasa con una cadena con ms de una fecha, como: "Algunos datos de caracter09.00mas caracteres02/01/2001mas sobrantes02/14/2001y aun mas" Puede pensar que deber procesar esto ms de una vez, pero no es as. La propiedad global que se mencion antes puede usarse en este caso. Si pone oRE.Global igual a .T., todas las instancias en que el patrn coincida sern reemplazadas. Test - Como vimos antes, este mtodo realiza la prueba para saber si la cadena pasada como parmetro coincide con el patrn proporcionado y devuelve un valor lgico indicando el resultado. llResult = oRE.Test(< cadena a probar >)
George Tasker trabaja para el Shaw Contract Group, de Cartersville, Georgia. Puede ser contactado en [email protected].
http://www.microsoft.com/spanish/msdn/comunidad/mtj.net/voices/art03.asp
26/04/2006
Pgina 23 de 23
Ed Rauh (MCP) es especialista en desarrollo dentro del entorno Win32 utilizando VFP, VC++ y tecnologas Windows DNA. Es MVP en Visual FoxPro desde el ao 1999. Puede ser contactado en [email protected].
Administre su perfil | Enve esta pagina por e-mail | Suscrbase al MSDN Flash 2006 Microsoft Corporation. Todos los derechos reservados. Aviso Legal | Marcas registradas | Privacidad
Ultima actualizacin: 13 de Enero de 2003
http://www.microsoft.com/spanish/msdn/comunidad/mtj.net/voices/art03.asp
26/04/2006