Estas são duas coisas diferentes:
% é o alias para o cmdlet ForEach-Object e foreach é também o alias para o cmdlet ForEach-Object ... e foreach é uma instrução de looping que não funciona com pipelining.
Conforme escrito, seu primeiro comando se expande para:
ForEach-Object ($i in $ints) {
Write-Host $i
}
... que não é uma sintaxe válida para o cmdlet ForEach-Object .
Quando foreach aparece, como no segundo comando, ele é interpretado como uma instrução foreach , não como o alias do cmdlet. Nesse caso, a sintaxe é válida e faz o loop conforme o esperado.
Você pode comparar as diferenças com get-help about_Foreach e get-help ForEach-Object . Esta postagem do blog Essencial PowerShell: Entendendo o foreach também faz um bom trabalho explicando.