简体   繁体   中英

Getting nested members of AD security group

I'm trying to get members of AD security group and list their account name, first name, last name and last logon date.

This is the script I have currently

# Function get-NestedMembers
# List the members of a group including all nested members of subgroups

function get-NestedMembers ($group){
  if ($group.objectclass[1] -eq 'group') {
        write-verbose "Group $($group.cn)"
    $Group.member |% {
      $de = new-object directoryservices.directoryentry("LDAP://$_")
       if ($de.objectclass[1] -eq 'group') {
        get-NestedMembers $de
      }
      Else {
        $de.sAMAccountName
      }
    }
  }
  Else {
    Throw "$group is not a group"
  }
}

# get-NestedMembers usage examples :

# get a group

$group = new-object directoryservices.directoryentry("LDAP://CN="group name",OU=folder,OU=Citrix,OU=Applications,DC=xx,DC=xx,DC=xx,DC=com")

# Get all nested members

get-NestedMembers $group

How do I modify it to get also First name, Last name and last logon date? Currently, it only lists account name (sAMAccountName).

Thanks a lot for any help.

Edit

This script works for me. Just edit line 26 with LDAP address of the group you want to scan.

# Function get-NestedMembers
# List the members of a group including all nested members of subgroups

Import-Module ActiveDirectory

function get-NestedMembers ($group){
  if ($group.objectclass[1] -eq 'group') {
        write-verbose "Group $($group.cn)"
    $Group.member |% {
      $de = new-object directoryservices.directoryentry("LDAP://$_")
      if ($de.objectclass[1] -eq 'group') {
        get-NestedMembers $de
      }
      Else {
        $de
      }
    }
  }
  Else {
    Throw "$group is not a group"
  }
}

# get a group

$group = new-object directoryservices.directoryentry("LDAP://CN=GroupName,OU=Groups,OU=File Servers,OU=Applications,DC=contoso,DC=com")

# Get all nested members

get-NestedMembers $group|FT @{l="First Name";e={$_.givenName}},@{l="Last Name";e={$_.sn}},@{l="Last Logon";e={[datetime]::FromFileTime($_.ConvertLargeIntegerToInt64($_.lastLogonTimestamp[0]))}},sAMAccountName

Output looks like this:

First Name           Last Name            Last Logon                sAMAccountName
----------           ---------            ----------                --------------
Name                 Surname              10.11.2014 14:58:02       {accname}
Name                 Surname              17.11.2014 19:11:15       {accname}
Name                 Surname              07.11.2014 15:38:57       {accname}
Name                 Surname              14.11.2014 03:50:03       {accname}
Name                 Surname              16.11.2014 21:30:15       {accname}

first name and last name are trivial. You seem to get the object already, so you can just add

$de.givenName ## to get first name
$de.sn ## to get last name
[datetime]::FromFileTime($de.lastlogon) ## however, this may not be exact. There are abundance of info on why.

Update: Responding to your questions... Printing them on the same line is easy simply put them in quotes

"$($de.givenName) $($de.sn) $LastLogon"

If you noticed, the last one does not have $(), which means "evaluate" within a string. If you simply put the variable name within doub-quotes "", it will be expanded. But when you want to do more, you want to use that $(put something here for execution) method.

Now the issue you are having is that LastLogon attribute may not have a value, so when reading it, you have to make sure there is a value. You could for example do something like this

if ($de.lastlogon) {
  $LastLogon=[datetime]::FromFileTime($de.lastlogon)
}

By the way, lastlogon attribute..is not really ideal. Take a look at this post: https://blogs.technet.com/b/askds/archive/2009/04/15/the-lastlogontimestamp-attribute-what-it-was-designed-for-and-how-it-works.aspx

Hope this helps.

See how this strikes your fancy...

function get-NestedMembers ($group){
  if ($group.objectclass[1] -eq 'group') {
        write-verbose "Group $($group.cn)"
    $Group.member |% {
      $de = new-object directoryservices.directoryentry("LDAP://$_")
       if ($de.objectclass[1] -eq 'group') {
        "get-NestedMembers $de"
      }
      Else {
        $de
      }
    }
  }
  Else {
    Throw "$group is not a group"
  }
}

# get-NestedMembers usage examples :

# get a group

$group = new-object directoryservices.directoryentry("LDAP://CN="group name",OU=folder,OU=Citrix,OU=Applications,DC=xx,DC=xx,DC=xx,DC=com")

# Get all nested members

get-NestedMembers $group|FT @{l="First Name";e={$_.givenName}},@{l="Last Name";e={$_.sn}},@{l="Last Logon";e={[datetime]::FromFileTime($_.ConvertLargeIntegerToInt64($_.lastLogonTimestamp[0]))}},sAMAccountName

The formatting magic is the FT in the last line there along with some impromptu hash tables to make it easier to read. To get the LastLogonTimestamp powershell makes you jump through hoops. The object type that you're using stores it as a LargeInteger that it just reports back as a System.__ComObject or some such. Fortunately the object also contains a way to convert that to a usable value which I call in that last line.

To be able to access that value alone you need to really convert it to a Int64 type, and from that extract the DateTime value, which is why we need:

[datetime]::FromFileTime($_.ConvertLargeIntegerToInt64($_.lastLogonTimestamp[0]))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM