AD inactive user with OU - powershell

I'd like to get a list of users that haven't used their account in the past 90 days. And I'd like to see in which OU/DC they are without getting the CN. is this possible? I'm using PowerShell ISE for this
I currently have
Search-ADAccount -UsersOnly –AccountInActive –TimeSpan 90:00:00:00
–ResultPageSize 2000 –ResultSetSize $null
| ?{$_.Enabled –eq $True}
| Select-Object Name, SamAccountName, DistinguishedName, LastLogonDate
| Export-CSV “C:\Temp\InActiveUsers.CSV” –NoTypeInformation
This returns the full distinguished name and I have to remove the CN in Excel afterwards, which is an annoying mess - I'd rather not deal with that repeatedly.
The solution doesn't have to be based on search-adaccount, but I do want it to be in a single code, so I don't have to get a list of users and then use that list with another bit of code to get their OU/DC.

You can grab the superior DN by splitting the string on the first non-escaped comma and discard the CN part:
# ...
| Select-Object Name,SamAccountName,#{Name='OU';Expression={($_.DistinguishedName -split '(?<!\\),',2)[1]}}, LastLogonDate

If your domain is running at least Windows 2012, you can ask for the msDS-parentdistname attribute, which will give you the DN of the parent object. It's a constructed attribute, which means it's calculated at the time you ask for it. You have to specifically ask for it, which means in this case I think you'll have to pipe the result into Get-ADUser to do so. That might slow things down quite a bit (there are faster ways to do this) but it should work.
Search-ADAccount -UsersOnly –AccountInActive –TimeSpan 90:00:00:00
–ResultPageSize 2000 –ResultSetSize $null
| ?{$_.Enabled –eq $True}
| Get-AdUser -Properties Name, SamAccountName, "msDS-parentdistname", LastLogonDate
| Select-Object Name, SamAccountName, "msDS-parentdistname", LastLogonDate
| Export-CSV "C:\Temp\InActiveUsers.CSV" –NoTypeInformation

Related

I have a list of Display names that I would like to also display SAM Account Names

I have an application that has never had old users cleaned out of it. I exported all the LastName, FirstName to a .CSV, but would like to have it add the SAM Account Name as well. This is so I know whether the person even still exists in the company. The below script works perfectly, but...if there is no existing SAM name, it doesn't bother to include the display name. I would like to have the field called SamAccountName just put in some text like "To be removed" if there is no matching AD account. I sure it's a simple conditional check, but my PowerShell game is weak.
Import-Csv c:\temp\DisplayName.csv | ForEach {
Get-ADUser -Filter "DisplayName -eq '$($_.DisplayName)'" -Properties Name, SamAccountName, Company |
Select Name, SamAccountName, Company
} | Export-CSV -path C:\temp\SamAccountName.csv -NoTypeInformation
You can use a calculated property for that. That way you pass everything from the original CSV, and just add in the samaccountname you want.
Import-Csv c:\temp\DisplayName.csv | Select *,#{l='samAccountName';e={Get-ADUser -Filter "DisplayName -eq '$($_.DisplayName)'" -Properties Name, SamAccountName, Company | Select -Expand SamAccountName}} | Export-CSV -path C:\temp\SamAccountName.csv -NoTypeInformation

Finding out if the same property occurs on multiple AD users

I'm pretty new on Powershell and this is by far the trickiest task I have gotten so far. I want to write a script that shows me if the same personal identity number occurs on multiple AD users.
I have managed to get a list of all AD users and their ID numbers using the Powershell Active Directory module and the following:
Get-ADUser -Filter * -SearchBase "OU=X,DC=X,DC=X,DC=X" -Properties PersonalIdentityNumber | Select-Object Name,PersonalIdentityNumber | Where-Object {$_.PersonalIdentityNumber} | Sort-Object -Property PersonalIdentityNumber
Although, I am not sure where to go from there. I suspect that I will have to use a for or foreach loop in some way, but I have tested a bit and not made any concluions. It will most likely be too heavy to compare every user against all other users, but I think that every user can be compared to the 20 users before or after, since matching ID numbers will probably be on users with the same name.
Any ideas on how to accomplish this?
Use the Group-Object cmdlet to group the users based on the value of the PersonalIdentityNumber property:
$usersWithPIN = Get-ADUser -Filter * -SearchBase "OU=X,DC=X,DC=X,DC=X" -Properties PersonalIdentityNumber | Select-Object Name,PersonalIdentityNumber | Where-Object {$_.PersonalIdentityNumber}
$usersWithSamePINGroups = $usersWithPIN |Group-Object PersonalIdentityNumber |Where-Object Count -gt 1
$usersWithSamePINGroups will now contain zero or more Group objects with a Count property (the number of users sharing a given PIN), and a Group property containing the user objects in question

