Skip to content

List all computers with a specific file

Problem to solve

The customer has clients with locally stored application files. The files are from an earlier application and should not be used anymore. I needed to verify that the application files was removed from the clients. I did not want to walk to each 500+ clients so I created a small script to use “test-path” to see if the files were removed and then summarise it.

Script breakdown

The script is small so I do a quick breakdown.

Get all computer-objects in AD

Retrieve all computers from AD. There is so few servers and other computers that I did not filter it.

$computers = Get-ADComputer -Filter * | select name

Test if there is a DNS record for the computer

Now we iterate through the $computers and test each computer if we can find it in the DNS. The reason for the DNS lookup is that I got almost 1000 computer objects from AD and I know that there is only about 500 computers.

if ([bool](Resolve-DnsName $computer -ErrorAction Ignore))

Test if the computer is reachable

Now we know that the computer has been live the last 7 days (DNS scavenging), so let us see if the computer is live right now.

if ([bool](test-netconnection $computer -ErrorAction Ignore  -InformationLevel Quiet) )

Test if the path exists

At this point we know that the computer is reachable so let us try to verify the path.

$path = "fu"
if (test-path $path)

 ```

### Run foreach parallel

Not to watch paint dry I ran the test in parallel with powershell jobs.

### Result

How did I publish my result? I returned all results in a hash table and then used the group cmdlet. I could then see that no clients had the application path on the computers.

```powershell
$data | group

## The complete script
```powershell
# Retrieve all computers
$computers = Get-ADComputer -Filter * | select name

#Empty job queue
Get-Job | Receive-Job

$data = @()
$i = 0
#Iterate through all computers
foreach ($computer in $computers)
{
    $i += 1
    $running = @(Get-Job | Where-Object { $_.State -eq 'Running' })
    Write-Progress -Activity "Looking up Clients" -Status "Running $($running.Count) simultaneous: " -PercentComplete ($i/$computers.Count)
    if ($running.Count -le 20)
    {
        Start-Job -Scriptblock {

            param ($computer)
            # write-host -ForegroundColor Green "=== Checking client: $computer ==="
            if ([bool](Resolve-DnsName $computer -ErrorAction Ignore))
            {
                if ([bool](test-netconnection $computer -ErrorAction Ignore -InformationLevel Quiet))
                {
                    # write-host -foreground green "Client is up, checking for file..."
                    $path = "\\$computer\c$\temp\login.txt"
                    if (test-path $path)
                    {
                        # write-host -foreground green "$(get-content $path)"
                        "Success"
                    }
                    else
                    {
                        # write-host -foreground red "Could not find: $path"
                        "FileFail"
                    }
                }
                else
                {
                    # write-host -foreground red "Client: $computer is not reachable..."
                    "PingFail"
                }
            }
            else
            {
                # write-host -foreground red "Client: $computer could not be looked up..."
                "DNSFail"
            }

        } -arg "$($computer.name)"
    }
    else
    {
        Start-Sleep -Milliseconds 100
    }
    $data += Get-Job | Receive-Job
}
$data | group