Archive

Archive for October 13th, 2014

Powershell script: Invoke-CommandOnADComputers

October 13th, 2014 No comments

Sometimes I need to run some command on bunch of computers. So I’ve created little bit more advanced function to be able to run script block on computers list created from domain:

 


<#
.Synopsis
   This function provides you way to run scriptblock on remote machines in the domain.
.DESCRIPTION
   This function is extension to Cmd-Let Invoke-Command. This function lists computer names in domain
   based on ADSearchBase and Filter parameters. In invoke scriptblock on those computers in the list.
.EXAMPLE
   To restart service "Windows Time" on all machines in domain:
   Invoke-CommandOnADComputers -SearchBase "DC=domain,DC=local" -ScriptBlock { Restart-Service W32Time; }
.EXAMPLE
   To restart service "Windows Time" on all machines which containt number 7 in name:
   Invoke-CommandOnADComputers -SearchBase "DC=domain,DC=local" -Filter 'Name -like "*7*"' -ScriptBlock { Restart-Service W32Time; }
#>

Function Invoke-CommandOnADComputers
{
    [CmdletBinding(SupportsShouldProcess=$True,ConfirmImpact='Low')]
    Param
    (
        # This is Active Directory Search Base to limit selection for computer accounts in domain.
        # It can be for example "OU=Computers,OU=Company Name,DC=domain,DC=local"
        [parameter(Mandatory=$true)]
        [string]
        $SearchBase,

        # Active Directory filter to merge your computer selection in to the detail.
        # It can be for example 'Name -like "Desktop*"'
        [string]
        $Filter = "*",

        # This is scriptblock which should be run on every computer.
        # For example { Restart-Service W32Time; }
        [parameter(Mandatory=$true)]
        [scriptblock]
        $ScriptBlock
    )
    Begin
    {
        #
        # Get list of computer accounts
        #
        Write-Verbose "Getting list of computer from $ADSear"
        try
        {
            [array]$ADComputersList = Get-ADComputer -SearchBase $SearchBase -Filter $Filter -ErrorAction Stop
        }
        catch
        {
            Write-Error -Message "Couldn't search in $SearchBase" -ErrorAction Stop
        }
        #
        # Write number of found computers
        #
        Write-Host "Found $($ADComputersList.Count) computers"
        #
        # If in debug, write list of computers
        #
        Write-Verbose "List of machines:"
        If (!$PSDebugContext)
        {
            foreach ($item in $ADComputersList)
            {
                Write-Verbose " $($item.Name)"
            }
        }
        Write-Verbose "Done with domain computer list"
    }
    Process
    {
        #
        # Let's invoke command on remote computer
        #
        foreach ($ADComputer in $ADComputersList)
        {
            Write-Host $ADComputer.Name
                try
                {
                    Write-Verbose "Invoking scriptblock on computer"
                    Invoke-Command -ComputerName $ADComputer.Name -ScriptBlock { $ScriptBlock } -ErrorAction Stop
                    Write-Host " Scriptblock invoked successful."
                }
                catch
                {
                    Write-Host " Scriptblock invoked UNSUCCESSFUL."
                }
        }
    }
}

You can run it using

Invoke-CommandOnADComputers -SearchBase “DC=domain,DC=local” -ScriptBlock { Restart-Service W32Time; }

and it will read all computer accounts from domain and restart Windows Time service.

Enjoy,