Script to gather local group members & include props - help please

Hey All

I am trying to use a script I found online as I’ve tried writing my own and I’m not having luck with either. I need to provide a report of all “Local Administrators” on servers. The servers are 2003/2008/2008r2/2012. I am using Powershell 4.0 on a system that has access to all but a few of the systems, but I don’t know which systems I can not access “yet”. I have systems in a couple domains and also stand-alone servers.

The only easy part about this is that I have an account which is a local administrator on all of these servers, and the creds are the same, and that’s been helpful as I have run several scripts from the jump box using that account and they typically work fine.

I need to get all Local Administrators - both local and domain accounts. I need to include the properties below, and I know some are specific to only domain accounts.
Display Name
Description (if any…)
Organization
Manager
Last login date - (this is only available for local accounts from the SAM DB)
Computer being queried should be listed in a column so that every entry in the csv file has that as a listed value, as I’ll have to be able to filter the report.
Domain - I need to specify what domain the account found as a local admin belongs to, so either in the format of domain\username or another method. I then have to specify the domain the computer belongs to if any.

The script I found is from the TechNet Gallery by the ONESCRIPT Team and it does a fair amount of this, but I can’t find out what systems are failing to be queried, but in the shell window I see the errors “Access Denied”, so I need to find out how to put in some sort of catch error code?

Then the usernames come back as login name in 1 column, then display in another, then the writer added another column that is titled “column”, but that is showing as the servername\username - regardless of whether the account is an AD account or local account. Then in the domain column, the servername is listed which is good, but I need to query for the domain the server is a member of as well.

Can anyone help me with the error checking and adjusting/fixing the code to get the details I need? I’ve tried modifying the queries for the domain as an example, and I don’t know why it’s not coming back as the domain the system belongs to. The “caption column” also doesn’t make sense to me.

For the errors, I am new to the “Try/Catch” code and I am not sure how to catch the errors if access is denied or the server is down/not reachable. I need to grab an error, whether it is only simply “access denied” or “failed”, so I know which servers I have to go after manually.

{content}

#requires -Version 2.0

<#
.SYNOPSIS
This script can be list all of local user account.
.DESCRIPTION
This script can be list all of local user account.
.PARAMETER
Specifies the local user account you want to search.
.PARAMETER <ComputerName
Specifies the computers on which the command runs. The default is the local computer.
.PARAMETER
Specifies a user account that has permission to perform this action.
.EXAMPLE
C:\PS> C:\Script\GetLocalAccount.ps1

	This example shows how to list all of local users on local computer.	
.EXAMPLE
    C:\PS&gt; C:\Script\GetLocalAccount.ps1 | Export-Csv -Path "D:\LocalUserAccountInfo.csv" -NoTypeInformation
	
	This example will export report to csv file. If you attach the  parameter with command, it will omit the type information 
	from the CSV file. By default, the first line of the CSV file contains "#TYPE " followed by the fully-qualified name of the object type.
.EXAMPLE
    C:\PS&gt; C:\Script\GetLocalAccount.ps1 -AccountName "Administrator","Guest"
	
	This example shows how to list local Administrator and Guest account information on local computer.
.EXAMPLE
    C:\PS&gt; $Cre=Get-Credential
	C:\PS&gt; C:\Script\GetLocalAccount.ps1 -Credential $Cre -Computername "WINSERVER" 
	
	This example lists all of local user accounts on the WINSERVER remote computer.

#>

Param
(
[Parameter(Position=0,Mandatory=$false)]
[ValidateNotNullorEmpty()]
[Alias(‘cn’)][String]$ComputerName=$Env:COMPUTERNAME,
[Parameter(Position=1,Mandatory=$false)]
[Alias(‘un’)][String]$AccountName,
[Parameter(Position=2,Mandatory=$false)]
[Alias(‘cred’)][System.Management.Automation.PsCredential]$Credential
)

$Obj = @()

