Search code examples
powershellforeachactive-directorypipeline

How to pass variables into Write-Host with pipeline


I have the following bit of script:

try {
    Get-ADUser -Properties Department -Filter $Filter | Where-Object {$_.Department -eq $old} | Set-ADUser -Department $new
} catch { Write-Host "Error occured" -BackgroundColor Red -ForegroundColor Black }

Which changes a given set of user's department to the chosen department ($new).

I would like it to display Successfully updated [$user.Name] with Write-Host after each user is updated, but I can't work out how to do this with pipeline!

I managed to use a foreach, but it doesn't look as good:

$users = Get-ADUser -Properties Department -Filter $Filter | Where-Object {$_.Department -eq $old}
ForEach ($user in $users) {
    try{
        Set-ADUser $user -Department $new
        Write-Host "Department changed: "$user.Name -BackgroundColor Green -ForegroundColor Black
    } catch { Write-Host "Error occured" -BackgroundColor Red -ForegroundColor Black }
}

Can anyone suggest a way of achieving this while still maintaining the succinct format of the first example?


Solution

  • You're going to have to use some kind of iteration/indexing at some point to achieve this, with the try/catch inside. The catch block is not part of the pipeline.

    I might suggest ForEach-Object instead of foreach:

    Get-ADUser -Properties Department -Filter $Filter | 
        Where-Object {$_.Department -eq $old} |
        ForEach-Object {
            $user = $_
            try{
                Set-ADUser $user -Department $new
                Write-Host "Department changed: "$user.Name -BackgroundColor Green -ForegroundColor Black
            } catch { Write-Host "Error occured" -BackgroundColor Red -ForegroundColor Black }
        }
    

    Alternatively, write your own function to handle this, which takes pipeline input:

    function Set-MyUserDepartment {
    [CmdletBinding()]
    param(
        [Parameter(
            Mandatory = $true,
            ValueFromPipeline = $true,
            ValueFromPipelineByPropertyName = $true
        )]
        [String[]]
        $Name ,
    
        [Parameter(
            Mandatory = $true
        )]
        [String]
        $NewDepartment
    )
    
        Process {
            foreach($user in $Name) {
                try{
                    Set-ADUser $user -Department $NewDepartment
                    Write-Host "Department changed: $user" -BackgroundColor Green -ForegroundColor Black
                } catch { Write-Host "Error occured" -BackgroundColor Red -ForegroundColor Black }
            }
        }
    }
    

    Then you can use it nicely:

    Get-ADUser -Properties Department -Filter $Filter | 
        Where-Object {$_.Department -eq $old} |
        Set-MyUserDepartment -NewDepartment $new