Hello, I’m trying to write a function that I can pass it a local user name and it returns all the groups it is associated with.
I found the below snippet and thought it was working well, but when I hit a server connected to the domain it takes forever…if I just run
$computer.psbase.children | where { $_.psbase.schemaClassName -eq ‘group’ }
It stops on the last local group 'winRMRemoteWMIUsers__ and doesnt move…I’m not sure why it is doing this…
Is there a way to just keep the search locally?
`
function groupsoflocal($usr)
{
$user = $usr
$server="."
$computer = [ADSI]"WinNT://$server,computer"
$computer.psbase.children | where { $_.psbase.schemaClassName -eq 'group' } | foreach {
$groupname = $_.name
$group =[ADSI]$_.psbase.Path
$group.psbase.Invoke("Members") |
foreach {
$member = $_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null)
if ($member -eq $user)
{
$name += @($Groupname)
}
}
}
$name
}
`
Not sure about ADSI, but you can do it with WMI
$computer = "workstation1"
$user = "user"
Get-CimInstance -ComputerName $computer -Filter "localaccount = true and name = '$user'" -ClassName win32_useraccount | Get-CimAssociatedInstance -Association win32_groupuser
Above code adapted from: http://blogs.technet.com/b/heyscriptingguy/archive/2012/12/16/weekend-scripter-use-powershell-and-wmi-associations-to-find-user-group-membership.aspx
Thanks for the reply, but sadly this I can only use Powershell 2.0…
If there is no good solution for this, can someone explain why it takes an hour to go through the function using ADSI for local groups?
Well I got it to work a lot faster using the method below, and instead of finding a user and using a function to get it’s groups i’m just using ‘net localgroup…’ to get it. Takes seconds vs 30min-1hour.
I’m not really sure why it takes so long to do it the first way, but I guess I’m past it now. Thanks again Curtis for your help and guidance!
#Allowed Local groups
$localgroups =@("Administrators", "backup operators","certificate service DCOM access", "Distributed COM users", "Event Log Readers", "Network Configuration Operators", "Performance Log Users", "Performance Monitor Users", "Print Operators", "Power Users")
#groups that exist on the server
$actualgroups = net localgroup | ?{ $_ -match "^\*.*" } | %{ $_.SubString(1) };
#pulls all users in each group that will be success if found
foreach ( $localgroup in $localgroups )
{
if($actualgroups -eq $localgroup)
{
$Group= [ADSI]"WinNT://$env:computername/$LocalGroup,group"
$Members = @($Group.psbase.Invoke("Members")) | %{$_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null)}
$localgood += $members
}
}
The reason it takes so long using ADSI is because when you run the command
$computer.psbase.children | where { $_.psbase.schemaClassName -eq ‘group’ }
against a domain joined machine, it does not return only the groups on the local machine, but also all of the groups in the domain, which it has to query a domain controller to retrieve. So time is greatly expanded by multiple factors. 1) Network Latency, 2) Increased volume of groups to process, 3) speed of Domain Controller to process the request. That’s why the WMI method works well if it can be used. In the WMI query I am specifying that I want it to only look at “localaccounts”. As such we do not pull down all the domain groups and expand the processing time. I just don’t know if that can be done with ADSI.
Glad you found a working solution.