Foreach($Computer in $ComputerName)
{
If($Credential)
{
$AllLocalAccounts = Get-WmiObject -Class Win32_UserAccount -Namespace “root\cimv2” `
-Filter “LocalAccount=‘$True’” -ComputerName $Computer -Credential $Credential -ErrorAction Stop
}
else
{
$AllLocalAccounts = Get-WmiObject -Class Win32_UserAccount -Namespace “root\cimv2” `
-Filter “LocalAccount=‘$True’” -ComputerName $Computer -ErrorAction Stop
}

Foreach($LocalAccount in $AllLocalAccounts)
{
	$Object = New-Object -TypeName PSObject
	
	$Object|Add-Member -MemberType NoteProperty -Name "Name" -Value $LocalAccount.Name
	$Object|Add-Member -MemberType NoteProperty -Name "Full Name" -Value $LocalAccount.FullName
	$Object|Add-Member -MemberType NoteProperty -Name "Caption" -Value $LocalAccount.Caption
  	$Object|Add-Member -MemberType NoteProperty -Name "Disabled" -Value $LocalAccount.Disabled
  	$Object|Add-Member -MemberType NoteProperty -Name "Status" -Value $LocalAccount.Status
  	$Object|Add-Member -MemberType NoteProperty -Name "LockOut" -Value $LocalAccount.LockOut
	$Object|Add-Member -MemberType NoteProperty -Name "Password Changeable" -Value $LocalAccount.PasswordChangeable
	$Object|Add-Member -MemberType NoteProperty -Name "Password Expires" -Value $LocalAccount.PasswordExpires
	$Object|Add-Member -MemberType NoteProperty -Name "Password Required" -Value $LocalAccount.PasswordRequired
	$Object|Add-Member -MemberType NoteProperty -Name "SID" -Value $LocalAccount.SID
	$Object|Add-Member -MemberType NoteProperty -Name "SID Type" -Value $LocalAccount.SIDType
	$Object|Add-Member -MemberType NoteProperty -Name "Account Type" -Value $LocalAccount.AccountType
	$Object|Add-Member -MemberType NoteProperty -Name "Domain" -Value $LocalAccount.Domain
	$Object|Add-Member -MemberType NoteProperty -Name "Description" -Value $LocalAccount.Description
	
	$Obj+=$Object
}

If($AccountName)
{
	Foreach($Account in $AccountName)
	{
		$Obj|Where-Object{$_.Name -like "$Account"}
	}
}
else
{
	$Obj
}

}

{content}

Hey there Jake,

Can you give this a shot? Let me know what problems, if any, you have. Thanks!

#requires -Version 2.0

<#
.SYNOPSIS
This script can be list all of local user account.
.DESCRIPTION
This script can be list all of local user account.
.PARAMETER
Specifies the local user account you want to search.
.PARAMETER	Specifies the computers on which the command runs. The default is the local computer.
.PARAMETER
Specifies a user account that has permission to perform this action.
.EXAMPLE
C:\PS> C:\Script\GetLocalAccount.ps1

This example shows how to list all of local users on local computer.
.EXAMPLE
C:\PS> C:\Script\GetLocalAccount.ps1 | Export-Csv -Path "D:\LocalUserAccountInfo.csv" -NoTypeInformation

This example will export report to csv file. If you attach the parameter with command, it will omit the type information
from the CSV file. By default, the first line of the CSV file contains "#TYPE " followed by the fully-qualified name of the object type.
.EXAMPLE
C:\PS> C:\Script\GetLocalAccount.ps1 -AccountName "Administrator","Guest"

This example shows how to list local Administrator and Guest account information on local computer.
.EXAMPLE
C:\PS> $Cre=Get-Credential
C:\PS> C:\Script\GetLocalAccount.ps1 -Credential $Cre -Computername "WINSERVER"

This example lists all of local user accounts on the WINSERVER remote computer.
#>
[cmdletbinding[]]

Param[
    [Parameter[Position=0,Mandatory=$false]]
    [ValidateNotNullorEmpty[]]
    [Alias['cn']][String[]]$ComputerName=$Env:COMPUTERNAME,
    [Parameter[Position=1,Mandatory=$false]]
    [Alias['un']][String[]]$AccountName,
    [Parameter[Position=2,Mandatory=$false]]
    [Alias['cred']][System.Management.Automation.PsCredential]$Credential
]#EndParam

$Obj = @[]

