Estoy en un cliente con unos pocos buzones de Exchange, sobre los 16.000, cuyos usuarios hacen experimentos con las convocatorias de Exchange como borrarlas sin avisar a los convocados, moverlas, no aceptarlas…. cosa que produce errores en el subsistema de Calendar Repair de Exchange en forma de bastantes avisos.
El caso es que el cliente quiere que se cree un script de PowerShell que busque una sèrie de errores y los vuelque en ficheros. Así que, después de experimentar un poco dado que no soy un experto en teclear me ha salido esto:
#############################################################################################
# PowerShell Script to check errors in Exchange calendars in recursion
# Author: Marc Salvador
# Version 1.0 – Versión inicial con control de errores y logs de salida
# Version 1.1 – Versión con descarte por fechas
# Version 1.2 – Eliminación de los logs de anteriores ejecuciones. NO PREGUNTA!!!
################################################################################################
# Definición de variables
$path = «D:\PowerShell\Calendar Repair Assistant»
$pathLog = «D:\PowerShell\Log»
# Se usan arrays para almacenar los datos de los ficheros y los errores en las citas
$filesInPath = @()
$CitesErronies = @()
#
———————————————————————-
# Control de errores: Existencia de la carpeta con los ficheros a tratar
#
if (!(Test-Path -Path $path))
{
Write-Host «No se encuentra la ruta de los archivos de ‘Calendar Repair Assistant’ en $path« -ForegroundColor Red
Break
}
# ———————————————————————-
# Control de errores: Creamos un directorio para guardar los logs del
# resultado del tratamiento de ficheros LOG/XML
if (!(Test-Path -Path $pathLog))
{
Write-Host «No se encuentra la ruta de los archivos de log en $pathlog» -ForegroundColor Red
New-Item -ItemType Directory -Path $pathLog -ErrorAction Stop
Write-Host «Directorio Log creado correctamente en $pathLog» -ForegroundColor Green
}
else
{
$directoryInfo = Get-ChildItem $pathLog | Measure-Object
# Contamos el número de elementos del directorio.
$ficherosTotales = $directoryInfo.count
# Si no es cero, es que no está vacío y se puede borrar
If ($directoryInfo.count -ne 0)
{
Remove-Item $pathLog\*.txt -Recurse -ErrorAction SilentlyContinue
Write-Host «$ficherosTotales ficheros de logs antiguos borrados en $pathlog» -ForegroundColor Yellow
}
}
#########################################################################
# Cuerpo principal del programa
#########################################################################
# Capturamos la fecha/hora del sistema.
$Date = Get-Date
# Fechas de inicio y finalización de la ejecución
$DateScriptH = Get-Date -Format t
$DateScriptD = Get-Date -Format d/M/y
# Obtenemos los nombres de los ficheros a analizar
$filesInPath = Get-ChildItem -Path $path -ErrorAction Stop
Try
{
Write-Host «Inicio de la ejecución del script a las $DateScriptH del día $DateScriptD« -ForegroundColor cyan
ForEach ($logs in $filesInPath)
{
# Obtenemos los nombres de los ficheros a analizar junto con el path donde se encuentran
$filesInPath = $path + «\» + $logs
# Convertimos los datos a XML
$xml = [xml](Get-Content $filesInPath -ErrorAction Stop)
# Seleccionamos los datos del XML que queremos tratar
$meetings = $xml.SelectNodes(«/CalendarRepairLog/Meetings/Meeting») | Where-Object {([DateTime]$_.StartTime) -ge $Date}
# Tratatamos los datos seleccionados
foreach ($meeting in $meetings)
{
# Buscamos los usuarios convocados en las citas
$attendees = $meeting.Attendees.Attendee
foreach ($attendee in $attendees)
{
# Buscamos los errores de en los calendarios de cada usuarios
$ConsistencyChecks = $attendee.ConsistencyChecks.ConsistencyCheck | Where-Object {$_.Result -eq «Failed»}
foreach ($ConsistencyCheck in $ConsistencyChecks)
{
# Guardamos los datos de error de cada cita de cada usuario en un array y
# lo guardamos en un fichero para cada usuario
$CitesErronies += ,($meeting.Subject, $meeting.StartTime, $meeting.Organizer, $attendee.EmailAddress, $ConsistencyCheck.Description) | Out-File -FilePath $pathLog\$logs-Resultado.txt -Force -ErrorAction SilentlyContinue
}
}
}
}
}
Catch [System.exception]
{
$ErrorMessage = $_.Exception.Message
$FailedItem = $_.Exception.ItemName
Write-host «Se ha producido un error de ejecución $FailedItem en el entorno $ErrorMessage « -ForegroundColor Red
Break
}
Catch
{
$ErrorMessage = $_.Exception.Message
$FailedItem = $_.Exception.ItemName
Write-host «Se ha producido un error de ejecución $FailedItem en el entorno $ErrorMessage « -ForegroundColor Red
Break
}
Finally
{
# Fechas de inicio y finalización de la ejecución
$DateScriptH = Get-Date -Format t
$DateScriptD = Get-Date -Format d/M/y
Write-Host «Finalización de la ejecución del script a las $DateScriptH del día $DateScriptD« -ForegroundColor cyan
write-host «Los logs de ejecución están en $pathLog» -ForegroundColor Green
}
Acepto comentarios de mejora como, por ejemplo, que genere un HTML por cada usuario y se lo envíe por correo…