I have a list of servers where I need to get the OU, I have put together a script that will do this.
Get-ADOrganizationalUnit
-Identity $(($adComputer = Get-ADComputer -Identity $env:COMPUTERNAME).DistinguishedName.SubString($adComputer.DistinguishedName.IndexOf("OU=")))
The issue here is that the OU name is hard to read and not easy on the eye, so I figured out that what i need is the CanonicalName. However here is the problem.
I have come up with the snippet below.
Get-ADOrganizationalUnit -Filter * -properties CanonicalName, DistinguishedName
| select-Object CanonicalName,DistinguishedName
The problem with the above is that it gets everything in AD, I need to be able to filter by servername so that when I load up the server list in a file, I can use a foreach loop to get a report of the servername and the OU, I have tried to use the -Server filter to no avail, as I believe that is for the AD server.
During my research I found, PowerShell filter by OU. In my test environment, it has been running for hours with no results back.
The snippet below will return groups, I cannot get servername filter to work.
Get-ADOrganizationalUnit -Properties CanonicalName -Filter *
| Sort-Object CanonicalName
| ForEach-Object { [pscustomobject]# {
Name = Split-Path $_.CanonicalName -Leaf
CanonicalName = $_.CanonicalName
UserCount = #(Get-AdUser -Filter * -SearchBase $_.DistinguishedName -SearchScope OneLevel).Count
}
}
This is how I would do it:
First query all the computers from your list. Here I'm assuming the computer list is coming from a CSV and the computers are on a column named Computers.
Get the computer's Organizational Unit by removing the Common Name from their DistinguishedName: (.... -split '(?=OU=)',2)[-1]
Add the computers objects to a Hash Table where the Keys are the computer's OUs. This will let us query each OU only once.
Loop over the Hash Table keys (OU's DistinguishedName) querying their CanonicalName.
Create a new object for each computer with the desired properties.
Export the result to a Csv.
# If it's a txt file instead:
# $computers = Get-Content path/to/computers.txt
$csv = Import-Csv path/to/csv.csv
$map = #{}
# If it's a txt file, instead:
# foreach($computer in $computers)
foreach($computer in $csv.Computers)
{
try
{
$adComputer = Get-ADComputer $computer
$ou = ($adComputer.DistinguishedName -split '(?=OU=)',2)[-1]
if($val = $map[$ou]) {
$map[$ou] = $val + $adComputer
continue
}
$map[$ou] = , $adComputer
}
catch
{
Write-Warning $_.Exception.Message
}
}
$result = foreach($ou in $map.Keys)
{
$params = #{
Identity = $ou
Properties = 'canonicalName'
}
try
{
$canonical = Get-ADOrganizationalUnit #params
foreach($computer in $map[$ou])
{
[pscustomobject]#{
'Computer Name' = $computer.Name
'OU DistinguishedName' = $ou
'OU CanonicalName' = $canonical.CanonicalName
}
}
}
catch
{
Write-Warning $_.Exception.Message
}
}
$result | Export-Csv .... -NoTypeInformation
Would something like this work? Filter on a computer name or a wildcard pattern, then get the OU name and OU canonical name using the computer's DistinguishedName and CanonicalName properties:
$filter = "Name -eq 'SERVER01'" # exact name
# OR
$filter = "Name -like 'SERVER*'" # anything that starts with SERVER
Get-ADComputer -Filter $filter -Properties canonicalname |
select name,
#{ name = 'OU' ; expression = { [void]($_.DistinguishedName -match 'OU=.+$'); $Matches[0] } },
#{ name = 'OU Canonical' ; expression = { $_.CanonicalName -replace "/$($_.Name)" } }
Related
In the code below, the userprinciplename will output strings like "LLL_John.Smith#email.com" and XXXX_Jane.Doe#email.com" but i am hoping to extract a substring from that, that being the codes before the "_" character, so LLL and XXXX.
There may be some which do not have an underscore character however and so these would need to be ignored / have the original string it would have returned.
##Check bottom of script for setting specific OU
Function Get-LastLogon {
param(
[string]$OUName
)
# Get all matching OUs on any level
$OUs = Get-ADOrganizationalUnit -Filter "Name -like '$OUName'"
$DCs = Get-ADDomainController -Filter *
# Get all users from each OU from each DC
$ADUsers = Foreach ($OU in $OUs) {
Foreach ($DC in $DCs.HostName) {
Get-ADUser -SearchBase $OU.DistinguishedName -Filter * -Properties LastLogon -server $dc |
Select-Object Name,userPrincipalName, #{n='LastLogon';e={[DateTime]::FromFileTime($_.LastLogon)}}
}
}
# return most recent LastLogon date for each user
$ADUsers |
Group Name,userPrincipalName |
Select Name,userprinciplename, #{n='LastLogon';e={$_.Group.LastLogon | sort -desc | select -First 1}}
} ## End function
##Enter the OU here
Get-LastLogon -OUName 'Clients'
##Un-comment below to export to csv
## | Export-Csv -Path 'C:\temp\UserExport.csv'
Here is what the script looks like now in full:
##Check bottom of script for setting specific OU
Function Get-LastLogon {
param(
[string]$OUName
)
# Get all matching OUs on any level
$OUs = Get-ADOrganizationalUnit -Filter "Name -like '$OUName'"
$DCs = Get-ADDomainController -Filter *
$ADUsers = foreach ($OU in $OUs) {
foreach ($dc in $DCs.HostName) {
Get-ADUser -SearchBase $OU.DistinguishedName -Filter * -Properties lastLogonTimeStamp -Server $dc |
Select-Object Name,UserPrincipalName,
#{Name = 'LastLogon';Expression = {[DateTime]::FromFileTime($_.lastLogonTimeStamp)}},
#{Name = 'UserCode'; Expression = {([regex]'^([^_]+)_.*').Match($_.UserPrincipalName).Groups[1].Value}}
}
} }
# return the most recent LastLogon date for each user
# (only the users with a code prefix in the UserPrincipalName)
$ADUsers | Where-Object { ![string]::IsNullOrWhiteSpace($_.UserCode) } |
Group-Object UserPrincipalName | ForEach-Object {
[PsCustomObject]#{
Name = $_.Group[0].Name
UserCode = $_.Group[0].UserCode
LastLogon = $_.Group.LastLogon | Sort-Object -Descending | Select-Object -First 1
}
}
## End function
$OUcustom = Read-Host -prompt 'Enter OU here or "Clients" for all'
##Enter the OU here
Get-LastLogon -OUName $OUcustom |
##export csv
Export-Csv -path "C:\temp\UserExport_$((Get-Date).ToString("ddMM_HHmm")).csv" -NoTypeInformation
".csv extracted to C:\temp"
pause
Just add another calculated property to the code you have to get the array of user objects:
$ADUsers = foreach ($OU in $OUs) {
foreach ($dc in $DCs.HostName) {
Get-ADUser -SearchBase $OU.DistinguishedName -Filter * -Properties lastLogonTimeStamp -Server $dc |
Select-Object Name,UserPrincipalName,
#{Name = 'LastLogon';Expression = {[DateTime]::FromFileTime($_.lastLogonTimeStamp)}},
#{Name = 'UserCode'; Expression = {if ($_.UserPrincipalName -like '*_*#*') {($_.UserPrincipalName -split '_')[0]} else { $null }}}
# or use regex like:
# #{Name = 'UserCode'; Expression = {([regex]'^([^_]+)_.*').Match($_.UserPrincipalName).Groups[1].Value}}
}
}
Then you can filter out the users that do have such a code:
# return the most recent LastLogon date for each user
# (only the users with a code prefix in the UserPrincipalName)
$ADUsers | Where-Object { ![string]::IsNullOrWhiteSpace($_.UserCode) } |
Group-Object UserPrincipalName | ForEach-Object {
[PsCustomObject]#{
Name = $_.Group[0].Name
UserCode = $_.Group[0].UserCode
LastLogon = $_.Group.LastLogon | Sort-Object -Descending | Select-Object -First 1
}
}
If you want to rule out all users that do not have some code followed by an underscore in their UserPrincipalName property straight away, you can use the filter parameter:
Get-ADUser -SearchBase $OU.DistinguishedName -Filter "UserPrincipalName -like '*_*#*'" -Properties lastLogonTimeStamp -Server $dc
This however will not give you the opportunity to use the collected users for some other purpose, like outputting users who do not have a code prefixed, as would be easy to do with the code above.
P.S. Did you know PowerShell also provides an attribute LastLogonDate, which is the LDAP property lastLogonTimeStamp, converted to local time.
So this was actually more simple than I realised.
I just needed to add in:
#{N='userPrincipalName';E={$_.userPrincipalName.Split("_")[0]}}
To the first and second blocks where UserPrincipleName was being selected.
Will post the full working code below for relevance.
##Check bottom of script for setting specific OU
Function Get-LastLogon {
param(
[string]$OUName
)
# Get all matching OUs on any level
$OUs = Get-ADOrganizationalUnit -Filter "Name -like '$OUName'"
$DCs = Get-ADDomainController -Filter *
# Get all users from each OU from each DC
$ADUsers = Foreach ($OU in $OUs) {
Foreach ($DC in $DCs.HostName) {
Get-ADUser -SearchBase $OU.DistinguishedName -Filter * -Properties LastLogon -server $dc |
Select-Object Name,#{N='userPrincipalName';E={$_.userPrincipalName.Split("_")[0]}}, #{n='LastLogon';e={[DateTime]::FromFileTime($_.LastLogon)}}
}
}
# return most recent LastLogon date for each user
$ADUsers |
Group Name,userPrincipalName |
Select Name,#{N='userprinciplename';E={$_.userprinciplename.Split("_")[0]}}, #{n='LastLogon';e={$_.Group.LastLogon | sort -desc | select -First 1}}
} ## End function
$OUcustom = Read-Host -prompt 'Enter OU here or "Clients" for all'
##Enter the OU here
Get-LastLogon -OUName $OUcustom |
##export csv
Export-Csv -path "C:\temp\UserExport_$((Get-Date).ToString("ddMM_HHmm")).csv" -NoTypeInformation
".csv extracted to C:\temp"
pause
My goal is to dump a CSV of our AD groups, their members, and whether those member objects are enabled, but I'm running into a strange (probably self-inflicted) issue, wherein a Foreach-Object loop is behaving unexpectedly.
The output almost works. It dumps a CSV file. The file has rows for each group, populated with the correct group-related data, and the right number of rows, following the number of group members. However, group member properties on those rows is repeated, showing the same user data over and over for each groupmember result, apparently following the properties of the last returned object from Get-ADGroupMember.
To try to diagnose the issue, I added the line Write-Host $GroupMember.Name -ForegroundColor Gray. This is how I knew the entries in the CSV were the last-returned results for each group. Confusingly, the console correctly echoes each group member's display name.
I'm assuming there's some kind of logic error at work here, but I have had no luck finding it. Any help would be appreciated!
clear
Import-Module ActiveDirectory
# CONFIG ========================================
# Plant Number OU to scan. Used in $CSV and in Get-ADComputer's search base.
$PlantNumber = "1234"
# FQDN of DC you want to query against. Used by the Get-AD* commands.
$ServerName = "server.com"
# Output directory for the CSV. Default is [Environment]::GetFolderPath("Desktop"). Used in $CSV. NOTE: If setting up as an automated task, change this to a more sensible place!
$OutputDir = [Environment]::GetFolderPath("Desktop")
# CSV Output string. Default is "$OutputDir\$PlantNumber"+"-ComputersByOS_"+"$(get-date -f yyyy-MM-dd).csv" (+'s used due to underscores in name)
$CSV = "$OutputDir\$PlantNumber"+"GroupMembers_"+"$(get-date -f yyyy-MM-dd).csv"
# Create empty array for storing collated results
$collectionTable = #()
# Get AD groups, return limited properties
Get-AdGroup -filter * -Property Name, SamAccountName, Description, GroupScope -SearchBase "OU=Security Groups,OU=$PlantNumber,OU=Plants,DC=SERVER,DC=COM" -server $ServerName | Select SamAccountName, Description, GroupScope | Foreach-Object {
Write-Host "Querying" $_.SamAccountName "..."
#Initialize $collectionRow, providing the columns we want to collate
$collectionRow = "" | Select GroupName, GroupScope, GroupDesc, MemberObjectClass, MemberName, MemberDisplayName, Enabled
# Populate Group-level collectionRow properties
$collectionRow.GroupName = $_.SamAccountName
$collectionRow.GroupDesc = $_.Description
$collectionRow.GroupScope = $_.GroupScope
# Process group members
Get-ADGroupMember -Identity ($collectionRow.GroupName) -Server $ServerName -Recursive | ForEach-Object {
$GroupMember = $_
# Echo member name to console
Write-Host $GroupMember.Name -ForegroundColor Gray
$collectionRow.MemberName = $GroupMember.SamAccountName
$collectionRow.MemberDisplayName = $GroupMember.name
$collectionRow.MemberObjectClass = $GroupMember.ObjectClass
# If the member object is a user, collect some additional data
If ($collectionRow.MemberObjectClass -eq "user") {
Try {
$collectionRow.Enabled = (Get-ADUser $GroupMember.SamAccountName -Property Enabled -ErrorAction Stop).Enabled
If ($collectionRow.Enabled -eq "TRUE") {$collectionTable += $collectionRow}
}
Catch {
$collectionRow.Enabled = "ERROR"
$collectionTable += $collectionRow
}
}
}
}
Write-Host "`n"
# Attempt to save results to CSV. If an error occurs, alert the user and try again.
$ExportSuccess = 'false'
while ($ExportSuccess -eq 'false') {
Try
{
# Export results to $CSV
$collectionTable| Export-csv $CSV -NoTypeInformation -ErrorAction Stop
# If the above command is successful, the rest of the Try section will execute. If not, Catch is triggered instead.
$ExportSuccess = 'true'
Write-Host "`nProcessing complete. Results output to"$CSV
}
Catch
{
Write-Host "Error writing to"$CSV"!" -ForegroundColor Yellow
Read-Host -Prompt "Ensure the file is not open, then press any key to try again"
}
}
There are many things from your code you need to fix, I'll just point out the most important ones:
Don't use #() and +=
You keep using 'True' and 'False' which are strings, PowerShell booleans are $true and $false.
There is also too much redundant code. Also ForEach-Object is slow, if your groups have many members and since you're using -Recursive it's better to use a fast loop instead.
$PlantNumber = "1234"
$ServerName = "server.com"
$OutputDir = [Environment]::GetFolderPath("Desktop")
$fileName = "${PlantNumber}GroupMembers_$(Get-Date -f yyyy-MM-dd).csv"
$CSV = Join-Path $OutputDir -ChildPath $fileName
# $collectionTable = #() => Don't do this to collect results, ever
$adGroupParams = #{
# Name and SAM are default, no need to add them
Properties = 'Description', 'GroupScope'
SearchBase = "OU=Security Groups,OU=$PlantNumber,OU=Plants,DC=SERVER,DC=COM"
Server = $ServerName
Filter = '*'
}
# Get AD groups, return limited properties
$collectionTable = foreach($group in Get-AdGroup #adGroupParams)
{
Write-Host "Querying $($group.samAccountName)..."
foreach($member in Get-ADGroupMember $group -Server $ServerName -Recursive)
{
# if this member is 'user' the Enabled property
# will be a bool ($true / $false) else it will be $null
$enabled = if($member.ObjectClass -eq 'User')
{
(Get-ADUser $member).Enabled
}
[pscustomobject]#{
GroupName = $group.SamAccountName
GroupDesc = $group.Description
GroupScope = $group.GroupScope
MemberName = $member.SamAccountName
MemberDisplayName = $member.Name
MemberObjectClass = $member.ObjectClass
Enabled = $enabled
}
}
}
as i understand, you need to export list of groups with members to a csv file and know if member accounts are enabled or not, if this what you want, you can check the below code
$output = #()
Import-Module ActiveDirectory
$ServerName = "server.com"
$PlantNumber = "1234"
$OutputDir = [Environment]::GetFolderPath("Desktop")
$CSV = "$OutputDir\$PlantNumber"+"GroupMembers_"+"$(get-date -f yyyy-MM-dd).csv"
$groups = Get-AdGroup -filter * -Property Description -SearchBase "OU=Security Groups,OU=$PlantNumber,OU=Plants,DC=SERVER,DC=COM" -server $ServerName
foreach ($group in $groups){
$members = Get-ADGroupMember -Identity $group.SamAccountName -Recursive
foreach ($member in $members){
$output += [pscustomobject]#{
GroupName = $group.SamAccountName
GroupDesc = $group.Description
GroupScope = $group.GroupScope
MemberName = $member.samaccountname
MemberDisplayName = $member.Name
MemberObjectClass = $member.ObjectClass
Enabled = $(Get-ADUser -Identity $member.samaccountname).enabled
}
}
}
$output | Export-Csv $CSV -NoTypeInformation
I am explicitly NOT refering your code. I'd just like to show how I would approach this task. I hope it'll help you anyway.
$Server = 'Server01.contoso.com'
$SearchBase = 'OU=BaseOU,DC=contoso,DC=com'
$CSVOutputPath = '... CSV path '
$ADGroupList = Get-ADGroup -Filter * -Properties Description -SearchBase $SearchBase -Server $Server
$ADUserList = Get-ADUser -Filter * -Properties Description -SearchBase $SearchBase -Server $Server
$Result =
foreach ($ADGroup in $ADGroupList) {
$ADGroupMemberList = Get-ADGroupMember -Identity $ADGroup.sAMAccountName -Recursive
foreach ($ADGroupmember in $ADGroupMemberList) {
$ADUser = $ADUserList | Where-Object -Property sAMAccountName -EQ -Value $ADGroupmember.sAMAccountName
[PSCustomObject]#{
ADGroupName = $ADGroup.Name
ADGroupDescription = $ADGroup.Description
ADGroupMemberName = $ADUser.Name
ADGroupMemberSamAccountName = $ADUser.sAMAccountName
ADGroupMemberDescription = $ADUser.Description
ADGroupMemberStatus = if ($ADUser.Enabled) { 'enabled' }else { 'diabled' }
}
}
}
$Result |
Export-Csv -Path $CSVOutputPath -NoTypeInformation -Delimiter ',' -Encoding utf8
It'll output only the a few properties but I hope you get the idea.
BTW: The properties DistinguishedName, Enabled, GivenName, Name, ObjectClass, ObjectGUID, SamAccountName, SID, Surname, UserPrincipalName are included in the default return set of Get-ADUser and the properties DistinguishedName, GroupCategory, GroupScope, Name, ObjectClass, ObjectGUID, SamAccountName, SID are included in the default return set of Get-ADGroup. You don't need to query them explicitly with the parameter -Properties.
im trying to pull out all the information regarding my domain admin adminsitrators
#set domains we are going to query
$domains = 'mydomainname.com'
#first here i bring the sam accounts names
Foreach ($domain in $domains)
{
$OUTPUT =Get-AdGroupMember -identity “Domain Admins” -recursive -server $domain |
Select-Object -Property samAccountName|
Select samAccountName;
$Outputs +=$OUTPUT;
$OUTPUT |Export-CSV "C:\File\$($domain).csv" -NoTypeInformation ;
}
$OUTPUT #this print the sam accounts
#here is the problem
Foreach ($user in $OUTPUT)
{
$Users2 =Get-ADUser -Filter "SamAccountName -like '$OUTPUT'" -Properties *
$USER3 +=$Users2;
$Users2 |Export-CSV "C:\File\$($domain)Userpop.csv" -NoTypeInformation ;
}
I think this is a problem with your filter. Try changing that line as follows:
Get-ADUser -Filter " SamAccountName -like `"$($user.samaccountname)`" " -Properties *
It can't be $OUTPUT as that's an array. Your loop variable is $user which is an object so you need the .samaccountname property. The filter needs a string with the -like matching a quoted string, so you need `" to pass the quote through to the final string.
Your CSV output of $user2 may not be what you expect either as each object is output to the same file. Perhaps you mean to have a -Append or write them to different files?
You'll probably want to reset $user3 as well. Perhaps add $user3 = #() before that loop.
You should always try to avoid adding to arrays with $array += $something, because that means the entire array gets rebuild in memory, costing time and resources.
Also, I would advise using more descriptive variable names, so the code will still be understandable after some time.
Then, because you are getting info from different domains, it is important to store the domain name in the first loop together with the samaccount names, so you can use these as -Server parameter in the second loop on Get-ADUser
Try
#set domains we are going to query
$domains = #('mydomainname.com') # since there is only one domain listed, use #() to force it into an array
$domainsAndAdmins = foreach ($domain in $domains) {
# store the SamAccountNames for this domain as objects in an array
$admins = Get-AdGroupMember -Identity 'Domain Admins' -Recursive -Server $domain |
Select-Object -Property SamAccountName
# export this to csv file
$outFile = 'C:\File\{0}.csv' -f $domain
$admins | Export-Csv $outFile -NoTypeInformation
# output an object with both the domain and the array of SamAccountNames
# this will be captured in variable $domainsAndAdmins
[PsCustomObject]#{Domain = $domain; Admins = $admins.SamAccountName }
}
# output on screen
$domainsAndAdmins | Format-Table -AutoSize
# will result in something like
#
# Domain Admins
# ------ ------
# mydomainname.com {jdoe, jbloggs, mpimentel}
# myseconddomainname.com {jdoe, mpimentel}
# next get ALL (?) properties from the users we found
$domainsAndAdmins | ForEach-Object {
$domain = $_.Domain
$result = foreach ($user in $_.Admins) {
Get-ADUser -Filter "SamAccountName -like '$user'" -Server $domain -Properties * -ErrorAction SilentlyContinue
}
$outFile = 'C:\File\{0}_Userpop.csv' -f $domain
$result | Export-Csv $outFile -NoTypeInformation
}
I am trying to query multiple computers from the Domain using Get-ADComputer. I would like to append the pc name I queryed to the array with the word "error" or a nonsensical date or even a blank value in that spot.
Import-Module ActiveDirectory
$PCNames = "laptop-namea", "laptop-nameb", "laptop-badname"
$Output = #()
$Output = foreach ($PC in $PCNames) {
try {
Get-ADComputer -Identity $PC -Properties * |
Select-Object Name, LastLogonDate
} catch {
$Output += ($PC)
}
}
Current output:
Name LastLogonDate
---- -------------
LAPTOP-NAMEA 1/27/2019 10:37:13 AM
LAPTOP-NAMEB 1/22/2019 8:23:02 AM
Wanted/expected output:
Name LastLogonDate
---- -------------
LAPTOP-NAMEA 1/27/2019 10:37:13 AM
LAPTOP-NAMEB 1/22/2019 8:23:02 AM
LAPTOP-BADNAME
Use -Filter instead of -Identity to avoid throwing errors in case of invalid names.
$Output = foreach ($PC in $PCNames) {
New-Object -Type PSObject -Property #{
'Name' = $PC
'LastLogon' = Get-ADComputer -Filter "Name -eq '$PC'" -Property LastLogonDate |
Select-Object -Expand LastLogonDate
}
}
Beware that querying AD for each individual computer is time-consuming. If the number of queries grows beyond a certain point it's better to query all computers, put them into an appropriate data structure (usually a hashtable), and then look up the desired information in that data structure.
$computers = #{}
Get-ADComputer -Filter '*' -Property LastLogonDate | ForEach-Object {
$computers[$_.Name] = $_.LastLogonDate
}
$Output = foreach ($PC in $PCNames) {
New-Object -Type PSObject -Property #{
'Name' = $PC
'LastLogon' = $computers[$PC].LastLogonDate
}
}
Try - Catch - Finally blocks handle terminating errors. Apply the common parameter -ErrorAction -Stop as follows:
Import-Module ActiveDirectory
$PCNames = "laptop-namea","laptop-nameb","laptop-badname"
$Output = ForEach ($PC in $PCNames)
{
try{
Get-ADComputer -Identity $PC -Properties * -ErrorAction Stop |
Select-Object Name, LastLogonDate
}
catch{
[PSCustomObject]#{Name=$PC;LastLogonDate=$null}
}
}
edited from original question because the real problem was something unrelated to the question
I got a list of trustees from NTFS permissions and now I want to expand the groups to show membership. If I have a SAM name like MyDomain\name, there's no indication of whether that is a group or not. The Get-ADobject command has an ObjectClass property which will indicate group or user if this is an Active Directory domain object. One can use:
Get-ADObject -filter 'SamAccountName -eq "My Users"' or
$sam = "My Users"
Get-ADObject -filter 'SamAccountName -eq $sam'
Thanks to JPBlanc who had an alternate form of writing that with a script block and some other suggestions.
And thanks, user2142466. That looks like a good suggestion for my original script.
You can use a variavle using :
$sam = "My Users"
Get-ADObject -Filter {(SamAccountName -eq $sam)}
But I agree that using vars in -Filter sometimes results in strange behaviours with vars (see this question), so I prefer to use -LDAPFilter.
Get-ADObject -LDAPFilter "(SamAccountName =$user)"
Be careful the -LDAPFilter use polish notation for the filter, it's a bit disconcerting at the begining, but here, it's the natural way of filtering using the underlaying protocol LDAP.
You can get more information about this syntax in Search Filter Syntax, you can also get corresponding filters in About_ActiveDirectory_Filter.
I am guessing you are getting an array of trustees. (i.e User,Group,user,user,Group). So if you get a group then you want to pull the members from it too?
So I would look to see if it is a group, like how you are doing first and then pulling those members out of it. Add it to an another array which will contain every single user for your NTFS permissions.
$arraytrustees
#Create a blank Array
$NTFSUsers =#()
for each ($object in $arraytrustees){
$ObjectClass = (Get-ADObject -filter {SamAccountName -eq $object}).ObjectClass
If ($ObjectClass -eq "group"){
$AdGroupUsers = (Get-ADGroupMember -identity $object).SamAccountName
$NTFSUsers = $NTFSUsers + $AdGroupUsers
}else{
$NTFSUsers = $NTFSUsers + $ojbect
}
}
I was asked to list all members of the groups, along with their ID, Name, and Description as well, so I added a couple of lines.
cls
$Users = #()
$Groups = #()
$list = Get-Content z:\pcm2.txt
Foreach ($o in $list)
{
$ObjectClass = (Get-ADObject -Filter {SamAccountName -eq $o}).ObjectClass
If ($ObjectClass -eq "User")
{
$U = Get-ADUser -Properties * -Identity $o
$User = "" | Select FullUserName, LoginID, Description
$User.FullUserName = $U.DisplayName
$User.LoginID = $U.SamAccountName
$User.Description = $U.description
$Users += $User
}
Else
{
If ($ObjectClass -eq "Group")
{
$G = Get-ADGroup -Properties * -Identity $o
$GM = Get-ADGroupMember -Identity $G.name -Recursive | Get-ADUser -Properties *
Foreach ($gmember in $GM)
{
$Group = "" | Select GroupName, GroupDescription, GroupMemberName, GroupMemberLoginID, GroupMemberDesc
$Group.GroupName = $G.Name
$Group.GroupDescription = $G.Description
$Group.GroupMemberName = $gmember.Name
$Group.GroupMemberLoginID = $gmember.SamAccountName
$Group.GroupMemberDesc = $gmember.Description
$Groups += $Group
}
}
}
}
$Users | Export-Csv z:\PCMUsers.csv -NoTypeInformation
$Groups | Export-Csv z:\PCMGroups.csv -NoTypeInformation
I received a list and was asked to determine whether the objects were users or group, and I came up with this. It worked!
cls
$Users = #()
$Groups = #()
$list = Get-Content z:\pcm.txt
Foreach ($o in $list)
{
$ObjectClass = (Get-ADObject -Filter {SamAccountName -eq $o}).ObjectClass
If ($ObjectClass -eq "User")
{
$U = Get-ADUser -Properties * -Identity $o
$User = "" | Select FullUserName, LoginID, Description
$User.FullUserName = $U.DisplayName
$User.LoginID = $U.SamAccountName
$User.Description = $U.description
$Users += $User
}
Else
{
If ($ObjectClass -eq "Group")
{
$G = Get-ADGroup -Properties * -Identity $o
$Group = "" | Select GroupName, Description
$Group.GroupName = $G.Name
$Group.Description = $G.Description
$Groups += $Group
}
}
}
$Users | Export-Csv z:\Users.csv -NoTypeInformation
$Groups | Export-Csv z:\Groups.csv -NoTypeInformation