'find User in a list of servers PowerShell

I have a list of servers where I have to find a specific user 'adtuser', and if it is part of the admin group in each server, and output a text file.

For the moment I have this script and it partially works.
I have the desired output, but some server are missing (they are ok if you check individually) and the script require a lot of time.

Thanks in advance

Get-Content C:\servers.txt | ForEach-Object {
    if (-not (Test-Connection -ComputerName $_ -Count 1 -Quiet)) {
        Write-Warning "Server '$_' is Unreachable hence Could not fetch data"
        return
    }
    
    $computer = $_
    ([adsi]"WinNT://$_").Children.ForEach{ 
        if($_.SchemaClassName -ne 'user' -and $_.Name.Value -ne 'ADTuser') {
            return
        }
        
        $groups = $_.Groups().ForEach([adsi]).Name
        
        [pscustomobject]@{
            Computername = $computer
            UserName     = $_.Name.Value
            Memberof     = $groups -join ';'
            Status       = $groups -contains 'Administrators'
        }
    }
} | Out-File -FilePath C:\users.txt


Solution 1:[1]

Be advised that test-netconnection requires powerhshell 2.0 or better. Method .ForEach requires Powershell 4.0 or better.

As @Santiago mentioned — I’m using Test-Connection with -port 3389 to test against the Windows RDP port. OP was originally just testing for ICMP connectivity which is a poor test because of common firewall rules.

You could test any know Windows port but RDP is usually pretty safe to assume is open. NMAP (or you network admin …grin) could probably give you the best guidance.

#!/usr/bin/env powershell
Get-Content -Path $env:HOMEDRIVE/servers.txt | ForEach-Object {
if (-not (Test-Connection -ComputerName $_ -Count 1 -Quiet)) {
    Write-Warning -Message ("Server '{0}' is Unreachable hence Could not fetch data" -f $_)
    return
}

$computer = $_
([adsi]('WinNT://{0}' -f $_)).Children.ForEach{ 
    if($_.SchemaClassName -ne 'user' -and $_.Name.Value -ne 'ADTuser') {
        return
    }
    
$groups = $_.Groups().ForEach([adsi]).Name
    
[pscustomobject]@{
        Computername = $computer
        UserName     = $_.Name.Value
        Memberof     = $groups -join ';'
        Status       = $groups -contains 'Administrators'
  }
 }
} | Out-File -FilePath $env:HOMEDRIVE/users.txt

Solution 2:[2]

Since you asked, if your servers can all use PowerShell version 5.1 or higher, you can make use of the Get-Local* cmdlets.

From your question, you are specifically looking for a certain user ADTuser

$userToCheck = 'ADTuser'
$servers     = Get-Content -Path 'C:\servers.txt'
$cred        = Get-Credential -Message 'Please enter your admin credentials'

# loop through the list of servers and collect the output objects
$result = foreach ($computer in $servers) {
    if (-not (Test-Connection -ComputerName $computer -Count 1 -Quiet)) {
        Write-Warning -Message "Server '$computer' is Unreachable hence Could not fetch data"
        # output a failed object
        '' | Select-Object @{Name = 'ComputerName'; Expression = {$computer}}, UserName,MemberOf, 
                           @{Name = 'Status'; Expression = {'Unreachable'}}
        # skip processing this server and proceed with the next one
        continue
    }
    # here we probe the server for the existance of user $userToCheck
    $out = Invoke-Command -ComputerName $computer -Credential $cred -ScriptBlock {
        $user = Get-LocalUser -Name $using:userToCheck -ErrorAction SilentlyContinue
        if ($user) {
            # get the names of all local groups the user is member of
            $userGroups = (Get-LocalGroup | Where-Object { ($_ | Get-LocalGroupMember).SID -contains $user.SID }).Name
            [PsCustomObject]@{
                Computername = $env:COMPUTERNAME
                UserName     = $user.Name
                MemberOf     = $userGroups -join '; '
                Status       = $userGroups -contains 'Administrators'
            }
        }
        else {
            [PsCustomObject]@{
                Computername = $env:COMPUTERNAME
                UserName     = $using:userToCheck
                MemberOf     = $null
                Status       = "User does not exist"
            }                
        }
    }
    # output the object but remove extra properties PowerShell added
    $out | Select-Object * -ExcludeProperty PS*, RunspaceId
}

# show in the console window
$result | Format-Table -AutoSize

# you can now use Export-Csv to output the results in a structured file you can open with Excel
$result | Export-Csv -Path 'C:\users.csv' -UseCulture -NoTypeInformation

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Theo