none
Get all members of local admin group for list of servers

    Question

  • I am trying to write a script to list all the members of the local Administrators group on a list of servers.  I can get the data back but am unable to find a way to format the data output as usable for my audit.

     

    here is what I got so far:

     

    $servers= get-content 'c:\input\test.txt'

    $output = 'c:\output\test.csv'

    foreach($server in $servers)

      {

     

            $group =[ADSI]"WinNT://$server/Administrators" 

            $members = @($group.psbase.Invoke("Members"))

            $results = $members | foreach {$_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null) } 

     

        }

     

    $results >> $output

    What I really need though is a way to add the servername in a column next to the users (at least) to be able to know which users belong to the listed server. 

    i.e. I would like to be able to just add:

     $Results += New-Object PSObject -Property $share

    }

    $Results | Export-Csv $Output -NoTypeInformation

    but the script errors with this:

    New-Object : Cannot convert 'System.Object[]' to the type 'System.Collections.Hashtable' required by parameter 'Property'. Specified method is not supported.

    At line:11 char:41

    + $object += New-Object PSObject -Property <<<<  $results

        + CategoryInfo          : InvalidArgument: (:) [New-Object], ParameterBindingException

        + FullyQualifiedErrorId : CannotConvertArgument,Microsoft.PowerShell.Commands.NewObjectCommand

     

     


    Thank you, TJ N. Hansen “He who knows nothing is closer to the truth than he whose mind is filled with falsehoods and errors” Thomas Jefferson
    Wednesday, August 17, 2011 10:01 PM

Answers

  • Or if you would like each member separated out, you can do it like this.  It allows you to sort by user in the CSV and see which machines they are an admin on.

     

    $servers= get-content 'c:\input\test.txt'
    $output = 'c:\output\test.csv' 
    $results = @()
    
    foreach($server in $servers)
    {
    $admins = @()
    $group =[ADSI]"WinNT://$server/Administrators" $members = @($group.psbase.Invoke("Members")) $members | foreach { $obj = new-object psobject -Property @{ Server = $Server Admin = $_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null) } $admins += $obj } $results += $admins } $results| Export-csv $Output -NoTypeInformation


     


    If you found this post helpful, please give it a "Helpful" vote. If it answered your question, remember to mark it as an "Answer".

    Rich Prescott | MCITP, MCTS, MCP

    Blog | Twitter: @Arposh | Powershell Client System Administration tool
    Wednesday, August 17, 2011 10:44 PM

