|
En este capitulo vamos a cubrir las funciones encargadas de la manipulación de archivos, a la vez vamos a ver funciones que nos permite obtener información de las unidades físicas de disco y los propios archivos. Es necesario que presten mucha atención ya que el manejo de archivo con las funciones API’S Win32 no es tan sencillo como creen, esto lo digo ya que VB proporciona controles y librerías que hacen el manejo de archivo rápido y sencillo pero ahora veremos lo que hay detrás de dichos controles. CREANDO Y LEYENDO ARCHIVOS Para este proyecto vamos a necesitar un formulario, que debe de contener 10 botones “command”, 1 label o etiqueta, 1 ProgressBar o barra de progreso y 1 CommonDialog. Luego pegan este código: Ver Codigo
Antes de correrlo vamos a dejar en claro ciertas cositas, en primer lugar se habrán dado cuenta de los comentarios colocados en la declaración de algunas funciones, ejemplo: 'Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, lpSecurityAttributes As SECURITY_ATTRIBUTES, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, lpSecurityAttributes As Long, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long Su única diferencia es lo que esta marcado en azul. La estructura SECURITY_ATTRIBUTES es una estructura para NT, que no vamos a usar, por ende para que no sea un fastido, declarar dicha estructura, cambio la función quitando en la declaración el parámetro SECURITY_ATTRIBUTES y coloco Long, con la finalidad de poder pasarle 0, cuando utilice la función. Como pueden ver hacemos acciones simples, pero que en código no son nada simple, dicha explicación la haré botón por botón, pero en este momento describiré 3 funciones claves, que vamos a ver en prácticamente todos los botones. CreateFile Api: Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, lpSecurityAttributes As Long, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long Función encargada de crear o abrir un archivo. LpFileName = Como primer parámetro tenemos el nombre del archivo que queremos crear o abrir. DwDesiredAccess = Especifica el tipo de acceso, esto parámetro puede tomar alguna o la combinacion de estas dos variables: Const GENERIC_READ = &H80000000 ‘ Se especifica que el archivo será abierto o creado para solo ser leído. Const GENERIC_WRITE = &H40000000 ‘ Se especifica que el archivo será abierto o creado para solo escritura. Pueden usar OR para combinar ambas constantes. DwShareMode = con este parámetro especificamos como va ser compartido el archivo creado o abierto. Puede tomar la combinación de los siguientes valores: Const FILE_SHARE_READ = &H1 Const FILE_SHARE_WRITE = &H2 Ambos parámetro son utilizados para especificar que se comparte el archivo solo para lectura, escritura o ambos. Recuerden que un archivo puede ser usado por varios programas al mismo tiempo. LpSecurityAttributes = Aquí es donde va la estructura SECURITY_ATTRIBUTES pero en nuestro caso no será utilizada y colocaremos 0. Aquellos que usan NT y están interesados pueden consultar la documentación en MSDN. DwCreationDisposition = Con este parámetro se especifica la acciones a tomar, en caso de que exista el archivo o no exista. Para verlo mejor veamos los valores que puede tomar: Const CREATE_NEW = 1 ‘ Crea el archivo, en caso de existir el archivo la función retorna un error es decir falla la ejecución de la función. Const CREATE_ALWAYS = 2 ‘ Crea el archivo, en caso de existir el archivo, este es sobrescrito, es decir, se pierde la información existente. Const OPEN_EXISTING = 3 ‘ Sirve para solo abrir el archivo cuando ya sabemos que existe, en caso de no existir la función retorna un error. Const OPEN_ALWAYS = 4 ‘ Abre el archivo ya existente, en caso de no existir la función lo crea si el valor CREATE_NEW esta especificado. Const TRUNCATE_EXISTING = 5 ‘ Abre el archivo existente, y una vez abierto este toma el tamaño de 0 bytes. La función falla si el archivo no existe. DwFlagsAndAttributes = Con este parámetro especificamos los atributos que va a poseer dicho archivo, puede tomar un valor o la combinacion de los siguientes valores: Const FILE_ATTRIBUTE_ARCHIVE = &H20 ‘ Con este especificamos que lo que estamos creando es un archivo. Const FILE_ATTRIBUTE_HIDDEN = &H2 ‘ Con este especificamos que el archivo sea oculto. Const FILE_ATTRIBUTE_NORMAL = &H80 ‘ El archivo no posee de ningún atributo en particular. Const FILE_ATTRIBUTE_OFFLINE = &H1000 ‘ Con este se especifica que la información del archivo no esta habilitada inmediatamente. Const FILE_ATTRIBUTE_READONLY = &H1 ‘ El archivo es de solo lectura. Const FILE_ATTRIBUTE_SYSTEM = &H4 ‘ El archivo forma parte del sistema, es decir, un archivo que el sistema operativo usa. Const FILE_ATTRIBUTE_TEMPORARY = &H100 ‘ El archivo va ser utilizado de manera temporal. Con estos parámetros se pueden usar también los siguientes, que solo son nombrados ya que no son usado en este manual:
Private Const FILE_FLAG_WRITE_THROUGH = &H80000000 Private Const FILE_FLAG_OVERLAPPED = &H40000000 Private Const FILE_FLAG_NO_BUFFERING = &H20000000 Private Const FILE_FLAG_RANDOM_ACCESS = &H10000000 Private Const FILE_FLAG_SEQUENTIAL_SCAN = &H8000000 Private Const FILE_FLAG_DELETE_ON_CLOSE = &H4000000 Private Const FILE_FLAG_BACKUP_SEMANTICS = &H2000000 Private Const FILE_FLAG_POSIX_SEMANTICS = &H1000000 Private Const FILE_FLAG_OPEN_REPARSE_POINT = &H200000 Private Const FILE_FLAG_OPEN_NO_RECALL = &H100000 HTemplateFile = en este parámetro se le pasa el “handle” de un archivo abierto con anterioridad, ¿Para que sirve eso?. Lo que se hace con esto es heredar o tomar los parámetros de ese archivo. Es decir, si el archivo abierto tiene el atributo HIDDEN, el archivo que vayamos a crear toma también dicho atributo. Lo veremos mas claro cuando vayamos a crear directorios. Estos son todos los parámetros, si la función se ejecuta con éxito dicha función retorna el “handle” del objeto abierto, que en este caso es un archivo. En caso de fallar este retorna: Const INVALID_HANDLE_VALUE = -1 Para un error mas especifico usamos la función GetLastError, función que veremos mas adelante. Ahora voy a mostrar las dos funciones que utilizamos para leer el archivo y escribir en él, algo que tiene que tener en cuenta aparte de haber entendido el capitulo de Memoria, es que un archivo es una arreglo de bytes. Es importante que tengan esto en mente ya que lo necesitaremos al momento de explicar el código. WriteFile Api: Declare Function WriteFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToWrite As Long, lpNumberOfBytesWritten As Long, lpOverlapped As Long) As Long Api: Declare Function WriteFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToWrite As Long, lpNumberOfBytesWritten As Long, lpOverlapped As OVERLAPPED) As Long Aquí pongo dos declaraciones ya que dense cuenta que el ultimo parámetro no es igual, y esto se debe a que no vamos a usar la estructura OVERLAPPED, ¿Por qué?, para ser sincero, es por que yo no le he visto uso a este parámetro, OJO, no estoy diciendo que no sirve para nada esta estructura, solo que YO no he visto la necesidad de usarla para hacer mis proyectos, por lo que no me he preocupado de estudiarla. Esta función como obviamente se imaginaran sirve para escribir en un archivo. HFile = como primer parámetro le pasamos el “handle” que nos regresa CreateFile, del archivo que se encuentra abierto, para que la función sirva, el archivo tuvo que ser creado o abierto especificando la constante GENERIC_WRITE. LpBuffer = puntero de memoria en donde se encuentra la información que queremos escribir en el archivo. NNumberOfBytesToWrite = numero de bytes que vamos a escribir. LpNumberOfBytesWritten = variable que después de haber llamado a la función contendrá la cantidad de bytes que fueron escritos. LpOverlapped = parámetro en donde se le pasa la estructura OVERLAPPED pero que en nuestro caso será 0. Si la función se ejecuta con éxito retorna un valor distinto de 0, en caso de retornar 0 implica que hubo alguna falla en su ejecución. ReadFile Api: Declare Function ReadFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, lpOverlapped As OVERLAPPED) As Long Api: Declare Function ReadFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, lpOverlapped As Long) As Long Función encargada de leer la información contenida en un archivo. HFile = como primer parámetro le pasamos el “handle” que nos regresa CreateFile, del archivo que se encuentra abierto, para que la función sirva, el archivo tuvo que ser creado o abierto especificando la constante GENERIC_READ. LpBuffer = puntero de memoria en donde se almacenará la información. NNumberOfBytesToWrite = numero de bytes que vamos a leer. LpNumberOfBytesWritten = variable que después de haber llamado a la función contendrá la cantidad de bytes que fueron leídos. LpOverlapped = parámetro en donde se le pasa la estructura OVERLAPPED pero que en nuestro caso será 0. Ahora que ya hemos visto las funciones claves, para entender el funcionamiento de cada una vamos a los ejemplos, y las funciones que aparezcan nuevas serán explicadas a medida que expliquemos el funcionamiento del programa. Command1 hFile = CreateFile("C:\prueba.txt", GENERIC_WRITE, FILE_SHARE_READ Or FILE_SHARE_WRITE, ByVal 0&, OPEN_ALWAYS, 0, 0) ‘ Creo el archivo especificando GENERIC_WRITE, donde doy a entender que vamos a escribir en él. . . s1 = "Hola Mundo!" espacio = GlobalAlloc(GMEM_FIXED Or GMEM_ZEROINIT, Len(s1)) ‘ Creo un espacio en memoria que contendrá la información de la variable “s1”, doy por entendido que leyeron el capitulo de Memoria. CopyMemory ByVal espacio, ByVal s1, Len(s1) Dim ret As Long WriteFile hFile, ByVal espacio, Len(s1), ret, ByVal 0& ‘ Escribo la información que apunta la variable “espacio”, en el archivo abierto “hFile”, el valor de “ret” después de ejecutar la función es igual a Len(s1) ya que escribimos toda la cadena GlobalFree espacio ‘ Liberamos el espacio de memoria que usamos. Aquí hago un STOP, para explicar la siguiente función API y luego continuo con el código, aunque en este momento en C:\ tienen un archivo “prueba.txt” que contiene en su interior “Hola Mundo!” SetFilePointer Api: Declare Function SetFilePointer Lib "kernel32" (ByVal hFile As Long, ByVal lDistanceToMove As Long, lpDistanceToMoveHigh As Long, ByVal dwMoveMethod As Long) As Long Función que sirve para mover el puntero del archivo ¿Puntero?. En un archivo existe un puntero dicho puntero es utilizado para saber en donde estamos en el archivo, es similar al puntero de bases de datos, con la diferencia que aquí hablamos de cualquier tipo de archivo. HFile = como primer parámetro le pasamos el “handle” que nos regresa CreateFile, del archivo que se encuentra abierto. LDistanceToMove, lpDistanceToMoveHigh = estas dos variables forman un valor de 64 Bits, que al combinarse especifican la cantidad de bytes que se va a mover el puntero del archivo. La primera especifica la parte baja de 32 bits y la segunda la parte alta. Particularmente en los ejemplos que use, utilice LdistanceToMove, para especificar la cantidad de bytes que quería mover colocando 0 en lpDistanceToMoveHigh. Eso lo veremos mas adelante. DwMoveMethod = Este parámetro puede tomar los siguientes valores: Const FILE_BEGIN = 0 ‘ Coloca el puntero en el inicio del archivo Const FILE_END = 2 ‘ Coloca el puntero al final del archivo. Ya explicada dicha función continuemos con el código: 'SetFilePointer hFile, 0, ByVal 0&, FILE_BEGIN SetFilePointer hFile, 0, ByVal 0&, FILE_END ‘ Aquí lo que hago es llevar el puntero al final del archivo para continuar escribiendo. s1 = "como estas" espacio = GlobalAlloc(GMEM_FIXED Or GMEM_ZEROINIT, Len(s1)) CopyMemory ByVal espacio, ByVal s1, Len(s1) WriteFile hFile, ByVal espacio, Len(s1), ret, ByVal 0& GlobalFree espacio CloseHandle hFile Aplico el mismo procedimiento de escritura explicado arriba. Pero quiten el comentario de la línea: 'SetFilePointer hFile, 0, ByVal 0&, FILE_BEGIN.
Y pónganle comentario a SetFilePointer hFile, 0, ByVal 0&, FILE_END, luego borren el archivo creado, ejecuten el programa y vean el archivo y dense cuenta de la diferencia. Command2 Dim s2 As String hFile = CreateFile("C:\prueba.txt", GENERIC_READ, FILE_SHARE_READ, ByVal 0&, OPEN_ALWAYS, 0, 0) ‘ Abro el archivo de modo LECTURA. If hFile = INVALID_HANDLE_VALUE Then MsgBox "error al cargar el archivo" End If tamaño = GetFileSize(hFile, 0) ‘ Obtengo su tamaño. espacio = GlobalAlloc(GMEM_FIXED Or GMEM_ZEROINIT, tamaño) ‘ Reservo la memoria donde almacenare la información. Dim ret As Long 'SetFilePointer hFile, 4, 0, FILE_BEGIN 'ReadFile hFile, ByVal espacio, Len(s1) - 4, ret, ByVal 0& 'SetFilePointer hFile, 1, 0, FILE_BEGIN 'ReadFile hFile, ByVal espacio, Len(s1) - 1, ret, ByVal 0& ReadFile hFile, ByVal espacio, tamaño, ret, ByVal 0& ‘ Recupero la información cuyo tamaño en bytes será lo que contenga la variable “tamaño” y lo almaceno en la dirección que apunta “espacio”. s2 = String$(ret, 0) CopyMemory ByVal s2, ByVal espacio, ret Debug.Print s2 ‘Muestro el contenido del archivo. GlobalFree espacio CloseHandle hFile Si aprietan el botón 1, en donde escribimos y luego el 2, en la ventana “Inmediato” de VB verán el contenido del archivo. Que sucede con estas líneas de código: 'SetFilePointer hFile, 4, 0, FILE_BEGIN 'ReadFile hFile, ByVal espacio, Len(s1) - 4, ret, ByVal 0& 'SetFilePointer hFile, 1, 0, FILE_BEGIN 'ReadFile hFile, ByVal espacio, Len(s1) - 1, ret, ByVal 0& Si ponen en comentario a esta línea: ReadFile hFile, ByVal espacio, tamaño, ret, ByVal 0& Y le quitan el comentario a las líneas marcadas de azul, se darán cuenta que la información que retorna no es la misma, es mas pequeño ya que moví el puntero del archivo 4 bytes, es decir, si en el archivo estaba la cadena : “Hola Mundo!”, pues lo que obtendremos será “Mundo!”, ya que movimos el puntero 4 bytes hacia la derecha. Igual sucede con las líneas de color rojo. Command3 Ya sabemos que en un archivo lo que pasamos es una serie de bytes, que representan alguna información, hemos utilizado la variable “espacio” como puntero de dicha serie de bytes que queremos almacenar, pero el command3 muestra otra forma de almacenar información, pero a través de arreglo, dicho arreglo deberá de ser de tipo byte, y cada casilla tendrá que tener el valor que queremos almacenar. ReDim bBytes(11) ‘ Declaro un arreglo de 11 casillas del tipo byte. bBytes(1) = Asc("H"): bBytes(2) = Asc("o"): bBytes(3) = Asc("l"): bBytes(4) = Asc("a") bBytes(5) = Asc(" "): bBytes(6) = Asc("M"): bBytes(7) = Asc("u"): bBytes(8) = Asc("n") bBytes(9) = Asc("d"): bBytes(10) = Asc("o"): bBytes(11) = Asc("!") ‘ Almaceno en cada casilla el ascii correspondiente a cada letra del contenido que vamos a guardar. hFile = CreateFile("C:\otraprueba.txt", GENERIC_WRITE, FILE_SHARE_READ Or FILE_SHARE_WRITE, ByVal 0&, OPEN_ALWAYS, 0, 0) ‘ Creo el archivo . . Dim ret As Long WriteFile hFile, bBytes(1), UBound(bBytes), ret, ByVal 0& ‘ Paso el arreglo que contiene la información a guardar. . . Vean que se obtiene exactamente lo mismo. Una pregunta podría ser ¿Por qué “espacio” lo pasas con ByVal, y el arreglo sin Byval? Buena pregunta. Ese parámetro de la función WriteFile, (y estoy hablando de “LpBuffer”) es un parámetro por pase por referencia. La variable “espacio” NO, y ojo NO contiene el contenido de la cadena, es decir, “espacio” no tiene almacenado “Hola Mundo!”, lo que tiene “espacio” almacenado es la dirección en memoria en donde se encuentra dicha cadena. Si yo quito Byval, pues entonces la función tomaría la dirección como valor y NO la cadena, es decir, quedaría almacenado el contenido de la variable “espacio” que no es mas que un simple numero, y claro, daría error la función ya que el tamaño a guardar es mayor que el contenido de la variable “espacio”. En cambio bBytes, es un arreglo, y todos sabemos que la primera posición, apunta a la primera posición en la memoria en donde se encuentra los bytes que queremos almacenar, no uso ByVal ya que aquí si me interesa que tome el pase por referencia de la primera posición. Se que es confuso y mas para aquellos que no pueden tener experiencia en C, pero siéntense analizar un poco y se darán cuenta lo que sucede. Command4 Command4 es el equivalente al Command2, pero usando arreglo: NOTA: omito las líneas que carecen de importancia. hFile = CreateFile("C:\otraprueba.txt", GENERIC_READ, FILE_SHARE_READ, ByVal 0&, OPEN_ALWAYS, 0, 0) ‘ Abro el archivo creado con Command3 tamaño = GetFileSize(hFile, 0) ‘ Obtengo el tamaño ReDim bBytes(tamaño) ‘ Redimensiono el arreglo para que soporte toda la información ReadFile hFile, bBytes(1), tamaño, ret, ByVal 0& ‘ Luego leo el contenido. Que va empezar almacenándose en la posición 1 del arreglo. For i = 1 To ret cadena = cadena & Chr(bBytes(i)) Next ’ Con este FOR construyo la cadena resultante. Hay una función que hemos usado y que de seguro han entendido lo que hace para vamos a mostrarla con detalle: GetFileSize Api: Declare Function GetFileSize Lib "kernel32" (ByVal hFile As Long, lpFileSizeHigh As Long) As Long función que se encarga de tomar el tamaño en bytes de un archivo, como primer parámetro le pasamos el “handle” del archivo y como segundo parámetro, en verdad no le he visto utilidad por lo que para nuestro propósito le pasamos 0. La función lo que retorna es el tamaño en bytes del archivo. Command5 Este botón hace exactamente lo mismo que command1, con la diferencia que almacena un valor de tipo String mas grande. Esto sirve para explicar el botón que sigue en donde veremos como hacer un recorrido del archivo. Command6 salida = True ‘ Variable de control que sirve para controlar cuando el puntero llegue a fin de archivo. espacio = GlobalAlloc(GMEM_FIXED Or GMEM_ZEROINIT, 10) res = ReadFile(hFile, ByVal espacio, 10, ret, ByVal 0&) ‘ Vamos a leer el archivo de 10 en 10, es decir, tomamos primero 10 bytes y así sucesivamente hasta llegar al EOF o fin de archivo. Do While salida If res And ret = 0 Then ‘ Este es la condición de EOF, es decir, cuando res = true y ret = 0 esto implica que la función ha llegado al final del archivo por ende no hay mas nada que leer, por lo que cambio salida = false para salir del bucle. salida = False Else ‘ En caso de no ser fin de archivo s2 = String$(ret, 0) CopyMemory ByVal s2, ByVal espacio, ret ‘ Copio los primeros 10 bytes tomados en la variable s2. Debug.Print s2 ‘ Voy imprimiendo en la ventana “inmediato” los bytes que voy recuperando. res = ReadFile(hFile, ByVal espacio, 10, ret, ByVal 0&) ‘ Procedo a leer los 10 bytes siguientes. Almacenándolos en el mismo espacio de memoria que reserve al inicio. End If Loop Command7 El command7 es un botón muy interesante ya que vamos hacer una copia EXACTA de un archivo sin usar ninguna función de copia, sino puro WriteFile y ReadFile. Voy a saltarme las primeras líneas en donde no deben de tener problema de entender, así que mostrare las mas importantes: salida = True ‘ Variable de control del bucle WHILE nBytes = 0 espacio = GlobalAlloc(GMEM_FIXED Or GMEM_ZEROINIT, 4096) ‘ Reserva 4K, lo que significa que vamos a ir leyendo el archivo de 4K en 4K. res = ReadFile(hOrigen, ByVal espacio, 4096, ret, ByVal 0&) ‘ Leo los primeros 4K. Do While salida If res And ret = 0 Then ‘ Si es fin de archivo. salida = False ‘ Cambio el valor de la variable “salida” para salir del bucle. Else ‘ Si no es fin de archivo. WriteFile hDestino, ByVal espacio, ret, ret2, ByVal 0& ‘ Escribo los primeros 4K en el archivo “hDestino”. nBytes = nBytes + ret2 ‘ Llevo la cuenta de la cantidad de bytes leído. Label1.Caption = "Bytes escritos = " & nBytes & " bytes" ‘ Muestro los bytes leídos. ProgressBar1.Value = nBytes res = ReadFile(hOrigen, ByVal espacio, 4096, ret, ByVal 0&) ‘ Leo los próximos 4K del archivo “origen” SetFilePointer hDestino, 0, ByVal 0&, FILE_END ‘ Me aseguro que el puntero del archivo “hDestino” este en el final, para ir almacenando los bytes uno detrás de otro. End If Loop Y listo, si quieren probarlo agarren un archivo grafico, y vean que la copia, tiene la misma imagen que el archivo original. Command8 botón utilizado para crear un directorio. CreateDirectory Api: Declare Function CreateDirectory Lib "kernel32" Alias "CreateDirectoryA" (ByVal lpPathName As String, lpSecurityAttributes As Long) As Long Api: Declare Function CreateDirectory Lib "kernel32" Alias "CreateDirectoryA" (ByVal lpPathName As String, lpSecurityAttributes As SECURITY_ATTRIBUTES) As Long Esta función es utilizada para crear un nuevo directorio, como primer parámetro le pasamos el nombre y ubicación del directorio, y como segundo parámetro en la función original debería de pasársele la estructura SECURITY_ATTRIBUTES, pero como no la vamos usar, usamos la función que posee dicho parámetro declarado de tipo long, y pasamos 0, cuando ejecutemos la función. Command9 botón utilizado para crear un directorio que toma los atributos de otro directorio. CreateDirectoryEx Api:Declare Function CreateDirectoryEx Lib "kernel32" Alias "CreateDirectoryExA" (ByVal lpTemplateDirectory As String, ByVal lpNewDirectory As String, lpSecurityAttributes As Long) As Long Api: Declare Function CreateDirectoryEx Lib "kernel32" Alias "CreateDirectoryExA" (ByVal lpTemplateDirectory As String, ByVal lpNewDirectory As String, lpSecurityAttributes As SECURITY_ATTRIBUTES) As Long Función que crea un directorio usando los atributos de un directorio que nos sirve como plantilla. Es decir, el directorio creado con el Command8, asígnenle la propiedad de oculto, y luego presionen el botón Command9, y se darán cuenta que el nuevo directorio “C:\Ejemplo 2”, se creo y también es una carpeta oculta ya que heredo los atributos del directorio “C:\Ejemplo”. Como primer parámetro le pasamos el directorio que nos sirve como plantilla, como segundo parámetro le pasamos el directorio que queremos crear y como tercer parámetro pasamos 0. Command10 botón utilizado para eliminar a un directorio. RemoveDirectory Api: Declare Function RemoveDirectory Lib "kernel32" Alias "RemoveDirectoryA" (ByVal lpPathName As String) As Long función utilizada para eliminar un directorio del disco, si la eliminación es un éxito dicha función retorna un valor distinto de 0, en caso de fracasar retornara 0. Y como único parámetro le pasamos el directorio que queremos eliminar. Se habrán dado cuenta que no es nada fácil trabajar con archivos usando las librerías de Windows, pero algunas veces dichas librerías nos proporcionan de cierto control y versatilidad que no encontraremos en los controles que se encargan de la realización de estas funciones. BUSCANDO ARCHIVOS Ahora vamos a ver un proyecto bien curioso y muy interesante ya que vamos a aprender a como buscar un archivo en un directorio. Y veremos las funciones involucradas en dicho proceso. Para este proyecto son necesarios los siguientes controles: 4 Botones “command”, 2 etiquetas o “label”, 2 Listbox, 3 cajas de texto o “TextBox”. Luego pegan este código: Ver Codigo
NOTA: no presionen el boton de CHEQUEO hasta que yo les diga El programa funciona de la siguiente manera en el Text1, colocan el archivo a buscar ejemplo : “prueba.txt”, en el Text2, ponemos el directorio ACTIVO en donde vamos a buscar dicho archivo, y el Text3 esta programado para buscar mas de un archivo, es decir, pongan por ejemplo “*.txt” y en list2 se les mostrara todos los .txt que se encuentren en el directorio activo. ¿Directorio Activo o Actual?, yo veo a este directorio como la carpeta a la cual se esta apuntando o se quiere realizar alguna operación que en este caso es de búsqueda. Cuando yo arranco el programa desde VB, el directorio actual es el de VB, ahora imaginemos que queremos cambiarlo, pongan por ejemplo “C:\” y cuando presionen el botón para cambiar el directorio actual, verán como cambia el directorio actual. Si el directorio no existe, no se cambia y se mantiene el directorio que estaba. GetCurrentDirectory Api: Declare Function GetCurrentDirectory Lib "kernel32" Alias "GetCurrentDirectoryA" (ByVal nBufferLength As Long, ByVal lpBuffer As String) As Long Función encargada de tomar el directorio actual, como primer parámetro se le pasa la cantidad de bytes que queremos recuperar y como segundo parámetro le pasamos la cadena de tipo String donde almacenaremos dicha información. Dim res As Long cDirectory = Space(MAX_PATH) res = GetCurrentDirectory(MAX_PATH, cDirectory) Label1 = Left(cDirectory, res) Si la función se ejecuta exitosamente, dicha función retornara la longitud en bytes. SetCurrentDirectory Api: Declare Function SetCurrentDirectory Lib "kernel32" Alias "SetCurrentDirectoryA" (ByVal lpPathName As String) As Long Función utilizada para asignar un nuevo directorio actual. Toma un solo parámetro y es la dirección o “path” del nuevo directorio. Ya explicadas estas dos funciones vamos a las funciones que se encargan de realizar la búsqueda: FindFirstFile Declare Function FindFirstFile Lib "kernel32" Alias "FindFirstFileA" (ByVal lpFileName As String, lpFindFileData As WIN32_FIND_DATA) As Long Función encargada de buscar un archivo o carpeta, en la carpeta o directorio que se encuentre como activo. Esta función toma dos parámetros, como primer parámetro se toma el directorio o archivo a buscar. Y como segundo parámetro se toma una estructura que se explica a continuación: Private Type WIN32_FIND_DATA dwFileAttributes As Long ‘ Especifica los atributos del archivo ftCreationTime As FILETIME ‘ Especifica la hora y fecha de creación del archivo ftLastAccessTime As FILETIME ‘ Especifica la hora y fecha de la ultima vez que se accedió al archivo. ftLastWriteTime As FILETIME ‘ Especifica la hora y fecha de la ultima vez cuando se escribió el archivo. nFileSizeHigh As Long ‘ Especifica el “HIGH-ORDER” del tamaño del archivo nFileSizeLow As Long ‘ Especifica el “LOW-ORDER” del tamaño del archivo dwReserved0 As Long ‘ Valor reservado para el sistema dwReserved1 As Long ’ Valor reservado para uso futuro cFileName As String * MAX_PATH ‘ Nombre del archivo cAlternate As String * 14 ‘ Nombre alternativo del archivo End Type Hablemos un poco de algunos parámetros, vean en primer lugar que el tamaño del archivo se divide en dos, la parte “high” y la parte “low”, para obtener el tamaño real del archivo hay que realizar la siguiente formula: (nFileSizeHigh * maxdword) + nFileSizeLow El parámetro dwFileAttributes puede retornar cualquiera de las siguientes constantes:
Const FILE_ATTRIBUTE_ARCHIVE = &H20 Const FILE_ATTRIBUTE_COMPRESSED = &H800 Const FILE_ATTRIBUTE_DIRECTORY = &H10 Const FILE_ATTRIBUTE_ENCRYPTED = &H4000 Const FILE_ATTRIBUTE_HIDDEN = &H2 Const FILE_ATTRIBUTE_NORMAL = &H80 Const FILE_ATTRIBUTE_OFFLINE = &H1000 Const FILE_ATTRIBUTE_READONLY = &H1 Const FILE_ATTRIBUTE_REPARSE_POINT = &H400 Const FILE_ATTRIBUTE_SPARSE_FILE = &H200 Const FILE_ATTRIBUTE_SYSTEM = &H4 Const FILE_ATTRIBUTE_TEMPORARY = &H100 Constantes explicadas en la parte de arriba. Ahora vamos a explicar los siguientes parámetros : ftCreationTime,ftLastAccessTime y ftLastWriteTime. Estas constantes son de otro tipo de estructura llamada FILETIME. Que es de la forma siguiente:
Private Type FILETIME dwLowDateTime As Long dwHighDateTime As Long End Type Es fácil, darse cuenta, que en esta estructura no hay hora, fechas, meses, días, ni nada por el estilo, aquí el tiempo esta representado por un formato, que particularmente no nos sirve. Dicho formato de tiempo es el UTC (Coordinated Universal Time), por consiguiente tenemos que transformar esta estructura en un formato mas entendible para nosotros. Y para eso esta las siguientes funciones: FileTimeToLocalFileTime Api: Declare Function FileTimeToLocalFileTime Lib "kernel32" (lpFileTime As FILETIME, lpLocalFileTime As FILETIME) As Long Esta función convierte el tiempo que le pasamos como primer parámetro que posee el formato UTC, y lo convierte en el formato “local file time”, que es almacenado en el segundo parámetro “lpLocalFileTime”, que es también del tipo FILETIME. Todavía, no sirve este formato, pero es necesario aplicar esta función para después aplicar la función siguiente: FileTimeToSystemTime Api: Declare Function FileTimeToSystemTime Lib "kernel32" (lpFileTime As FILETIME, lpSystemTime As SYSTEMTIME) As Long Esta función sirve para transformar del formato “local file time” en formato “system time”, y este formato si ya es un formato entendible para nosotros. Como primer parámetro le pasamos la variable que colocamos en “lpLocalFileTime” de la función anterior. Y el resultado de dicha transformación se almacena, en el segundo parámetro de la función que es de tipo SYSTEMTIME. Dicha estructura se representa de la siguiente manera: Private Type SYSTEMTIME wYear As Integer ‘ Año wMonth As Integer ‘ Mes wDayOfWeek As Integer ‘ Día de la semana, expresado en número wDay As Integer ‘ Dia. wHour As Integer ‘ Hora wMinute As Integer ‘ Minuto wSecond As Integer ‘ Segundos wMilliseconds As Integer ‘ Milisegundos End Type Este formato si ya es entendible por nosotros y lo podemos utilizar para saber los distintos tiempos que manejan los 3 parámetros antes mencionados de la estructura WIN32_FIND_DATA. De todas maneras cuando vayamos al código entenderán mejor. Regresando a la función FindFirstFile, hay que tener en cuenta que si la función encuentra algún archivo dicha función retorna un “handle” de búsqueda, en caso de fallar la búsqueda retornaría INVALID_HANDLE_VALUE. Para verlo todo mas claro vayamos al ejemplo: hBusqueda = FindFirstFile(Text1.Text, wData) ‘ empiezo la búsqueda del archivo especificado en el Text1. If hBusqueda = INVALID_HANDLE_VALUE Then ‘ Si la búsqueda falla seria por que tal vez no se encontró. MsgBox "Archivo no encontrado" Exit Sub End If List1.AddItem wData.cFileName ‘ Muestro el nombre del archivo en el list1 If wData.dwFileAttributes And FILE_ATTRIBUTE_ARCHIVE Then ‘ Verifico si el archivo posee cada uno de los atributos. List1.AddItem "Este es un archivo" Else List1.AddItem "Este no es un archivo" End If . . . FileTimeToLocalFileTime wData.ftCreationTime, ftime ‘ Convierto el tiempo que me regresa la función en el tiempo “local file time” FileTimeToSystemTime ftime, stime ‘ Convierto “local file time” en “system time” que es el formato el cual entendemos. List1.AddItem " Dia = " & stime.wDay List1.AddItem " Dia de la semana = " & stime.wDayOfWeek List1.AddItem " Hora = " & stime.wHour List1.AddItem " Minuto = " & stime.wMinute List1.AddItem " Segundos = " & stime.wSecond List1.AddItem " Milisegundos = " & stime.wMilliseconds List1.AddItem " MEs = " & stime.wMonth List1.AddItem " Año = " & stime.wYear Muestro las especificaciones del tiempo en el list1. . . . List1.AddItem "Tamaño = " & ((wData.nFileSizeHigh * maxdword) + wData.nFileSizeLow) ‘ Calculo el tamaño del archivo FindClose búsqueda ‘ cierro el “handle” de búsqueda. FindClose Api: Declare Function FindClose Lib "kernel32" (ByVal hFindFile As Long) As Long Función encargada de cerrar un “handle” de búsqueda que se encuentre abierto. Como único parámetro le pasamos el “handle” del archivo encontrado. Ya sabemos como buscar un archivo, pero que sucede si queremos buscar una serie de archivos por ejemplo, queremos buscar todos los “*.bmp” que posea una carpeta para ello es importante la siguiente función: FindNextFile Api: Declare Function FindNextFile Lib "kernel32" Alias "FindNextFileA" (ByVal hFindFile As Long, lpFindFileData As WIN32_FIND_DATA) As Long Esta función es la encargada de buscar el archivo “siguiente”, ya que FindFirstFile busca el primero y luego será trabajo de esta función buscar el siguiente archivo, como primer parámetro le pasamos el primer archivo encontrado, es decir, el “handle” que nos retorna FindFirstFile, y como segundo parámetro le pasamos una variable del tipo WIN32_FIND_DATA. Si la función es un éxito ella retorna el nuevo “handle” del archivo encontrado. En caso de fallar retorna 0. ¿Cómo saber que el error es por no haber mas archivo?. Para ello usamos una función que no quería tratar, pero me vi obligado a usarla en este ejemplo y es: GetLastError Api: Declare Function GetLastError Lib "kernel32" () As Long Esta función retorna el último error que se produjo en un hilo o “thread”. Dicha función no toma ningún parámetro y devuelve un código y dependiendo del código representa algún error. Dichos códigos los encuentran en MSDN, en la sección “Error Codes”. En este caso el error que me interesa capturar es: Const ERROR_NO_MORE_FILES = 18& Vamos aclarar algo ¿Por qué no quería tocar esta función?. Esta función no se usa nada mas en archivo sino en muchas funciones de cualquier tipo, por ejemplo en las graficas se puede usar dicha función ¿Por qué usar esta función? Algunas veces cuando una función falla, puede fallar por muchas razones, por ejemplo, en algunas funciones yo he dicho que si la función falla dicha función retorna 0. ¿Pero, por que exactamente fallo? Es aquí donde GetLastError entra, ya que esta función nos proporciona de una manera mas detalla que fue lo que paso y por que fallo la función. Por ejemplo FindNextFile retorna FALSE si falla, pero como se que falla por que no hay mas archivos o por otra cosa. Entonces es donde la función cumple un papel primordial. No quería tocar este tema ya que es MUY AMPLIO, es decir, a medida que salen nuevas versiones de Windows, los errores van aumentando, y cada función retorna errores específicos. Y en realidad este tema de errores no juega un papel primordial y la finalidad de este manual. Si ven los ejemplos de MSDN, verán que los programadores son muy cuidadosos al momento de capturar errores, en mis ejemplos yo he sido menos cuidadoso, ya que desarrollo los ejemplos de tal manera que no fallen. Por consiguiente si desean estudiar los errores, tendrán que estudiar los códigos de los errores, y dependiendo de la función tendrán que ver el error especifico que genera dicha función. Pero ese trabajo se los dejo a ustedes. Analicemos el código: Dim encontrado As Boolean ‘ Variable que controla el WHILE que se expone abajo. Dim hbusqueda2 As Long encontrado = True List2.Clear hBusqueda = FindFirstFile(Text3.Text, wData) ‘ Buscamos el primer archivo If hBusqueda = INVALID_HANDLE_VALUE Then ‘ Si no existe ni siquiera uno entonces nos salimos. MsgBox "Archivo no encontrado" Exit Sub End If Do While encontrado ‘ Mientras encontremos List2.AddItem wData.cFileName ‘ Mostramos el nombre del archivo encontrado If Not FindNextFile(hBusqueda, wData) Then ‘ Buscamos el siguiente, si retorna 0, que es equivalente a FALSE If GetLastError = ERROR_NO_MORE_FILES Then ‘ Verificamos que el error haya sido por que no había mas archivos. encontrado = False End If End If Loop ‘ Salimos del bucle. FindClose búsqueda ‘ Cerramos el “handle” de búsqueda. Para los curiosos que presionaron el botón Command4, si saber lo que hacia, seguramente se habrán dado cuenta que su programa se queda como bloqueado, y seguramente tuvieron que cerrar todo VB para resolver dicha tranca. Pues déjenme decirles que el programa no estaba trancado sino mas bien estaba “esperando” que algo sucediera, esta parte va ser explicado brevemente por la razón siguiente. Windows posee funciones sincronizadas o como MSDN las pone “Synchronization” y de este hay todo un tema, “Synchronization” es la manera de coordinar múltiples hilos o thread que se están ejecutando. Es decir, podemos tener 2 programas y través de estas funciones sincronizar ambas aplicaciones, es decir, que una aplicación haga “algo”, cuando la otra termine de hacer “algo”. Dicho tema no lo trato en este manual ya que es complejo, y no poseo muchos conocimientos respecto al tema. Pero aquellos interesados pueden buscar “Synchronization” en MSDN y leer todo un tema acerca de eso. Pero aquí en este ejemplo use una función de las llamadas “wait function” que son funciones que dejan el programa en espera de “algo”, vamos a verlo mas claro, corran el programa y denle clic al Command4, el programa pareciera como si estuviera trancado pero no es así. Vayan ahora a “Mi Pc” y luego se meten en “C:”, estando en “C:” creen un archivo cualquiera, después de crearlo vayan al programa y verán que ya no esta trancado y ven un mensaje "EPA POR QUE ANDAS CREANDO ARCHIVOS". ASOMBROSO!!!!. Ustedes dirán ¿Cómo sabes que cree un archivo? Para responder a esa pregunta veamos la siguiente función: FindFirstChangeNotification Api: Declare Function FindFirstChangeNotification Lib "kernel32" Alias "FindFirstChangeNotificationA" (ByVal lpPathName As String, ByVal bWatchSubtree As Long, ByVal dwNotifyFilter As Long) As Long Esta función sirve para ver o notificar algún cambio en un directorio. Dicha función se debe de utilizar con una función de sincronización que en este caso usamos una función de tipo “wait”. Ya hablaremos de eso adelante. Como primer parámetro le pasamos la ruta del directorio que queremos observar. Como segundo parámetro “bWatchSubtree” le pasamos TRUE o FALSE, si es FALSE solo se monitorea el directorio que se especifico en el segundo parámetro, en caso de que sea TRUE se monitorea desde el “root” del directorio especificado, y por ultimo tenemos el tercer parámetro que le podemos pasar las siguientes constantes, que especifican que tipo de notificación queremos capturar: Const FILE_NOTIFY_CHANGE_FILE_NAME = &H1 ‘ Con este parámetro monitoreamos la creación, eliminación o cambio de nombre de algún archivo. Const FILE_NOTIFY_CHANGE_ATTRIBUTES = &H4 ‘ Con este monitoreamos alguna modificación de los atributos del directorio. Const FILE_NOTIFY_CHANGE_DIR_NAME = &H2 ‘ Monitoreamos la creación y eliminación de algún directorio. Const FILE_NOTIFY_CHANGE_SIZE = &H8 ‘ Monitoreamos algún cambio en el tamaño del directorio. Const FILE_NOTIFY_CHANGE_LAST_WRITE = &H10 ‘ Monitoreamos las ultimas entradas a los archivos y directorios. Const FILE_NOTIFY_CHANGE_SECURITY = &H100 ‘ Monitoreamos algún cambio de seguridad. Ahora esta función no sirve, si no usamos alguna función de “wait function”. Que en nuestro caso es: WaitForSingleObject Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long NOTA: hay otras funciones que se pueden utilizar, que lo encuentran en el apartado que mencione arriba, como no vamos a explicar con detenimiento el funcionamiento de todas las funciones, nada mas me remito a explicar la que use. Que en este caso es WaitForSingleObject. Esta función nos sirve para esperar las alteraciones que se producen en un objeto, que en nuestro caso es un directorio. Como primer parámetro se le pasa dicho objeto. Y como segundo parámetro se le pasa el tiempo en milisegundos, que queremos que este esperando. Ya que seria muy riesgoso dejarlo de manera infinita. En caso de pasarle 0, la función verifica el estado del objeto y retorna inmediatamente. Los valores que puede retornar son: Const WAIT_ABANDONED = ((STATUS_ABANDONED_WAIT_0) + 0) Const WAIT_OBJECT_0 = ((STATUS_WAIT_0) + 0) ‘ Significa que la condición que pusimos a monitorear se estableció, es decir, “sucedió”. Const WAIT_TIMEOUT = 258& ‘ Significa que la función termino por limite de tiempo. En español, como seria entender todo esto, vayamos al código: hChequeo = FindFirstChangeNotification("C:\", False, FILE_NOTIFY_CHANGE_FILE_NAME) ‘ Creo un objeto en donde se monitorea a “C:\”, y lo que voy a monitorear es algún cambio en los archivos. Dim hObject As Long Dim bucle As Boolean bucle = True hObject = WaitForSingleObject(hChequeo, 50000) ‘ Creo el objeto de espera, el cual esperara que se produzcan dichos cambios en un periodo de 5 minutos. El sistema se mantendrá BLOQUEADO hasta que algún cambio ocurra o pasen los 5 minutos. Select Case hObject Case WAIT_OBJECT_0 ‘ Si hObject es WAIT_OBJECT_0 significa que hubo algún cambio, en los nombre, creación o eliminación de algún archivo en C:. Label2.Caption = "EPA POR QUE ANDAS CREANDO ARCHIVOS" Case WAIT_TIMEOUT ‘ Si entra aquí significa que el tiempo de espera termino. MsgBox "TIEMPO EXCEDIDO" End Select FindCloseChangeNotification hChequeo ‘ Cierro el objeto que se esta monitoreando. FindCloseChangeNotification Api: Declare Function FindCloseChangeNotification Lib "kernel32" (ByVal hChangeHandle As Long) As Long Función que se encarga de cerrar el objeto creado con FindFirstChangeNotification. Pueden ver lo interesante y asombroso de todo esto, y espero que al igual que a mi les haya gustado. TIPOS DE UNIDADES En este proyecto veremos como saber que tipo de unidades representan cada “letra” y el espacio disponible en cada unidad. Para el proyecto se necesitan solo 2 ListBox. Luego pegan este código: Ver Codigo
Creo que si corren el programa es fácil, ver lo que hace. Por lo que vamos a ir directo a las funciones involucradas en dicho proceso. GetDriveType Api: Declare Function GetDriveType Lib "kernel32" Alias "GetDriveTypeA" (ByVal nDrive As String) As Long Función utilizada para conocer que tipo de dispositivo representa alguna “ruta” o “letra”. La función retorna el tipo de dispositivo que es. Que viene determinado por las siguientes constantes: Const DRIVE_CDROM = 5 ‘ Significa que dicha unidad es un CDROM Const DRIVE_FIXED = 3 ‘ Significa que la unidad es un disco rígido, o disco duro Const DRIVE_RAMDISK = 6 ‘ Significa que la unidad un disco en memoria ram. Para poner un ejemplo, es lo que hace el disco de inicio de Windows 98. Const DRIVE_REMOTE = 4 ‘ Significa que la unidad es un disco conectado a una RED. Const DRIVE_REMOVABLE = 2 ‘ significa que la unidad es de disco flexible, ejemplo Floppy. Const DRIVE_UNKNOWN = 0 ‘ Significa que la unidad es desconocida. Ahora cada vez que presionan clic en una unidad “valida”, llamo unidad valida a una “letra” que represente algún dispositivo mencionado arriba, verán en el segundo listbox, el espacio libre y ocupado del mismo. Esto se logra por la siguiente función. GetDiskFreeSpaceEx Api: Declare Function GetDiskFreeSpaceEx Lib "kernel32.dll" Alias "GetDiskFreeSpaceExA" (ByVal lpDirectoryName As String, ByRef lpFreeBytesAvailableToCaller As Currency, ByRef lpTotalNumberOfBytes As Currency, ByRef lpTotalNumberOfFreeBytes As Currency) As Long Esta función sirve para saber los bytes libres y ocupados de una unidad de disco. Como primer parámetro le pasamos la unidad a verificar, como segundo parámetro pasamos una variable del tipo “currency” y dicha variable almacenara los bytes libres que están disponibles, como tercer parámetro tenemos el total de bytes que posee el dispositivo, y como último parámetro tenemos el total de bytes libres. ¿Por qué del tipo currency?. En la actualidad lo disco duros se expresan en GB, que es lo equivalente a 1.000.000.000 bytes, una variable de tipo long, no soporta dicha cifra, por consiguiente la variable en VB que puede soportar tal cifra es “currency”. Y como podrán ver en el ejemplo estas dos funciones son fáciles de usar. Pero hay una tercera que se ejecuta cuando le dan clic en el formulario, y verán en la ventana “inmediato” todas las letras que actualmente tienen ocupadas. GetLogicalDriveStrings Api: Declare Function GetLogicalDriveStrings Lib "kernel32" Alias "GetLogicalDriveStringsA" (ByVal nBufferLength As Long, ByVal lpBuffer As String) As Long Esta función se encarga de mostrar en una cadena de texto, todas las unidades lógicas que existen en la PC, como primer parámetro le pasamos la cantidad de bytes que queremos recuperar y como segundo parámetro pasamos la variable de tipo String que almacenara dicha información. Si la función se ejecuta con éxito, esta retorna el tamaño en bytes de la cadena almacenada. OTRAS FUNCIONES Estas funciones que expongo a continuación, son funciones sencillas, y por esa razón no desarrolle un proyecto, sino me limito solo a explicar como funciona. CopyFile Api: Declare Function CopyFile Lib "kernel32" Alias "CopyFileA" (ByVal lpExistingFileName As String, ByVal lpNewFileName As String, ByVal bFailIfExists As Long) As Long Función que copia un archivo de un lugar de origen a un lugar destino. Como primer parámetro se pasa el archivo a copiar, como segundo parámetro se tiene el archivo destino, que no tiene que llamarse igual al archivo de origen. Como tercer parámetro se le pasa TRUE o FALSE, de ser TRUE implica que si el archivo existe pues la función no hace nada, si se pone FALSE significa que en caso de existir el archivo la función lo sobrescribe. Ejm: Copyfile “C:\prueba.txt”, “D:\p.txt”, FALSE MoveFile Api: Declare Function MoveFile Lib "kernel32" Alias "MoveFileA" (ByVal lpExistingFileName As String, ByVal lpNewFileName As String) As Long Función que sirve para renombrar a un archivo o directorio. Como primer parámetro pasamos el archivo de origen, y como segundo parámetro el archivo nuevo. Ejm: MoveFile “C:\prueba.txt”, “C:\p.txt” DeleteFile Api: Declare Function DeleteFile Lib "kernel32" Alias "DeleteFileA" (ByVal lpFileName As String) As Long función que se encarga de eliminar a un archivo que se le pasa como primer parámetro. GetBinaryType Api: Declare Function GetBinaryType Lib "kernel32" Alias "GetBinaryTypeA" (ByVal lpApplicationName As String, lpBinaryType As Long) As Long función que se encarga de determinar si un archivo es ejecutable y en caso de serlo saber que tipo de aplicación es. Dicha información se retorna en la variable que se le pasa como segundo parámetro. Es decir, después de llamar a la función la variable pasada en el segundo parámetro puede ser igual a alguna de estas constantes: Const SCS_32BIT_BINARY = 0 ‘ El ejecutable es una aplicación basada en Windows 32Bits Const SCS_DOS_BINARY = 1 ‘ En una aplicación de DOS Const SCS_OS216_BINARY = 5 ‘ Es una aplicación de 16 bits basado en OS/2 Const SCS_PIF_BINARY = 3 ‘ Es una aplicación PIF que se ejecuta en DOS Const SCS_POSIX_BINARY = 4 ‘ Es una aplicación basado en POSIX Const SCS_WOW_BINARY = 2 ‘ Es una aplicación basado en Windows 16Bits Si la función retorna un valor distinto de 0 implica que el archivo es un ejecutable. GetFileAttributes Api: Declare Function GetFileAttributes Lib "kernel32" Alias "GetFileAttributesA" (ByVal lpFileName As String) As Long Función encargada de obtener los atributos de un archivo. Como primer parámetro se le pasa el archivo a verificar, y la función retorna los atributos del archivo. Para ver que atributos posee, aplican lo mismo que hicimos cuando usamos la estructura WIN32_FIND_DATA (dwFileAttributes) SetFileAttributes Api: Declare Function SetFileAttributes Lib "kernel32" Alias "SetFileAttributesA" (ByVal lpFileName As String, ByVal dwFileAttributes As Long) As Long Función utilizada para asignarle atributos a un archivo, dichos atributos con las constantes expuestas arribas que empiezan por FILE_ATTRIBUTE_..., como primer parámetro pasamos la ruta del archivo, y como segundo parámetro pasamos los nuevos atributos.
|