Powershell, filters and combining properties - powershell

I have an AD group that has other AD groups as members. Some of these groups may have "sub-groups" as well. I want to recursively descend through this group and find answers to several questions about the users in that group. For example:
Is User-X "enabled" in the overall group?
Does the account of User-X have values in ANY of the properties: AccountExpirationDate, accountExpires and Deleted?
I would like a displayed result that contains the properties: DisplayName, SamAccountName, AccountExpirationDate, accountExpires, Deleted and enabled (from the group object)
I have tried doing an "Add-Member" to insert the "enabled" value from get-ADgroupMember but I get the error:
Add-Member : Cannot add a member with the name "enabled" because a member with that name already exists. If you want to over
write the member anyway, use the Force parameter to overwrite it.
... but there is no such element as far as I can tell. I have renamed the member in the Add-Member to several very unique things but I still get the same error.
my current attempt is:
Import-Module ActiveDirectory
get-adgroupmember -Identity "My big AD group of groups" -recursive |
Where-Object -FilterScript {($_.ObjectClass -eq 'user')} |
ForEach-Object {
$enabled = $_.enebled
Get-ADUser `
-Filter {(name -eq $_.name)} `
-Properties DisplayName,SamAccountName,AccountExpirationDate,accountExpires,Deleted |
Add-Member -Name "myITGGroupEnabled" -Value $enabled -MemberType NoteProperty |
Where-Object `
-FilterScript {
($_.AccountExpirationDate -lt [datetime]::now) `
-OR ($_.accountExpires -eq $true) `
-OR ($_.Deleted -eq $true) `
-OR ($_.myITGGroupEnabled -eq $false)
}
Select-Object DisplayName,SamAccountName,AccountExpirationDate,accountExpires,Deleted,GroupEnabled
break
}
I am lost. Ideas?