All replies

  • Separate char ";" - User1;User3

     

    $servers= get-content 'c:\input\test.txt'
    $output = 'c:\output\test.csv'
    
    $results = @()
    
    foreach($server in $servers)
    {
     $group =[ADSI]"WinNT://$server/Administrators" 
     $members = $group.Members() | foreach {$_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null) } 
     $results += New-Object PsObject -Property @{
      Server = $server
      Members = $members -join ";"
      }
    }
    
    $results | Export-Csv $Output -NoTypeInformation
    



    Wednesday, August 17, 2011 10:12 PM
  • Or if you would like each member separated out, you can do it like this.  It allows you to sort by user in the CSV and see which machines they are an admin on.

     

    $servers= get-content 'c:\input\test.txt'
    $output = 'c:\output\test.csv' 
    $results = @()
    
    foreach($server in $servers)
    {
    $admins = @()
    $group =[ADSI]"WinNT://$server/Administrators" $members = @($group.psbase.Invoke("Members")) $members | foreach { $obj = new-object psobject -Property @{ Server = $Server Admin = $_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null) } $admins += $obj } $results += $admins } $results| Export-csv $Output -NoTypeInformation


     


    If you found this post helpful, please give it a "Helpful" vote. If it answered your question, remember to mark it as an "Answer".

    Rich Prescott | MCITP, MCTS, MCP

    Blog | Twitter: @Arposh | Powershell Client System Administration tool
    Wednesday, August 17, 2011 10:44 PM
  • I have the following script..take a look.  You can ignore the email part..

    http://portal.sivarajan.com/2011/04/list-local-administrator-group-members.html

    $GFile = New-Item -type file -force "C:\Scripts\SGroupMemberDetails.csv"
    
    Import-CSV "C:\Scripts\Servers.csv" | ForEach-Object {
    $SName = $_.ServerName
    "Server Name -  $SName" | Out-File $GFile -encoding ASCII -append
    $group = [ADSI]("WinNT://$SName/Administrators,group"$GMembers = $group.psbase.invoke("Members")
    $GMembers | ForEach-Object {$_.GetType().InvokeMember("Name",'GetProperty', $null, $_, $null) | Out-File $GFile -encoding ASCII -append
    }
    


    Santhosh Sivarajan | MCTS, MCSE (W2K3/W2K/NT4), MCSA (W2K3/W2K/MSG), CCNA, Network+ Houston, TX

    Blogs - http://blogs.sivarajan.com/
    Articles - http://www.sivarajan.com/publications.html
    Twitter: @santhosh_sivara - http://twitter.com/santhosh_sivara
    This posting is provided AS IS with no warranties,and confers no rights.
    Thursday, August 18, 2011 2:07 AM
  • Arposh,

     

    i like your solution but the output is having an error and rewriting the servers group membership to the csv with every iteration of the script i.e. 

     

    testserver1 Admin

    testserver1 Admin

    testserver2 Admin

    testserver1 Admin

    testserver2 Admin

    testserver3 Admin

    testserver1 Admin

    testserver2 Admin

    testserver3 Admin

    testserver4 Admin

    and so on...

     

    Any way to fix this in the script?  It looks like the dual $admins = @() and $results = @() is causing the object to input the data this way?


    Thank you, TJ N. Hansen “He who knows nothing is closer to the truth than he whose mind is filled with falsehoods and errors” Thomas Jefferson
    Thursday, August 18, 2011 4:21 PM
  • I updated the code to fix that issue.  $admins = @() was moved to the correct location.

    If you found this post helpful, please give it a "Helpful" vote. If it answered your question, remember to mark it as an "Answer".

    Rich Prescott | MCITP, MCTS, MCP

    Blog | Twitter: @Arposh | Powershell Client System Administration tool
    Thursday, August 18, 2011 5:00 PM
  • Is there a way for the output csv to have a seperator line between the servers that list in the csv?

    Or for just the server names to list once? 


    Thursday, August 18, 2011 8:24 PM
  • Heckter,

    Use Kazun's script to do that.


    If you found this post helpful, please give it a "Helpful" vote. If it answered your question, remember to mark it as an "Answer".

    Rich Prescott | MCITP, MCTS, MCP

    Blog | Twitter: @Arposh | Powershell Client System Administration tool
    Monday, August 22, 2011 3:31 PM
  • I'll use that, thank you all :)
    Monday, August 22, 2011 4:13 PM
  • Rich

    I get the error below when I run my script. All I did was edit it to point to my folder locations and to my list of servers.  Any ideas?

    At line:16 char:15
    + {$admins = @()$group =[ADSI]"WinNT://$server/Administrators"
    +               ~~~~~~
    Unexpected token '$group' in expression or statement.
        + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
        + FullyQualifiedErrorId : UnexpectedToken
     

    Wednesday, August 28, 2013 4:30 PM
  • There's supposed to be a line break between "$admins = @()" and "$group = ...".  You've somehow put both statements on the same line, which won't work (unless they're separated by a semicolon, but that's generally bad coding practice).
    Wednesday, August 28, 2013 4:46 PM
  • you saved my whole day... great work.
    Wednesday, March 05, 2014 10:30 AM
  • How do  i also pull the group domain prefix i nthe results....

    basically the result is only listing the group name as opposed to the domain\group name

    Please help

    Thanks

    Thursday, June 23, 2016 7:50 PM
  • How do  i also pull the group domain prefix i nthe results....

    basically the result is only listing the group name as opposed to the domain\group name

    Please help

    Thanks

    Thursday, June 23, 2016 7:50 PM
  • I know this was last year, but I figured this might help someone else if they're interested or in need. I took Rich's code and made some modifications. The script below does quite a bit (including pulling the domain information and using it in the file name which incidentally could also be used to drop into the results as well, you would just back reference and select $domain when outputting results.) I know it's not exactly what you were looking for, but it is something. It can be scheduled as a job, but you would want to comment out the "Write-Host" stuff. I use it when I run it manually so I can see it move through the servers. Output is broken into successes and failures so I know which ones it couldn't connect to.

    # Adjust Path variable as needed. Use UNC or local drive paths
    $Path = "\\Servername\sharedfolderhere"
    
    #The next line requires that the AD module be installed on the system where it is running from.
    Import-module ActiveDirectory
    
    # Set variables needed later
    $DTG = get-date -format ddMMyyyy
    $DTG2 = get-date -format ddMMyyyy-mmss
    
    # Uses .net method to pull domain info. There are obviously several ways to do this...
    $domain = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
    $targetFile = "LocalServerAdminsExport.$domain.html"
    
    # Test target path to ensure it is available and if not, set to local.
    if (Test-Path $Path) {
        $HTMLPath = "$Path\$targetFile"
    } else {
        $Path = "."
        $HTMLPath = ".\$targetFile"
    }
    
    # Set HTML Styles. Modify here to change the look and feel of the report.
    $filehead = "<title>W -- $DTG</title>"
    $filehead = $filehead + "<style>"
    $filehead = $filehead + "BODY{background-color:LightGreen;}"
    $filehead = $filehead + "TABLE{border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse}"
    $filehead = $filehead + "TH{border-width: 1px;padding: 10px;border-style: solid;border-color: black;background-color: CadetBlue;}"
    $filehead = $filehead + "TD{border-width: 1px;padding: 10px;border-style: solid;border-color: black;background-color: lavender;}"
    $filehead = $filehead + "</style>"
    
    # Set the variable for our date calculation
    $d = [datetime]::Today.AddDays(-60)
    
    # Setup hash table and populate 
    $getServer = @{}
    $getServer = Get-ADComputer -filter {(OperatingSystem -like "*Server*") -and (enabled -eq "true") -and (OperatingSystem -like "*Windows*") -and (LastLogonTimeStamp -ge $d)} -Properties * | Select Name,CanonicalName,DNSHostName,OperatingSystem
    
    # Setup arrays for populating later.
    $SuccessHosts = @()
    $FailedHosts = @()
    
    #Code Block, fore each, let's do something...
    foreach ($Srv in $getServer) {
        
        $Hostname = $Srv.Name
        $rpc = $null
        $Success = $null
        $Failed = $null
        
        #Test the WMI connection before trying to collect stats
        try {
            Write-host "Testing RPC for "$Hostname
            $WMI_conn = [wmi] ''
            $WMI_conn.psbase.options.timeout = "0:0:3"  #timeout = 3 seconds
            $WMI_conn.path = "\\$Hostname\root\cimv2:Win32_ComputerSystem.Name='$Hostname'"
            $WMI_conn | Select None | Out-Null
            $rpc = $true
        }
        catch { 
            #WMI connection failed
            Write-host "RPC FAILED for "$Hostname $Error[0]
            
            $rpc = $false
        }
            
    	# Next, Execute commands
    	if($rpc) {
            Write-host "Getting Local Administrators for "$Hostname
            
    	$admins = @()
    	$results = @()
    
        # For each server result found, get local administrators and populate 
        $group =[ADSI]"WinNT://$Hostname/Administrators" 
    	$members = @($group.psbase.Invoke("Members"))
    	$members | foreach {
     		$obj = new-object psobject -Property @{
     		Server = $Hostname
     		Admin = $_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null)
     		}
     		$admins += $obj
     		} 
    	$results += $admins
    	}
    
        else {
            $Failed = New-Object System.Object
            $Failed | Add-Member -type NoteProperty -Name Server -Value $Srv.DNSHostName
            $Failed | Add-Member -type NoteProperty -Name Description -Value "RPC unavailable"
        }    
        
        # Populate arrays.
        $SuccessHosts += $results
        $FailedHosts += $Failed
    }
    
    # Sort results
    $SuccessLines = $SuccessHosts | Sort-Object Server
    $FailedLines = $FailedHosts | Sort-Object Server 
    
    # Convert responses to html in fragments to merge into one report later.
    $HTMLsuccess = $SuccessLines | ConvertTo-HTML -Fragment
    $HTMLfailed = $FailedLines | ConvertTo-HTML -Fragment
    
    #Rename and archive any old reports to be safe.
    Rename-Item "$Path\$targetFile" "$Path\$TargetFile-$DTG2.html" -force -ea SilentlyContinue
    move-item "$Path\$Targetfile-$DTG2.html" "$Path\Archive\$Targetfile-$DTG2.html" -Force -ea SilentlyContinue
    
    # Pass query results to the ConvertTo-HTML method and then output.
    ConvertTo-HTML -HEAD $fileHead -Body "<H2>Shows all local server Administrators for $domain Windows servers as of $DTG.</H2> $HTMLsuccess <P></P> $HTMLfailed" | Out-File $HTMLPath

    
    Tuesday, February 21, 2017 12:24 PM
  • Also, I use the HTML for outputting as a report for management types who prefer it that way. Since it is in table format, I can just drop the HTML file in an open Excel window and modify there directly and save as a spreadsheet easily...
    Tuesday, February 21, 2017 12:26 PM
  • Last update. I was able to remove Domain Controllers from my filtered list of servers using an additional filter of, -and (primaryGroupID -notlike "516")...
    Wednesday, March 01, 2017 6:11 PM
  • When I run the scripts in this thread, I only get Local Administrators that are Groups. If an individual User account is a Local Administrator, they don't appear. How would I modify these scripts to get both Groups and User accounts that are in the Local Administrators group?
    Thursday, March 16, 2017 4:21 PM
  • Are all these scripts powershell?

    I need a batch job that will list all accounts in the administrators group of many servers

    Server Name     Account Name

    Wednesday, April 12, 2017 7:23 PM
  • Thanks.... after googling almost 2 hours, I found your script which did the magic in no time - literally. Bless you !
    Friday, May 05, 2017 4:29 PM