Get-ADUser unable to sort by LastLogonDate - powershell

I'm trying to sort my disabled users by the last date they logged in.
I used the following command:
Get-ADUser -Filter "samaccountname -eq '$user' -and enabled -eq '$False'" -Properties * |
select samaccountname, displayname, emailaddress, LastLogonDate |
Sort-Object -Property LastLogonDate
I'm not sure why, but it doesn't sort the LastLogonDate property. I keep getting an unsorted list of my disabled users.

Continuing from my comment, I think the code you show is the part inside a loop where you iterate users, perhaps based on the input from a CSV file.
Your code only finds one single user and sorts that one object on its LastLogonDate.
The sorting should be done after you have collected all your users like
# capture the resulting objects from a collection of users
$result = foreach ($user in $MyListOfUserSamAccountNames) {
Get-ADUser -Filter "samaccountname -eq '$user' -and enabled -eq '$False'" -Properties displayname, emailaddress, LastLogonDate |
Select-Object samaccountname, displayname, emailaddress, LastLogonDate
}
# here is where you sort the result for output
$result | Sort-Object -Property LastLogonDate
Please bear in mind that the calculated property LastLogonDate (not really a AD attribute at all) is not replicated within the domain and to get the most accurate value, you need to iterate the domaincontrollers in your domain.

Related

Upstream filtering a users AD users group membership list by wild-carded string

