1

I can use some help structing/nesting the below powershell code to get the desired outcome.

When I use the command:

Get-ADGroupMember -Identity $groupname | 
    Get-ADUser -Properties * -Erroraction Ignore | 
        select @{N='UserName';E={$_.UserPrincipalName}} | 
            Export-csv $filename -NoTypeInformation

It works as expected and only selects people from the AD group $groupname, but when I modify the code and try to filter for only NEW accounts based on when the account was created, it's now including user accounts that are NOT in that group

Get-ADGroupMember -Identity $groupname | 
    Get-ADUser -Filter { whenCreated -ge $when } -Properties * -Erroraction Ignore | 
        select @{N = 'UserName'; E = { $_.UserPrincipalName } } | 
            Export-csv $filename -NoTypeInformation

I'm not sure why it is now including all new user accounts in our AD, even some outside of the group $groupname

Olaf
  • 4,690
  • 2
  • 15
  • 23
Justin V
  • 27
  • 5

1 Answers1

2

You cannot use -Filter while piping in objects. If you are piping in objects Get-ADUser will assume you want to get them. This boils down to a parameter binding error, however, since you've set the -ErrorAction Ignore you aren't getting the error feedback that would have said so.

You should have any problem getting AD Users that we know exist by virtue of their group membership. So, I'd question if you really need to ignore errors. That said, Removing -ErrorAction Ignore will not solve the parameter binding issue. For that, I'm afraid you'll have to resort to post-filtering with a Where{} clause. For example:

$When = (Get-Date "12/31/2020").ToUniversalTime()

Get-ADGroupMember -Identity $groupname | 
Get-ADUser -Properties WhenCreated | 
Where-Object{ $_.WhenCreated -ge $when }
Select-Object @{Name = 'UserName'; Expression = { $_.UserPrincipalName } } | 
Export-csv $filename -NoTypeInformation

Note: The property is stored in UTC, so by converting the local time we're interested in we should get the correct results.

Note: You do not need to get all the properties. UserPrincipalName is included in the default set. To post-filter you will have to add WhenCreated to the results.

An Aside: Try not to use script blocks for the -Filter argument. If you look at Get-ADUser help documentation you'll find the parameter is actually string typed. As such specifying a script block requires recasting under the hood and can lead to issues. so, if you were to use the -Filter parameter in this project or elsewhere just use a regular string, like: -Filter "Name -like '*steve*'"

Another Aside: A [DateTime] such as returned by Get-Date cannot be directly used in a -Filter argument. This likely has to do with If, when, and how cmdlet is manipulating the WhenCreated. The Value of the WhenCreated LDAP attribute is stored more like "20200820040000.Z", so you can adjust to use as the -Filter or -LDAPFilter argument respectively like below:

$when = (Get-Date '8/20/20' ).ToUniversaltime().ToString('yyyMMddHHmmss.Z')

Get-ADUser -Filter "WhenCreated -ge '$when'"

Or with -LDAPFilter

Get-ADUser -LDAPFilter "(whencreated>=$when)"

I'll follow-up with documentation on the filter-able properties if I can find it.

Update:

Based on comments from @SantiagoSquarzon, you may not want to use Get-ADGroupMember at all, as you may be passing non-user objects to Get-ADUser. Combining up his suggestion, an example may look like:

$when = (Get-Date '8/20/20' ).ToUniversaltime().ToString('yyyMMddHHmmss.Z')

$groupDN = (Get-ADGroup -Identity $groupname).DistinguishedName

Get-ADUser -LDAPFilter "(&(memberOf=$groupDN)(whencreated>=$when))" | 
Select-Object @{Name = 'UserName'; Expression = { $_.UserPrincipalName }} | 
Export-csv $filename -NoTypeInformation
Steven
  • 6,817
  • 1
  • 14
  • 14
  • 1
    Nice answer, I think it's important to note that `Get-ADuser` _could_ throw supposing the group has a member that is not a `user` object, which is why I would always recommend `Get-ADUser -LDAPFilter "(&(memberOf=$groupDN)(whencreated>=$when))"` assuming `$groupDN` has the DistinguishedName` of the group in question, and not use `Get-ADGroupMember` at all (hate that cmdlet :P) – Santiago Squarzon Aug 19 '21 at 22:12
  • 1
    Stop the hate bro. Just kidding, great addition to the answer! I will edit to add it with credit... Come to think of it it's always annoyed me that the *Group* cmdlets don't handle non-user/group objects. For example mail contacts. I liked QAD cmdlets better, but their .Net dependency is making them untenable. Thanks again for the input. – Steven Aug 19 '21 at 22:52
  • Wow thanks all for the breaking it down for me I thought it was something with the piping but I am very new to powershell. Thanks a ton! – Justin V Aug 20 '21 at 12:01