I think all you need is a new PSObject. Like this:
...
Get-AdUser -Filter {name -eq $_.name} -Properties .... | % {
If ( ($_.AccountExpirationDate -lt [datetime]::now) `
-OR ($_.accountExpires -eq $true) `
-OR ($_.Deleted -eq $true) `
-OR ($_.myITGGroupEnabled -eq $false)) {
New-Object PSObject -Property #{MyITGGRoupEnabled=$enabled}
}
}

Related

Get-ADUser - Filter child OU's and users where surname is empty

I am trying to run a command where I get all active directory users in the parent OU (Users) and filter out the child OU's (Admin accounts, service accounts, disabled accounts) as well as filter out any user account that does not have a surname in the surname field.
At the moment I have
Get-ADUser -Filter{enabled -eq $true} -SearchBase 'OU=Users,OU=Company,DC=CompanyName,DC=local' | Where-Object { $_.DistinguishedName -notlike "*,$Disabled" } | Where {$_.Surname -notlike "$Null"} | select samAccountName
When I add another child OU after 'Disabled' there is an error
Where-Object : A positional parameter cannot be found that accepts argument 'Where'.
Please may someone advise on how to filter out additional child OU's?
Good day Smoore
The problem is you are using multiple Where-object cmdlets but you only need one and separate them using () and adding the -and option, also to refer to $null value you don't need to use the "" marks
Get-ADUser -Filter {Enabled -eq $true} -SearchBase "OU=Users,OU=Company,DC=CompanyName,DC=local" | Where-Object {($_.DistinguishedName -notlike "*,$Disabled*") -and ($_.Surname -notlike $Null)} | select samAccountName
With this options you should be able to get all the users you want
Have a nice day!
I would use a regex -notmatch so it would be possible to combine all OU Distinguished names in just one variable.
Something like this:
$Admins = 'OU=Administrators,OU=Company,DC=CompanyName,DC=local'
$Service = 'OU=ServiceAccounts,OU=Company,DC=CompanyName,DC=local'
$Disabled = 'OU=DisabledUsers,OU=Company,DC=CompanyName,DC=local'
# build a regex string from the above OU DistinguishedNames
$Exclude = '({0}|{1}|{2})$' -f [regex]::Escape($Admins), [regex]::Escape($Service), [regex]::Escape($Disabled)
Get-ADUser -Filter 'Enabled -eq $true' -SearchBase 'OU=Users,OU=Company,DC=CompanyName,DC=local' |
Where-Object { ![string]::IsNullOrWhiteSpace($_.Surname) -and $_.DistinguishedName -notmatch $Exclude } |
Select-Object SamAccountName
As per your comment:
$Admins = 'OU=Administrators,OU=Company,DC=CompanyName,DC=local'
$Service = 'OU=ServiceAccounts,OU=Company,DC=CompanyName,DC=local'
$Disabled = 'OU=DisabledUsers,OU=Company,DC=CompanyName,DC=local'
# the group you want to add the users to
$TargetGroup = 'Company Team'
# build a regex string from the above OU DistinguishedNames
$Exclude = '({0}|{1}|{2})$' -f [regex]::Escape($Admins), [regex]::Escape($Service), [regex]::Escape($Disabled)
$users = Get-ADUser -Filter 'Enabled -eq $true' -SearchBase 'OU=Users,OU=Company,DC=CompanyName,DC=local' |
Where-Object { ![string]::IsNullOrWhiteSpace($_.Surname) -and $_.DistinguishedName -notmatch $Exclude }
# get the AD group as object
$GroupObject = Get-ADGroup -Filter "Name -eq '$TargetGroup'"
# now add these users that have Surnames to the security group all in one go
try {
Write-Host "Adding $(#($users).Count) users to group $TargetGroup"
$GroupObject | Add-ADGroupMember -Members $users -ErrorAction Stop -Verbose
}
catch {
Write-Warning "Error: $($_.Exception.Message)"
}
# or if you prefer loop through the users and add each one individually then use this instead
# foreach ($user in $users) {
# try {
# Write-Host "Adding user $($users.Name) to group $TargetGroup"
# $GroupObject | Add-ADGroupMember -Members $user -ErrorAction Stop -Verbose
# }
# catch {
# Write-Warning "Error adding user $($users.Name) to group $($TargetGroup): $($_.Exception.Message)"
# }
# }

Powershell - Combining Variables Properties from AD output

First script I have tried to put together. Im trying to get a new variable with ad user name and ad computer by comparing user name property and description properties. I don't know how to pull the properties I want into the new variables based on a compare-object or match. The description property has a setup of username - ######## numbers very.
Variables used (date tell expire)
$SevenDayWarnDate, $ThreeDayWarnDate, $OneDayWarnDate
AD user
$7, $3, $1 -properties "Name", "PasswordExpiry
AD computer
$comp "Name", "Description"
I was then going to make a pop up on user computer based on expiring passwords.
Below is what I was trying to do but im not sure if the needed information was passed as computer filed comes back empty.
$SevenDayWarnDate = (get-date).adddays(7).ToLongDateString()
$7= Get-ADUser -filter {Enabled -eq $True -and PasswordNeverExpires -eq $False -and PasswordLastSet -gt 0 } `
-Properties "Name", "msDS-UserPasswordExpiryTimeComputed" | Select-Object -Property "Name", `
#{Name = "PasswordExpiry"; Expression = {[datetime]::FromFileTime($_."msDS-UserPasswordExpiryTimeComputed").tolongdatestring() }} `
|Where-object -Property PasswordExpiry -EQ $SevenDayWarnDate
$comp = Get-Adcomputer -Filter {Enabled -eq $True} -SearchBase "OU=,DC=" -properties "Name", "Description" `
| Select-Object -Property "Name", "Description"
Compare-Object -ReferenceObject $7 -DifferenceObject $comp -IncludeEqual -ExcludeDifferent -PassThru |
ForEach-Object {
[PSCustomObject]#{
Name = $_.name
Computer = ($comp.name | Where-Object Description -match $_.name).Directory
}
}
Working code based on Santiago Squarzon below.
$dayArray= #()
$dayArray=#(7,3,1)
foreach ($day in $dayArray)
{
$SevenDayWarnDate = (get-date).adddays($day).ToLongDateString()
$filter = "Enabled -eq '$True' -and PasswordNeverExpires -eq '$False' -and PasswordLastSet -gt '0'"
$computerArray= #()
$users = Get-ADUser -Filter $filter -Properties "Name", "msDS-UserPasswordExpiryTimeComputed" |
Select-Object Name, #{
Name = "PasswordExpiry"
Expression =
{
[datetime]::FromFileTime($_."msDS-UserPasswordExpiryTimeComputed").tolongdatestring()
}
} | Where-object -Property PasswordExpiry -EQ $SevenDayWarnDate
# => It might be better to use:
# PasswordExpiry -ge [datetime]::Now -and PasswordExpiry -le $sevenDayWarnDate
# Find the computers each user is using
$result = foreach($user in $users)
{
$temp=$user.Name
if ($comp = Get-ADComputer -Filter "Description -like '*$temp*'" -Properties Description)
{
[PSCustomObject]#{
Name = $user.Name
PasswordExpiry = $user.PasswordExpiry
ComputerName = $comp.Name
ComputerDescription = $comp.Description
}
$tmpArray= #()
$tmpArray= $comp.Name.Split(" ")
foreach($item in $tmparray)
{
$computerArray += $item
}
$tmpArray = $Null
# }
}
continue
}
foreach($computer in $computerArray)
$tmpMessage =
$tmpMessageTitle =
{Send-RDUserMessage -HostServer $env:COMPUTERNAME -UnifiedSessionID 1 -MessageTitle $tmpMessageTitle -MessageBody $tmpMessage
}
$result | Format-Table
}
Based on the comments and the code in question, I'm guessing this is what you're looking for. There is no need to use Compare-Object, you can simply query Active Directory to get the user's computer based on the Description property.
$SevenDayWarnDate = [datetime]::Now.AddDays(7)
$filter = "Enabled -eq '$True' -and PasswordNeverExpires -eq '$False' -and PasswordLastSet -gt '0'"
$users = Get-ADUser -Filter $filter -Properties "Name", "msDS-UserPasswordExpiryTimeComputed" |
Select-Object Name, #{
Name = "PasswordExpiry"
Expression = {
[datetime]::FromFileTime($_."msDS-UserPasswordExpiryTimeComputed")
}
} | Where-object -Property PasswordExpiry -EQ $SevenDayWarnDate
# => It might be better to use:
# {$_.PasswordExpiry -ge [datetime]::Now -and $_.PasswordExpiry -le $sevenDayWarnDate}
# Find the computers each user is using
$result = foreach($user in $users)
{
if($comp = Get-ADComputer -LDAPFilter "(description=$($user.Name))" -Properties Description)
{
[PSCustomObject]#{
Name = $user.Name
PasswordExpiry = $user.PasswordExpiry
ComputerName = $comp.Name
ComputerDescription = $comp.Description
}
continue
}
Write-Host "No computer was found for User: $($user.Name)"
}
$result | Format-Table

Get-ADUser is not returning anything when I use the UPN returned from Get-MailboxPermissions as a variable

I am trying to get the SamAccountName from Get-ADUser, but when I pass in the variable $member.User I get no results. $member.User when I print it out with Write-Host returns a variable, but used in the code below I get nothing. Also, if I copy/paste the $member.User value into that $add = Get-ADUser I get the SamAccountName. Why isn't Get-ADUser -Filter {EmailAddress -eq "$member.User" } returning anything? It is driving me nuts. Thank you in advance.
$Send = #()
$SendAs = #()
# Displaying FullAccess permissions for shared mailboxes
$Send = Get-MailboxPermission -Identity $MailboxUPN | Where-Object { -not ($_.User -like “NT AUTHORITY\SELF”) } | Select-Object Identity,User,AccessRights
$Send
# Displaying SendAs permissions for shared mailboxes
# $SendAs = Get-RecipientPermission -Identity $MailboxUPN | Where-Object {($_.IsInherited -eq $False) -and -not ($_.Trustee -like “NT AUTHORITY\SELF”) } | Select-Object Trustee, AccessRights
# $SendAs
forEach ($member in $Send){
Write-Host "In here"
Write-Host $member
$add = Get-ADUser -Filter {EmailAddress -eq "$member.User" }| Select-Object -ExpandProperty SamAccountName
Write-Host $add.SamAccountName
}

Get user count and actual userdata in a csv file in Powershell

I am trying to get the user count and the actual userinformation through get-aduser but fail miserably.
Get-ADUser -Server $test -Credential $1cred -Filter{enabled -eq $true} | Where-Object { $_.DistinguishedName -notlike '*OU=.Service Accounts,*' -and $_.samaccountname -notlike '*health*' } | Select-object Samaccountname,surname,givenname | Where { $excludedusers -NotContains$_.Samaccountname } | format-list > 'C:\Scripts\Test\enabled_users_and count.csv'
Is the current code. I can add a .count before format-list like this:
(Get-ADUser -Server $test -Credential $1cred -Filter{enabled -eq $true} | Where-Object { $_.DistinguishedName -notlike '*OU=.Service Accounts,*' -and $_.samaccountname -notlike '*health*' } | Select-object Samaccountname,surname,givenname | Where { $excludedusers -NotContains$_.Samaccountname }).count
But I only get the count of the users, as earlier said, I need both.
Extremely thankful for the help.
You need Two different things, Count don't need to be a field in the csv, you can get it by the line count of the final output
You might need the count for the console use, anyway it's not logically right to save it in the final output. (if I understand you right)
You can save it to a variable, then do export or count check...
$Users = Get-ADUser -Server $test -Credential $1cred -Filter{enabled -eq $true} |
Where-Object { $_.DistinguishedName -notlike '*OU=.Service Accounts,*' -and $_.samaccountname -notlike '*health*' } |
Where { $excludedusers -NotContains $_.Samaccountname }
Export:
$Users | Select-object Samaccountname,surname,givenname |
Export-CSV 'C:\Scripts\Test\enabled_users_and count.csv'
Check Count:
$Users.Count

Powershell - Get-AdUser: Exclude users in array

I want to generate a list of users, with the exception of a list of names. This exclusion list changes from week to week.
$exclude = #('smith, bob', 'jones, tom', ...)
$csvmaster = #()
$uacct = 'User Account'
$UserID = 'User ID'
$lastname = 'Last Name'
... other attributes
$ulist = get-aduser -filter {enabled -eq 'true'} -properties * | ? {$_.Distinguishedname -like '*Standard User*' -and $_.title -ne $null -and $_.employeenumber -ne $null}
foreach ($u in $ulist)
{
if ($u.name -notmatch $exclude) {
$csvline = New-Object System.Object
$csvline | Add-Member -MemberType NoteProperty -name $UserID -value $u.EmployeeNumber
$csvline | Add-Member -MemberType NoteProperty -name $lastname -value $u.surname
...other attributes
$csvmaster += $csvline
}
}
...Output to csv
When I run this, the names I want to exclude still make it into the list. I also tried -notcontains and excluding them like this:
$ulist = get-aduser -filter {enabled -eq 'true'} -properties * | ? {$_.Distinguishedname -like '*Standard User*' -and $_.title -ne $null -and $_.employeenumber -ne $null -and $_.name -notmatch $exclude}
This behaves the same way.
Cheers.
So I think my problem was the way Get-ADUser accepts input value. And/Or my logic in general. I changed the code to this:
$exclude = #( ..list..of..names..)
$csvline = #()
$ulist = get-aduser ...
foreach ($u in $ulist)
{
if ($exclude -notcontains $u.name)
{
...
$csvline += $u.name
}
}
And it is doing what I need.