Monday, January 11, 2021

Performing an Operation on All Servers in Active Directory

In a previous blog post, Getting a List of All of Your Windows Servers Using PowerShell, I showed you how to retrieve a list of all of your Windows Servers using PowerShell. In this post, I am going to expand on that post and create a script template that iterates across all the servers and performs a simple task, in this case a network ping.

Let's start by looking at the PowerShell code we wrote to retrieve the server list from Active Directory:

Get-ADComputer -Filter {OperatingSystem -like "*windows*server*"}

The only change we're going to make to this line of code is to assign the results to a variable:

$servers = Get-ADComputer -Filter {OperatingSystem -like "*windows*server*"}

The next step is to iterate over the list of servers.

$count = 0
foreach ($server in $servers)
{
    $count += 1
    $percentDone = $count / $servers.Count * 100
    Write-Progress -Activity "Scanning $($server.Name)..." -PercentComplete $percentDone
    
    if ((Test-Connection -ComputerName $server.DNSHostName -Count 1 -ErrorAction Ignore) -eq $null)
    {
    	continue
    }
}

Because I have a large number of servers in my production environment, over 700, I add a progress bar to many of my scripts so that I can monitor the progress as the script runs. I do this using the $count variable, which tracks how many servers the script has iterated over, and the $percentDone variable, which is the calculated completion percentage of the script. The Write-Progress cmdlet then display a progress bar and status message so that you can see the script progress through the list of servers.

Whenever you have a large number of servers in your environment, it is likely that there will be some servers listed in Active Directory that are no longer active. Because of this, I have added a Test-Connection command (the PowerShell equivalent of a ping) to the script, and immediately skip to the next server in the list if the Test-Connection fails. Depending on what operation you are performing, this can significantly increase the speed of the script.

The last thing we need to do is add an action to be performed on each server that is still active. In this case, I am just going to do another ping, but this time I will output the results of the ping to the console. And to make the script a little more modular, I will create a function to actually perform the ping operation.

The completed script look like this:

function PingServer
{
    param
    (
        [String]
        $ComputerName = $env:COMPUTERNAME,
    )
    
    return Test-Connection -ComputerName $ComputerName -Count 1
}

$servers = Get-ADComputer -Filter {OperatingSystem -like "*windows*server*"

$count = 0
foreach ($server in $servers)
{
    $count += 1
    $percentDone = $count / $servers.Count * 100
    Write-Progress -Activity "Scanning $($server.DNSHostName)..." -PercentComplete $percentDone
    
    if ((Test-Connection -ComputerName $server.DNSHostName -Count 1 -ErrorAction Ignore) -eq $null)
    {
    	continue
    }
    
    PingServer -ComputerName $server.DNSHostName
}

On my test network, I get the following output:



We can replace the PingServer function with any other function that performs an operation on a single server. We will use this template in the future to do some very useful work on our entire server list.

If you found this blog helpful or have a question, please leave a comment.

Thanks for reading.

No comments:

Post a Comment