I have a requirement to combine Get-ADUser and Get-ADGroup (with filtering) to retrieve a list of a users groups, only where the group name matches a wildcard pattern I specify.
Getting the whole list of a users groups can be slow over VPN when WFH. So instead of retrieving all the users group names into an array, then looping through that to find the matching names I need, can I include the group name filtering further upstream in the Get-ADUser call, or the Get-ADGroup call?
My question isn't so much "how is it done?" but "can it be done?", and would it actually be any quicker than pulling all group names into an array then looping.
Something like:
$SEC_GROUPS = (Get-ADUser $_ –Properties MemberOf).memberof |
Get-ADGroup -filter {Name -like "*SEC*"} -Properties Name,Description |
Select-Object Name,Description |
Sort-Object name
Thank you for any replies so far
I had another bash and thought this worked:
$SEC_GROUPS = (get-aduser $_ -properties Memberof).memberof |
Get-ADGroup -filter 'Name -like "*SEC*"' -Properties Name,Description -ErrorAction SilentlyContinue |
select-object Name,Description |
Sort-Object Name
But it pulls all matching AD groups, not just those the user is a member of.
Update: Using the comment from Santiago below was the trick. Remember, for speed I needed to retrieve only the user groups matching the group name pattern I specify, as early as possible, no manually processing on the full groups list.
$SEC_GROUPS = (get-aduser $_ -properties Memberof).memberof -like '*SEC*' |
Get-ADGroup -Properties Name,Description |
select-object Name,Description |
Sort-Object Name
I found that, even when my group names started with SEC I still needed to include the * on both side of the match pattern, using SEC* didn`t work. I'm guessing this is because the match target starts with CN=SEC_whatever
You can use the Active Directory Filter to search for all groups having your user as member and having a name containing SEC. This is as fast as it gets in my opinion.
$user = (Get-ADUser someUser).DistinguishedName
$groups = Get-ADGroup -LDAPFilter "(&(member=$user)(name=*SEC*))" -Properties Description |
Select-Object Name, Description |
Sort-Object Name
If you want to give it a try you can also filter the memberof property of your user including those having a CN (common name) containing SEC (I don't think this will be faster or more robust than before snippet):
$groups = (Get-ADUser someUser -Properties memberOf).memberOf -match '(?<=^CN=).*SEC.*?(?<!\\),' |
Get-ADGroup -Properties Description |
Select-Object Name, Description |
Sort-Object Name

Searching for specific users created less than 30 days

I am trying to create a line of code that will search for a specific user (from a list). My current code below is not working as it doesn't bring back anything when you run it. However, if I remove the whenCreated field it finds something. The user I am testing this with was created yesterday so not sure why it is not being returned. Any help always appreciated.
$startDate = (Get-Date).Date
$endDate = $startDate.AddDays(-30).Date
Get-ADUser -filter {Surname -eq $e -and physicalDeliveryOfficeName -eq $site -and whencreated -ge $enddate} | Select-Object samAccountName -ExpandProperty samAccountName
I would suggest to first get all users created on or after your $enddate and who'se Office property is equal to your variable $site and then eventualy filter those that can be found in your array if last names.
Also, -Filter should be a string, not a scriptblock.
Try
Get-ADUser -Filter "Office -eq '$site' -and Created -ge $enddate" -Properties Office, Created |
Where-Object { $yourListOfLastNames -contains $_.Surname }
If need be, you can pipe through to a Select-Object to obtain only the properties you need for your output.
By default, Get-ADUser outputs objects with these properties:
DistinguishedName, Enabled, GivenName, Name, ObjectClass, ObjectGUID, SamAccountName, SID, Surname, UserPrincipalName
and in this case we've extended that to also have Office (= physicalDeliveryOfficeName) and Created (= whenCreated converted to DateTime)

List properties of users using foreach comment

My goal is to list extended properties of a list of users by Display Name or SamAccountName pulling those names from a Csv. I am using the following script and it works but it either skips names in the Csv or repeats them. If I do one at a time it returns what I need but from the Csv it doesn’t. Csv has one column named Name.
Import-Csv C:\Users\Administrator\Documents\test.txt | Foreach {
Get-ADUser -Filter "DisplayName -eq '$($_.Name)'" -Properties *
} | Select-Object DisplayName, SamAccountName, Title, Department, EmailAddress, ObjectGUID | Sort-Object Displayname | FT
There is nothing wrong with your current code, except for using Import-Csv on a .txt file (test.txt), I would assume this was a typo. I've added an if condition to help you troubleshoot so at least you would know which users where not found.
You should also avoid the use of -Properties *, querying all properties for the users is inefficient and slow.
$properties = #(
'DisplayName'
'SamAccountName'
'Title'
'Department'
'EmailAddress'
'ObjectGUID'
)
Import-Csv C:\Users\Administrator\Documents\test.csv | ForEach-Object {
$adUser = Get-ADUser -Filter "DisplayName -eq '$($_.Name)'" -Properties $properties
if(-not $adUser) {
Write-Warning "'$($_.Name)' could not be found on AD"
return # Go next
}
$adUser
} | Select-Object $properties | Sort-Object Displayname | Format-Table

Trying to input a specific user list for get-aduser

I'm trying to use a list of usernames to perform a simple get-aduser command. It works fine for a single user, but I can't input a file to perform this for a list.
This command works fine for a single user:
get-aduser -identity myusername -properties passwordlastset, passwordneverexpires |
sort name | ft Name, passwordlastset, Passwordneverexpires | out-file c:\PS\Output.txt
This works fine, but rather than use -filter * for all AD or identity pointing to a file, I am completely lost. I have tried doing a get-content and link to a file but I'm just getting into a pickle.
If I have a text file with a list of usernames in, how do I run the above command against that single text file list, rather than all of AD?
As a side query, is there a way that I can perform the above command, but for a specific OU?
If you have a list that isn't an object, either import it to an object or iterate over the values
Try something like:
$Userlist = Get-Content -path 'c:\temp\test.txt'
$Results = $Userlist | ForEach-Object {
Get-aduser -identity $_ -properties passwordlastset, passwordneverexpires
}
$Results | sort name | ft Name, passwordlastset, Passwordneverexpires | out-file c:\PS\Output.txt
This will work as long as you supply valid SamAccountNames in your list
I would do it this way. You can pipe in identity byvalue. You can import the csv later and get objects back.
get-content userlist.txt |
Get-aduser -properties passwordlastset, passwordneverexpires |
sort name |
select Name, passwordlastset, Passwordneverexpires |
export-csv users.csv
# searchbase example
get-aduser -filter 'name -like "j*"' -SearchBase 'OU=People,DC=stackoverflow,DC=com'

How to get AD user that does not have Picture

I am trying to get a list of AD user who does not have picture. I am on QBC.CAN domain and trying to get information from KOBAL domain. The KOBAL domain looks like this KOBAL.COM. There is OU called SALES AND sub OU called NORTHWEST.
My job is the get a list of users with name, title, email, where Picture is not present. thumbnailPhoto is the ldap-display name. I tried few queries but it doesn't give me what I need and keep getting error.
Get-ADUser -Filter * -Server "ADCP12WSDC54X01.KOBAL.COM" -properties thumbnailPhoto | ? {!$_.thumbnailPhoto} | select Name
This code works but I don't need the entire list. I only need OU=SALES,OU=NORTHWEST. If I change the script to following I get an error
Get-ADUser -Filter * -SearchBase "OU=NORTHWEST, OU=SALES ,DC=KOBAL,DC=COM" -properties thumbnailPhoto | ? {!$_.thumbnailPhoto} | select Name
Get-ADUser : The supplied distinguishedName must belong to one of the following
partition(s): 'DC=QBC,DC=CAN , CN=Configuration,DC=QBC,DC=CAN , cN=Schema,CN=Configuration,DC=QBC,DC=CAN , DC=DomainDnsZones,DC=QBC,DC=CAN, DC=ForestDnsZones,DC=QBC,DC=CAN'.
Here's what I would use:
$SearchBase = 'OU=NORTHWEST,OU=SALES,DC=KOBAL,DC=COM';
$LdapServer = 'YourLDAPServerName';
$UsersWithoutPhotos = Get-ADUser -Filter 'thumbnailPhoto -notlike "*"' -SearchBase $SearchBase -SearchScope 'Subtree' -Server $LdapServer | Select-Object 'Name'
The filter here removes the need for piping to a Where-Object. It will return any user in the target OU or below that doesn't have a thumbnailPhoto attribute. You don't need -Properties thumbnailPhoto now since you're not using it for anything anymore, so you won't be returning all that data.
Edit to add:
By default, the only properties returned by Get-ADUser are DistinguishedName, Enabled, GivenName, Name, ObjectClass, ObjectGUID, SamAccountName, SID, Surname, UserPrincipalName. If you want access to anything else, you'll need to include the -Properties parameter again with Get-ADUser to tell that command to fetch that data, too. All the Select-Object command does is eliminate fields that you don't want to see.
This should work for you:
$UsersWithoutPhotos = Get-ADUser -Filter 'thumbnailPhoto -notlike "*"' -SearchBase $SearchBase -SearchScope 'Subtree' -Server $LdapServer -Properties 'title', 'displayName';
You can then restrict it to just the fields you want:
$UsersWithoutPhotos = $UsersWithoutPhotos | Select-Object 'Name','title', 'displayName';
Or sort it by a field:
$UsersWithoutPhotos = $UsersWithoutPhotos | Sort-Object 'displayName';
And display it:
$UsersWithoutPhotos | Format-Table -AutoSize;
Or:
$UsersWithoutPhotos | Out-GridView;
Of course, you can do all that on one line, too, and just keep piping.