En este ejercicio se propone una aplicación que borra los archivos temporales de Windows XP y la carpeta que los contiene, leyendo la variable de entorno TEMP, definida para el usuario de la sesión actual. Además, se muestra al usuario información sobre:
Durante varios años he utilizado un script de Visual Basic DeleteTempFiles.vbs, creado en 1999 por Michael Harris y modificado posteriormente por Bill James y Marcial Carlés. Este script funciona correctamente, borrando los archivos temporales de Windows e informando al usuario del tamaño de los archivos borrados (dato que guarda en un archivo de texto en el directorio de Windows). Pero ha llegado el momento de plantear: ¿por qué no hacerlo con .NET? Y el resultado es esta aplicación, inspirada en DeleteTempFiles.vbs en cuanto a su función principal y también en cuanto al mantenimiento de información en un archivo de texto. En lugar de guardar el tamaño, se guarda el número acumulado de los archivos borrados.
A continuación se comentan los detalles más interesantes del código Visual Basic .NET.
'manejo de archivos y carpetas Imports System.IO 'obtener variables de entorno Imports System.Environment 'tratar cadenas de texto (ejemplo: codificación usada al escribir en un archivo de texto) Imports System.Text 'proporciona clases e interfaces que permiten la programación multiproceso Imports System.Threading
'variables declaradas a nivel de clase
'
'ruta a la carpeta definida en la variable de entorno TEMP
Protected rutaTemp As String = Environment.GetEnvironmentVariable("TEMP")
'ruta a la carpeta de sistema (WINDIR --> directorio de Windows)
Protected rutaWindir As String = Environment.GetEnvironmentVariable("WINDIR")
'variable para la ruta completa al archivo de texto que registra el nº de archivos borrados
Protected rutaTxt As String = rutaWindir & "\Borrar_TEMP.txt"
'variables para guardar nº de archivos
'iCuentaTempAll --> todos los archivos encontrados en TEMP
Protected iCuentaTempAll As Integer
'lCuentaBorrados --> nº de archivos borrados hasta la fecha
Protected lCuentaBorrados As Long
'al cargar el formulario
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'pulsar la tecla ESC equivale a pulsar el botón OK
Me.CancelButton = Me.Button1
End Sub
'comprobar si el archivo de registro existe (crearlo si no existe)
Protected Sub archivoTxt()
Dim archivo As New FileInfo(rutaTxt)
'si "Borrar_TEMP.txt" no existe --> crearlo e informar al usuario para que reinicie
If archivo.Exists = False Then
archivo.CreateText()
Dim aviso As String
aviso = "Se ha creado el archivo ""Borrar_TEMP.txt"" en la carpeta de Windows." & vbCrLf & _
"Es necesario reiniciar el programa para su correcto funcionamiento." & vbCrLf & _
"Pulsa ""Aceptar"" y el programa se cerrará y reiniciará automáticamente."
MessageBox.Show(aviso, "Reiniciar el programa", MessageBoxButtons.OK)
'
'cerrar el formulario y que se vuelva a abrir automáticamente para que en el nuevo inicio
'lea correctamente desde el archivo Borrar_TEMP.txt y muestre la información
'
'crear un nuevo hilo (thread) que se enlaza con el método nuevoForm()
'que arrancará otra instancia diferente de Form1
Dim hilo As New Thread(AddressOf nuevoForm)
hilo.Start()
'cerrar la aplicación y su hilo actual
Application.Exit()
'
'si "Borrar_TEMP.txt" ya existe --> ejecutar el programa con normalidad
Else
'llamar a los métodos:
'- leer el nº de archivos del directorio y el nº acumulado de archivos borrados en "Borrar_TEMP.txt"
Call listadoPre()
'- leer el nº de archivos borrados en la ejecucion actual y escribir en "Borrar_TEMP.txt"
Call listadoPost()
End If
End Sub
'método que inicia de nuevo la aplicación
Public Shared Sub nuevoForm()
'detenerse 0,2 segundos
Thread.Sleep(200)
'iniciar de nuevo la aplicación en el nuevo hilo
Application.Run(New Form1)
End Sub
'método que cuenta los archivos y las carpetas de TEMP antes del borrado
Protected Sub listadoPre()
Try
'variables para guardar el nº de archivos
'iCuentaTempPre = nº de archivos en la raíz de TEMP
'iCuentaSubdirPre = nº de carpetas en la raíz de TEMP
'iCuentaSubdirFilesPre = nº de archivos en las carpetas de la raíz de TEMP
Dim iCuentaTempPre, iCuentaSubdirPre, iCuentaSubdirFilesPre As Integer
'la clase DirectoryInfo expone métodos de instancia para crear, mover y
'enumerar archivos en directorios y subdirectorios
'se utiliza para operaciones típicas como copiar, mover, cambiar de nombre,
'crear y eliminar directorios
Dim dirTemp As New DirectoryInfo(rutaTemp)
'comprobar si el directorio existe
If dirTemp.Exists = True Then
'contar los archivos de la raíz de TEMP (no en subdirectorios)
iCuentaTempPre = dirTemp.GetFiles.Length
'contar todos los subdirectorios de TEMP
Dim dirSub As FileSystemInfo() = dirTemp.GetDirectories()
iCuentaSubdirPre = dirSub.Length
'contar todos los archivos de cada subdirectorio (sólo en el primer nivel de subdirectorios)
Dim dirTemp2 As New DirectoryInfo(rutaTemp)
For Each dirTemp2 In dirSub
iCuentaSubdirFilesPre += dirTemp2.GetFileSystemInfos.Length
Next
'mostrar información en la etiqueta de texto
Me.Label1.Text = (iCuentaTempPre + iCuentaSubdirFilesPre).ToString
'valor de t = nº total de archivos encontrados antes de borrar TEMP
iCuentaTempAll = (iCuentaTempPre + iCuentaSubdirFilesPre)
'
'leer el nº de archivos borrados hasta la fecha desde un archivo de texto guardado en %WINDIR%
'el archivo se llama C:\Windows\Borrar_TEMP.txt (siendo %WINDIR% = C:\Windows en este caso)
'las clases Stream.Reader y Stream.Writer permiten tratar con archivos de texto secuenciales
Dim srLector As StreamReader
'variable para la primera línea del archivo de texto
Dim sLinea As String
'
'leer la primera línea y pasarla a lCuentaBorrados
srLector = New StreamReader(rutaTxt)
sLinea = srLector.ReadLine
lCuentaBorrados = CLng(sLinea)
'cerrar el archivo
srLector.Close()
'
'el método DirectoryInfo.Delete elimina una instancia de DirectoryInfo
'especificando si se van a eliminar los subdirectorios y los archivos (True o False)
'se asigna al directorio de archivos temporales
dirTemp.Delete(True)
Else
'si no existe el directorio TEMP
Me.Label1.Text = "0"
Me.Label2.Text = "0"
End If
'capturar excepciones
Catch pollo As Exception
'pasar por alto la excepción si la causa es no poder borrar archivos por estar en uso (excepción System.IO.IOException)
Dim sTipo As String
sTipo = "System.IO.IOException"
If Not pollo.GetType.ToString = sTipo Then
MessageBox.Show(pollo.Message, "Aviso del programa", MessageBoxButtons.OK)
Application.Exit()
End If
End Try
End Sub
'método que cuenta los archivos de TEMP después del borrado
'estos archivos son los que no han podido ser borrados porque están en uso
Protected Sub listadoPost()
Try
'variables para guardar el nº de archivos
'iCuentaTempPost = nº de archivos en la raíz de TEMP
'iCuentaSubdirPost = nº de carpetas en la raíz de TEMP
'iCuentaSubdirFilesPost = nº de archivos en las carpetas de la raíz de TEMP
Dim iCuentaTempPost, iCuentaSubdirPost, iCuentaSubdirFilesPost As Integer
'la clase DirectoryInfo expone métodos de instancia para crear, mover y
'enumerar archivos en directorios y subdirectorios
'se utiliza para operaciones típicas como copiar, mover, cambiar de nombre,
'crear y eliminar directorios
Dim dirTemp As New DirectoryInfo(rutaTemp)
'comprobar si el directorio existe
If dirTemp.Exists = True Then
'contar los archivos de la raíz de TEMP (no en subdirectorios),
iCuentaTempPost = dirTemp.GetFiles.Length
'
'ahora no hace falta contar los archivos de las subcarpetas pues el método
'dirTemp.Delete(True) las ha eliminado
'contar todos los subdirectorios de TEMP
'Dim dirSub As FileSystemInfo() = dirTemp.GetDirectories()
'iCuentaSubdirPost = dirSub.Length
'contar todos los archivos de cada subdirectorio (sólo en el primer nivel de subdirectorios)
'Dim dirTemp2 As New DirectoryInfo(rutaTemp)
'For Each dirTemp2 In dirSub
' iCuentaSubdirFilesPost += dirTemp2.GetFileSystemInfos.Length
'Next
'
'nº de archivos borrados hasta la fecha + nº de archivos borrados en la ejecución actual
lCuentaBorrados = lCuentaBorrados + (iCuentaTempAll - iCuentaTempPost)
'
'escribir el nº de archivos en un archivo de texto guardado en %WINDIR%
'el archivo se llama C:\Windows\Borrar_TEMP.txt (siendo %WINDIR% = C:\Windows en este caso)
'las clases Stream.Reader y Stream.Writer permiten tratar con archivos de texto secuenciales
Dim swEscritor As StreamWriter
'variable para la primera línea del archivo de texto
Dim sLinea As String
' StreamWriter recibe 3 parámetros:
'- String con la ruta al archivo
'- True para añadir texto al existente, False para sobreescribir el texto existente
'- codificación de caracteres que se utilizará (default: página de códigos ANSI usada por el sistema)
swEscritor = New StreamWriter(rutaTxt, False, Encoding.Default)
sLinea = CStr(lCuentaBorrados)
'escribir el valor de lCuentaBorrados en la primera línea
swEscritor.WriteLine(sLinea)
'cerrar el archivo
swEscritor.Close()
'
'mostrar información en la etiqueta de texto
'variable iCuentaTempAll --> total de archivos encontrados antes de borrar TEMP
'restándole los archivos no borrados por estar en uso --> archivos borrados realmente
Me.Label2.Text = (iCuentaTempAll - iCuentaTempPost).ToString
'variable lCuentaBorrados --> nº de archivos borrados hasta la fecha + nº de archivos borrados en la ejecución actual
If lCuentaBorrados = 0 Then
Me.Label3.Text = "Ningún archivo"
Else
Me.Label3.Text = lCuentaBorrados.ToString("#,#") & " archivos"
End If
Else
'crear el directorio temporal en caso de que no exista
'algunos programas arrancan con errores si no detectan la presencia del directorio definido en TEMP
'por ejemplo: Visual Studio da error de compilador, Media Player no inicia correctamente...
dirTemp.Create()
Me.Label1.Text = "0"
Me.Label2.Text = "0"
End If
'capturar excepciones
Catch pollo As Exception
MessageBox.Show("AVISO: " & pollo.Message, "Aviso del programa", MessageBoxButtons.OK)
Application.Exit()
End Try
End Sub
Private Sub PictureBox2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PictureBox2.Click
Dim ayuda As String = "Borra los archivos temporales y la carpeta que los contiene" & vbCrLf & _
"(variable de entorno TEMP, definida para el usuario actual)." & vbCrLf & vbCrLf & _
"Muestra al usuario información sobre:" & vbCrLf & _
"- Nº de archivos encontrados en la ejecución actual." & vbCrLf & _
"- Nº de archivos borrados en la ejecución actual." & vbCrLf & _
"- Nº total acumulado de archivos borrados por el programa" & vbCrLf & _
" (leyendo este dato desde un archivo de texto en C:\WINDOWS)."
MessageBox.Show(ayuda, "Acerca de...", MessageBoxButtons.OK)
End Sub
Nos interesan dos tipos de excepción que pueden aparecer cuando al programa no le es posible borrar algún archivo, lo que suele suceder porque el archivo está en uso o porque no se puede acceder a él por algún otro motivo. Se trata de las excepciones "System.IO.IOException" y "System.UnauthorizedAccessException"; es recomendable no capturar estas 2 excepciones en el método listadoPre() para no interrumpir el flujo del programa y evitar avisos de error:
'capturar excepciones Catch pollo As Exception 'pasar por alto la excepción si la causa es no poder borrar archivos por estar en uso ' (excepción System.IO.IOException o System.UnauthorizedAccessException) Dim sTipo1, sTipo2 As String sTipo1 = "System.IO.IOException" sTipo2 = "System.UnauthorizedAccessException" If Not pollo.GetType.ToString = sTipo1 And Not pollo.GetType.ToString = sTipo2 Then MessageBox.Show(pollo.Message, "Aviso del programa", MessageBoxButtons.OK) Application.Exit() End If End Try