Powershell AD user group member

Is there any simple way to just filter user group member like this:
$abcgroup = (Get-ADUser -Identity username –Properties MemberOf) | where {$_.MemberOf -like "*ABC*"}| Select-Object -ExpandProperty MemberOf | FT MemberOf -AutoSize
And return user group just the ABC-XYZ instead of every single group as output, otherwise any easy method to process all the group name and just extract the any group name start with ABC-*
Thanks
I would make it a little bit simpler, both in server and local processing:
Get-ADGroup -LDAPFilter "(&(member=$((Get-ADUser username).distinguishedName))(sAMAccountName=abc-*))"
This would get all the groups that include selected user and their name matches the pattern. This would only include two LDAP requests (one for getting user DN, one for getting all the groups). All the selection will be done on the server and only interesting values will be returned, meaning less data transfer and less post-processing (i.e. filtering) on the client side.
Untested, but this might work:
$abcgroup = (Get-ADUser -Identity username –Properties MemberOf).MemberOf |
Where-Object {$_ -match '^cn=ABC-'} | ForEach-Object {(Get-ADGroup -Identity $_).Name}
$abcgroup | Format-Table

Querying the ManagedBy attribute in PowerShell for AD

I have a small script in powershell written to query user groups in a specific OU in AD to get the name of those groups and to also try and get the ManagedBy attribute of those groups. I've been searching online and here for solutions to why the ManagedBy attribute is not populated results but I have had no luck. Every solution I have found has been written in C# (or another language) and I have tried using the Quest software for AD which doesn't seem to help.
$test = 'OU=example,DC=example,DC=test'
$test | ForEach {Get-ADGroup -Filter * -Properties ManagedBy -SearchBase $_ } | Select Name, Properties | Sort -Property Name | Out-File C:\test.csv
I am only getting results of the name of the groups and empty brackets for the ManagedBy attribute. My question is, is there anyway to query the managedby attribute in powershell without using another language or integrating different plugins? I've never written in C and I would prefer using native powershell if possible.
You've got an error in your Select. Properties should be ManagedBy.
$test = 'OU=example,DC=example,DC=test'
$test | ForEach {Get-ADGroup -Filter * -Properties ManagedBy -SearchBase $_ } |
Select Name, ManagedBy |
Sort -Property Name |
Out-File C:\test.csv

Converting LastLogon to DateTime format

My objective is to get a list of users from my domain with the following info:
-Display name
-Country
-Manager Name
-Last login date
I am running the following script, and everything looks good except for the LastLogon. It outputs the time into a bunch of random numbers like "129948127853609000". How can I convert this to DateTime format?
Search-ADAccount -UsersOnly -SearchBase "OU=International,DC=mycompany,DC=com" -AccountDisabled:$false | Get-ADUser -Properties Name, manager, LastLogon | Select Name, manager, LastLogon | export-csv C:\Australia.csv -NoTypeInformation
DateTime.FromFileTime should do the trick:
PS C:\> [datetime]::FromFileTime(129948127853609000)
Monday, October 15, 2012 3:13:05 PM
Then depending on how you want to format it, check out standard and custom datetime format strings.
PS C:\> [datetime]::FromFileTime(129948127853609000).ToString('d MMMM')
15 October
PS C:\> [datetime]::FromFileTime(129948127853609000).ToString('g')
10/15/2012 3:13 PM
If you want to integrate this into your one-liner, change your select statement to this:
... | Select Name, manager, #{N='LastLogon'; E={[DateTime]::FromFileTime($_.LastLogon)}} | ...
Get-ADUser -Filter {Enabled -eq $true} -Properties Name,Manager,LastLogon |
Select-Object Name,Manager,#{n='LastLogon';e={[DateTime]::FromFileTime($_.LastLogon)}}
LastLogon is the last time that the user logged into whichever domain controller you happen to have been load balanced to at the moment that you ran the GET-ADUser cmdlet, and is not replicated across the domain. You really should use LastLogonTimestamp if you want the time the last user logged in to any domain controller in your domain.
Use the LastLogonDate property and you won't have to convert the date/time.
lastLogonTimestamp should equal to LastLogonDate when converted.
This way, you will get the last logon date and time across the domain without needing to convert the result.
It is important to know that LastLogonDate is not replicated. LastLogonTimestamp is so it is important that you use timestamp on large domains
While lastlogon is not replicated, lastlogontimestamp is. lastlogontimstamp is not human readable (milliseconds since windows epoch)
Here is a one liner that ACTUALLY solves it without querying every server.
get-adcomputer -filter 'operatingsystem -like "server" -and enabled -eq "true"' -prop lastlogontimestamp|select name, lastlogontimestamp, #{N='LastLogon'; E={[DateTime]::FromFileTime($_.LastLogontimestamp)}}