0

PowerShell "white belt" here, first time poster. I'll try not to lower the collective IQ of such a helpful community while I'm here! :) I'm running PowerShell 3.0 with Quest installed.

My organization has an Active Directory OU with several Security Groups that all control VPN access - these were created in the days before we had naming conventions (ugh!)

I'd prefer not to rely on the names by going "get me the members of X and Y and Z" but rather say "get me the members of anything in OU XXX" instead.

Ideally, I'd like a count at the end too, because ultimately this is for auditing "how many users have VPN access" (although I could barf results out to a .CSV or something if that's too complicated)

So I have some pieces that will do PARTS of this, I just can't quite visualize how to fit them all together. Any help would be appreciated. Here are my moving parts:

returns users in one specific group:

get-adgroupmember "group_of_coolness" -recursive | Select name

returns results from a user-filled OU using "searchbase":

Get-ADUser -Filter * -SearchBase 'ou=XXX,ou=XXX,dc=XXX,dc=XXX,dc=org' -Properties GivenName, Surname, EmailAddress, Office, Company, Title, distinguishedname | 
select GivenName, Surname, EmailAddress, Office, Company, Title, distinguishedname | Out-GridView 

returns results from a couple of specific groups but also gives a count (my most advanced patch-work so far ^^):

    $GroupMembers=(get-ADGroup -filter {(Name -eq "XXXX") -or (Name -eq "YYYY")} |
     get-adgroupmember -Recursive | select distinguishedname -Unique)

    $Users=foreach ($user in $GroupMembers.distinguishedname) {
    Get-ADUser $user
    }

    $Users | Sort-Object DistinguishedName |
    select name, DistinguishedName

    Write-Host
    Write-Host "Total Users = " $Users.count

That last code-snippet seems closest to me, IF I could replace the "name -eq XXXX or YYYY" with "-searchbase "ou=XXX..."

What do you think smart people - am I at all close to the answer? Again, thanks for any advice, and let me know if I'm being a jack-ass and overlooking a thread where this is already answered (I found some close calls but nothing quite on-the-money).

I'm excited to see what I'm missing here :)

3Jake
  • 51
  • 1
  • 2
  • 11

2 Answers2

1

You can pretty easily simplify this:

$Users = Get-ADGroup -SearchBase 'ou=XXX,ou=XXX,dc=XXX,dc=XXX,dc=org' -Filter * `
    | Get-ADGroupMember -Recursive `
    | Select-Object -Unique `
    | Sort-Object DistinguishedName;
$Users | Select-Object Name, DistinguishedName;
Write-Output ("Total Users = {0}" -f $Users.Count);

If you want to search by group name, you can change the first line to Get-ADGroup -Filter {(Name -eq "Group A") -or (Name -eq "Group B")} like you were using.

You're not using anything other than Name and Distinguished name in your example, so there's no reason to run it through Get-ADUser a second time and fetch the same data from the server like you were. No reason to waste the DC's time.

If you do need to get additional properties beyond the name and distinguished name, then you do need to do that. You can do it like this:

$Users = Get-ADGroup -SearchBase 'ou=XXX,ou=XXX,dc=XXX,dc=XXX,dc=org' -Filter * `
    | Get-ADGroupMember -Recursive `
    | Select-Object -Unique `
    | ForEach-Object { Get-ADUser $_ -Properties GivenName, Surname, EmailAddress, Office, Company, Title, distinguishedname; } `
    | Sort-Object DistinguishedName;
Bacon Bits
  • 30,782
  • 5
  • 59
  • 66
  • Coooooool... ok, so I see how this puts the groups into a variable and then says "for each group, go get the users and get the following info". (note to self, learn more about foreach loops!) – 3Jake May 21 '15 at 16:26
  • - This definitely falls under the category of "additional improvements" beyond the scope of the original question, but I'd like to ignore any disabled users that are still group members, throw the results out to gridview, and make the count show up on the gridview doc as well. I thought I could just slap in the line `where {$_.Enabled -ne $False}` after 'Get-ADGroupMember -Recursive` but the resulting doc still includes disabled accounts (I added the property "enabled" in the list of "get-aduser" stuff). Any suggestions for that? I'll post the updated code block below – 3Jake May 21 '15 at 18:14
  • `$Users = Get-ADGroup -SearchBase 'ou=XXX,ou=XXX,dc=XXX,dc=XXX,dc=org' -Filter * | Get-ADGroupMember -Recursive | where {$_.Enabled -ne $False} | Select-Object -Unique | ForEach-Object { Get-ADUser $_ -Properties GivenName, Surname, EmailAddress, Office, Company, Title, distinguishedname, enabled; } | Sort-Object DistinguishedName | Out-GridView ; Write-Output ("Total Users = {0}" -f $Users.Count);` – 3Jake May 21 '15 at 18:16
  • @3Jake You need to filter after the Get-ADUser, since the Enabled property isn't available in objects from Get-ADGroupMember: `$Users = Get-ADGroup -SearchBase 'ou=XXX,ou=XXX,dc=XXX,dc=XXX,dc=org' -Filter * | Get-ADGroupMember -Recursive | Select-Object -Unique | ForEach-Object { Get-ADUser $_ -Properties GivenName, Surname, EmailAddress, Office, Company, Title, distinguishedname, enabled; } | where {$_.Enabled -ne $False} | Sort-Object DistinguishedName | Out-GridView ; Write-Output ("Total Users = {0}" -f $Users.Count);` – Bacon Bits May 21 '15 at 22:57
  • Ahh, that makes perfect sense in retrospect. I was running into an issue where it would spit the results out to gridview, but not the count. And in the console window, it would report the users as zero. I'm aware that you can pipe results FROM Gridview BACK into the console, and maybe that's the answer, but it's a bit beyond my ken at this point. Gridview for everything would be ideal, but removing that and just letting it print to the console window works perfectly! Thanks for your excellent advice BB, I feel like I learned a lot here! – 3Jake Jun 01 '15 at 15:49
  • @3Jake Well, if you really need to pipe it twice, then just end the line after the sort and save it as a variable, then on separate lines you can do whatever you need. I just copied how you had it and changed as little as possible. Don't feel like you have to put everything on one line because it performs slightly better. Make your code readable first, functional second, and only then worry about performance. – Bacon Bits Jun 01 '15 at 16:15
1

Find all deactivated users in a specific OU:

$ExportFile="C:\TempInf\Inaktiv.txt"

Get-ADGroup -Filter{Name -eq "OU Name"}
$OUpath = 'OU=OU Name,OU=OU Parent,DC=WWW,DC=ORGANIZATION,DC=COUNTRY'

$uf = @{Expression={$_.samAccountName};Label="samAccountName";width=30}, `
      @{Expression={$_.GivenName};Label="GivenName";width=50}, `
      @{Expression={$_.whenChanged};Label="whenChanged";width=20}, `
      @{Expression={$_.Description};Label="Description";width=50}, `
      @{Expression={$_.DistinguishedName};Label="DistinguishedName";width=250}

Get-ADUser -Filter {Enabled -eq $false} -SearchBase $OUpath -Properties samAccountName, GivenName, whenChanged, DistinguishedName, Description |
 Format-Table $uf | 
 Out-File -FilePath $ExportFile -Width 400
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459