Foreach[$Computer in $ComputerName]{
    If[$Credential]{
        
        Try{
        
            $AllLocalAccounts = Get-WmiObject -Class Win32_UserAccount -Namespace "root\cimv2" `
            -Filter "LocalAccount='$True'" -ComputerName $Computer -Credential $Credential -ErrorAction Stop
        
        }#EndTry

        Catch [System.Exception]{ 
        
            $ErrorMsg = $Error[0] | Select-Object * | Format-List -Force
            Write-Output "An error occurred while attemtping to connect to system $Computer.  The error was $ErrorMsg"
        
        }#EndCatch

    }#EndIf

    else{
        Try{

            $AllLocalAccounts = Get-WmiObject -Class Win32_UserAccount -Namespace "root\cimv2" `
            -Filter "LocalAccount='$True'" -ComputerName $Computer -ErrorAction Stop

        }#EndTry

        Catch [System.Exception]{

            $ErrorMsg = $Error[0] | Select-Object * | Format-List -Force
            Write-Output "An error occurred while attemtping to connect to system $Computer.  The error was $ErrorMsg"

        }#EndCatch

    }#EndElse

    Foreach[$LocalAccount in $AllLocalAccounts]{
    $Object = New-Object -TypeName PSObject

    $Object|Add-Member -MemberType NoteProperty -Name "Name" -Value $LocalAccount.Name
    $Object|Add-Member -MemberType NoteProperty -Name "Full Name" -Value $LocalAccount.FullName
    $Object|Add-Member -MemberType NoteProperty -Name "Caption" -Value $LocalAccount.Caption
    $Object|Add-Member -MemberType NoteProperty -Name "Disabled" -Value $LocalAccount.Disabled
    $Object|Add-Member -MemberType NoteProperty -Name "Status" -Value $LocalAccount.Status
    $Object|Add-Member -MemberType NoteProperty -Name "LockOut" -Value $LocalAccount.LockOut
    $Object|Add-Member -MemberType NoteProperty -Name "Password Changeable" -Value $LocalAccount.PasswordChangeable
    $Object|Add-Member -MemberType NoteProperty -Name "Password Expires" -Value $LocalAccount.PasswordExpires
    $Object|Add-Member -MemberType NoteProperty -Name "Password Required" -Value $LocalAccount.PasswordRequired
    $Object|Add-Member -MemberType NoteProperty -Name "SID" -Value $LocalAccount.SID
    $Object|Add-Member -MemberType NoteProperty -Name "SID Type" -Value $LocalAccount.SIDType
    $Object|Add-Member -MemberType NoteProperty -Name "Account Type" -Value $LocalAccount.AccountType
    $Object|Add-Member -MemberType NoteProperty -Name "Domain" -Value $LocalAccount.Domain
    $Object|Add-Member -MemberType NoteProperty -Name "Description" -Value $LocalAccount.Description

    $Obj+=$Object
    
    }#EndForEach

    If[$AccountName]{

        Foreach[$Account in $AccountName]{

            $Obj|Where-Object{$_.Name -like "$Account"}

        }#EndForEach

    }#EndIf
        
    else{

        $Obj
    
    }#EndElse
}#EndForEach

You are trying to get the members of the local administrators group, the script you posted is just getting the local groups, not the members. You want a lot of information, but it should be tackled in chunks. Try this on some test computers and see if you can get the start of what you want:

#List of computers
$computers = ".", "Computer123"

#Define the credentials, this would prompt for the computers
$cred1 = Get-Credential -UserName "Administrator"
$cred2 = Get-Credential -UserName "domain\adminDude"
#Put the credentials in an array so we can loop through them
$credentials = @($cred1,$cred2)

#Loop through the computers and put results in $results variable
$results  = foreach ($computer in $computers) {
#Loop through each credential set and try to pull the data
foreach ($credential in $credentials) {
        $splat = @{
            Class = "win32_groupuser"
            Namespace = "root\cimV2"
            ComputerName = $computer
            Credential = $Credential
        }
        
        try {
            #Try to get the members of Administrators with the current loop creds
            Get-WmiObject @splat | 
            Where-Object { $_.GroupComponent -match 'administrators' } |
            ForEach-Object {
                [wmi]$_.PartComponent | Select Name,
                                               Domain,
                                               LocalAccount,
                                               Description,
                                               PSComputerName,
                                               @{Label="Cred";Expression={$cred.UserName}} 
            }
        } #end try
        catch {
            #If an error occurs, we still want to return the failure as a matching object.
            #You are going to get an error for each computer unless both credentails work
            #on the system.  
            New-Object -TypeName PSObject -Property @{ Name = "ERROR";
                                                       Domain = $null;
                                                       LocalAccount = $null;
                                                       Description = $_.Exception.Message;
                                                       PSComputerName = $computer;
                                                       Cred = $cred.UserName }
        } #end catch
    } #foreach credential

} #foreach computer

$results