Get AD Users' Latest Last Logon Dates across Multiple DCs
Aliases

You're used to my reviews by now so you're probably tired of me saying this, but avoid aliases and abbreviations (% vs ForEach-Object, Select vs Select-Object, -expand vs -ExpandProperty, sort vs Sort-Object, etc.).



Backticks &#96; as line continuation

Try to avoid shortening lines with backtick where possible. The backticks are hard to see / easy to miss. 

Note that you can end a line with a pipe | or an operator and continue on the next line without the backtick, which I think is a much more flexible solution:

Get-ADObject -Filter { whatever } |
Sort-Object BySomething |
Select-Object Thing1,Thing2,Thing3 |
Where-Object {
    $_.A -eq 5 -and
    $_.Z -like '*what*' -and
    $_.BoolProp
} |
Format-Table


As an added bonus, it doesn't confuse the syntax highlighting on these sites!



Domain Controller Discovery

When finding a domain controller in a certain region, you might consider filtering on Site. Nothing wrong with going by your naming convention, although it's more likely for that to change, or for a short pattern like ES* to match something else; I'm sure you've considered that and your pattern is fine, just offering another suggestion.

I also like to add -Discover, -ForceDiscover, and -Service ADWS to ensure that you are finding DCs that are available and usable with PowerShell. Combined:

$DCs = Get-ADDomainController -Discover -ForceDiscover -SiteName Spain -Service ADWS | Select-Object -Expand Name




Logon Dates

You're probably already familiar with the logon date attributes in AD, but I'll summarize:


LastLogon &mdash; Updated every time a user logs on, but only on the domain controller that authenticated the user. This value is not replicated.
LastLogonTimestamp &mdash; This value is replicated, but to avoid heavy replication traffic it's not updated every time, so you sacrifice accuracy (it could be as much as 2 weeks off by default), but you only have to query a single DC to get the value. This value is also annoying to turn into an actual date.
LastLogonDate &mdash; This is not actually in AD. It's provided by the PowerShell cmdlets, and it's a real [DateTime] object that has the same value as LastLogonTimestamp, which makes it really convenient to use and filter on.


So, depending on how accurate you really need this process to be, you might avoid querying all the DCs in the first place and just take LastLogonDate as being "Close Enough" for your purposes. It would simplify things greatly if that's acceptable.

The thing is, this also reveals a problem in your script. You are already using LastLogonDate, you're just querying it from every DC instead of using LastLogon. As long as replication is working correctly, that value will always be the same, so querying multiple DCs is unnecessary.

If you want the precision, you need to use LogonDate (and do the appropriate conversions like in the technet script you linked to). This is probably why Group-Object is not often used. Because it's not so trivial to treat this attribute directly as a [DateTime].



Search-ADAccount

I'm not sure I understand the aversion to using Search-ADAccount. The object returned is still an AD account object, and it includes the LastLogonDate property so you can return that.

After re-reading it I understand; you're not filtering on any specific date in this script. So you're returning all users and their dates.



Simplification

Based on what I wrote above, I might suggest a more simple solution (I know this isn't SO but, it's basically a one-liner...):

$DC = Get-ADDomainController -Discover -ForceDiscover -SiteName Spain -Service ADWS | Select-Object -Expand Name -First 1
Get-ADUser -SearchBase $SearchBase -Filter { Enabled -eq $true } -Properties LastLogonDate -Server $DC |
Sort-Object SamAccountName |
Select-Object SamAccountName,Name,LastLogonDate


I would even add that because the attribute is replicated, there's no need to query a Spanish DC; you can leave out the whole discovery part and just let Get-ADUser use the logon server, or use discovery but don't limit it to a site. It should in theory be more efficient to simply query the closest DC to where the script is running.