Pulls a list of servers from AD, then starts a job for each server to query WMI for the owner of all explorer.exe processes.  Parses that info into an array of users which has a server property, and puts the servers that each of those users is logged onto in that property.

The start-job command is using a scoping command that only works in Powershell v3.

Changing the script to pull the group of users or the list of servers from files would be simple, however you would probably need to change all instances of "$s.name" to just "$s".

# Created by Shawn Cude 
# Date: 4/26/2012 
# Get all servers a list of 
# of users is logged on to. 
$starttime = get-date 
# Gets all servers from the servers OU in fabrikam.com: 
write-host "Getting server list." 
$servers = get-adcomputer -Filter {name -like "*"-SearchBase "ou=servers,dc=fabrikam,dc=com" -SearchScope Subtree | sort-object name 
# Creates an array of obects called "lanObj" that has a custom Name and Servers property 
$lanIDs = "Bill","Ted","Abe","Sam" 
$lanObj = @() 
$count = 0 
foreach ($objTech in $lanIDs){ 
    $objTech = New-Object System.Object 
    $objTech | Add-Member -type NoteProperty -name Name -value $lanIDs[$count] 
    $ObjTech | Add-Member -type NoteProperty -name Servers -value $null 
    $lanObj +$objTech 
    $count += 1} 
# Starts a job for each server which pulls the owner of all explore.exe processes. 
write-host 'Querying' $servers.count 'servers.' 
$JobCount = 0 
$conjobs = 25 # Number of jobs to run concurrently. 
foreach ($s in $servers) { 
    #write-host "Jobcount is $jobcount at start of foreach." 
    start-job -name $s.name {Get-WMIObject Win32_Process -filter 'name="explorer.exe"' -computername $using:s.name | ForEach-Object { $owner = $_.GetOwner(); $owner.User } | Get-Unique} 
    start-sleep -m 100 
    $RunningJobs = get-job -state running 
    $JobCount = @($RunningJobs).count 
    #write-host "Jobcount is $jobcount before loop" 
    if ($JobCount -ge $ConJobs){ 
        do {write-host "Job limit of $conjobs hit.  Sleeping." 
            start-sleep 10 
            $runningjobs = get-job -state running 
            $JobCount = @($RunningJobs).count 
            write-host "Resuming.  Job count is $jobcount of $conjobs"} 
        until ($jobCount -lt $ConJobs) 
write-host "All jobs started." 
# Checks to make sure all jobs are complete. 
$RunningJobs = get-job -state running 
$JobCount = @($RunningJobs).count 
if ($JobCount -ge 1){ 
    write-host "Sleeping until all jobs complete." 
    do {start-sleep 5 
        $runningjobs = get-job -state running 
        $JobCount = @($RunningJobs).count 
        write-host "Running job count is $jobcount."} 
    until ($jobCount -lt 1) 
# Gets the information from each job and puts it into the server property for any user who is logged in. 
$count = 0 
foreach ($s in $servers){ 
    $count += 1 
    write-host 'Receiving and parsing job' $s.name 
    $users = $null 
    $users = receive-job $s.Name 
    if ($users -ne $null){ 
        foreach ($u in $users){ 
            if ($lanIDs -contains $u){ 
                foreach ($l in $lanObj){ 
                    if ($l.name -eq $u){ 
                        $l.servers += ($s.name | out-string) 
write-host "`n" 
write-host "Servers each user is logged onto:" 
write-host "`n" 
# Spits out a nice list for each user and the servers they are logged onto. 
$count = 0 
foreach ($o in $lanobj){ 
    if ($lanobj[$count].servers -ne $null){         
        write-host $lanobj[$count].name 
        write-host $lanobj[$count].servers 
    $count = $count + 1   
# Remove jobs. 
foreach ($s in $servers) {remove-job $s.name} 
write-host "Jobs removed." 
# Time keeping. 
$finishtime = get-date 
$totaltime = $finishtime - $starttime 
write-host "Start time: " $starttime 
write-host "Finish time:" $finishtime 
Write-Host "Total time: " $totaltime