In un recente progetto di migrazione a Exchange Online da una precedente soluzione di posta elettronica, mi sono trovato ad avere a che fare con molti client su cui la posta era archiviata in numerosi file PST locali.
Questo ovviamente esponeva a numerosi rischi il sistema, primo di tutti la perdita di dati: se un file PST si corrompe – e non è difficile con PST da 20 o 30 GB – i dati sono quasi sicuramente persi, anche perché non c’era backup dei client. Oltretutto, i PST non offrono agli amministratori la possibilità di controllarne l’uso ed il contenuto facilmente: insomma, un vero incubo per un admin di Exchange!
Dopo aver migrato le caselle di produzione da server a server, dovevo quindi “scovare” tutti i PST sparsi nei vari computer del dominio, per poi raccoglierli su una share di rete e importarli in Exchange Online.
Ho deciso di scrivere da solo un piccolo tool in PowerShell allora che andasse a fare questo lavoro per me, risparmiando molte ore uomo di lavoro. I requisiti per eseguire lo script sono i seguenti:
– privilegi di amministratore sulle macchine in cui cercare
– un computer Windows con almeno PowerShell 5.1
– raggiungibilità dei computer target via rete
Durante l’esecuzione, lo script mostra a console quello che sta facendo:
Alla fine vi troverete un file CSV con tutti i PST (con nome del computer, nome del file, path completo e dimensione in GB), che poi potrete importare anche in Excel e procedere quindi poi con la raccolta dei file PST:
I computer che risulteranno offline dalla prima esecuzione potranno poi essere facilmente riscansionati in seguito, confrontando il file di log e quello dei computer da processare:
Questo il codice dello script – che potete altrimenti scaricare da GitHub:
#region Credits
# Author: Federico Lillacci - Coesione Srl - www.coesione.net
# GitHub: https://github.com/tsmagnum
# Version: 1.1
# Date: 26/02/2024
#endregion
#region TODO
#endregion
#Storing the execution time in a variable; used to name the log and results file
$executionTime = (Get-Date).ToString('yyyyMMdd-hhmm')
#region VARIABLES
#please set these variables before running the script
#Txt file with the computers to process, one per line
$Computers = Get-Content -Path "C:\Scripts\ClientsTest.txt"
#Log file of the processed computers
$processedPCs = "C:\Scripts\$($executionTime)_ProcessedPC.txt"
#Results file
$csvPath = "C:\Scripts\$($executionTime)_PstFilesFound.csv"
#endregion
#Begin script execution
#Creating an empty array for the results
$results = @()
Set-Content $processedPCs -Value "Logging script execution - $($executionTime)"
Foreach ($Computer in $Computers)
{
#Checking if the target computer is online: if so, the check continues
Write-Host -ForegroundColor Cyan "Checking if $($Computer) is online"
$pingtest = Test-Connection -ComputerName $Computer -Quiet -Count 1 -ErrorAction SilentlyContinue
if ($pingtest)
{
$message = "$($Computer) is online, looking for PST files..."
Write-Host -ForegroundColor Cyan $message
Add-Content -Path $processedPCs -Value $message
#Performing the search
$pstFiles = Get-Wmiobject -namespace "root\CIMV2" -computername $Computer -Query "Select * from CIM_DataFile Where Extension = 'pst'"
#Storing the results in PS Object
Foreach ($file in $PstFiles)
{
$result = [PSCustomObject]@{
Computer = $file.CSName
Name = $file.Filename
Path = $file.Description
Size = ($file.FileSize)/1GB
LastAccess = ($file.LastAccessed.Split("."))[0]
}
Write-Host -ForegroundColor Green "PST found! Adding $($result.Name) to results"
$results += $result
#End 3rd foreach
}
#End 2nd foreach
}
#Logging offline computers
else {
$message = "$($Computer) is offline, skipping PST search"
Write-Host -ForegroundColor Red $message
Add-Content -Path $processedPCs -Value $message
}
#End 1st foreach
}
#Saving results to a CSV file
$results | Export-Csv -Path $csvPath -NoTypeInformation