As stated in comments, you can use -ErrorAction Stop so that PowerShell treats the error as a terminating one, that way the error will be caught by your try block.
Regarding how you can change the logic of your script so that, it can catch an error but also does not stop further processing. For this you just need to put your try / catch statement inside the loop:
(Get-LocalUser | ? Enabled).Name | ForEach-Object {
try {
Add-LocalGroupMember -Group "Hyper-V Administrators" -Member $_ -ErrorAction Stop
}
catch {
Write-Error -Message 'Failed to add user' -Exception $_.Exception
}
}
Get-LocalUser | Where-Object Enabled | ForEach-Object {
try {
$addLocalGroupMemberSplat = @{
Group = 'Hyper-V Administrators'
Member = $_
ErrorAction = 'Stop'
}
Add-LocalGroupMember @addLocalGroupMemberSplat
}
catch {
Write-Error -Message 'Failed to add user' -Exception $_.Exception
}
}