How can I get password expiration dates for all users?

0
12
Asked By TechyBunny32 On

I'm trying to generate a report that lists the password expiration dates for all our users, but I've hit a snag with the PowerShell script my coworker started. We have both Windows 10 and Windows 11 users, and they follow different password policies. I need to pull this data using Active Directory. Here's the code I'm working with:

```powershell
# Define the domain you want to query
$Domain = "mycompany.com" # Replace with your domain name or domain controller FQDN

# Define LDAP filter
$Filter = "(&(objectCategory=person)(objectClass=user)(employeeID=*)(!(userAccountControl:1.2.840.113556.1.4.803:=65536)))"

# Array to hold employees
$Employees = @()

Write-Host "Getting all employees from $Domain"

try {
# Pull users from the specified domain
$Employees += Get-ADUser -LDAPFilter $Filter -Properties pwdLastSet, mail -Server $Domain | Select-Object -Property *,
@{N = 'Domain'; E = { $Domain } },
@{N = 'PasswordLastSet'; E = { [DateTime]::FromFileTimeUtc($_.pwdLastSet) } },
@{N = 'DaysTilExpiry'; E = {
$Policy = Get-ADUserResultantPasswordPolicy -Identity $_.UserPrincipalName
if ( $null -eq $Policy ) {
89 - ((Get-date) - (Get-Date -Date ([DateTime]::FromFileTimeUtc($_.pwdLastSet)))).Days
} else {
($Policy.MaxPasswordAge.TotalDays - 1) - ((Get-date) - (Get-Date -Date ([DateTime]::FromFileTimeUtc($_.pwdLastSet)))).Days
}
}}
# THIS IS WHERE WE ARE STUCK - HOW DO WE GET THE PROPERTIES LISTED BELOW?
# Create custom object
$EmployeeObj = [PSCustomObject]@{
UserPrincipalName = $Employee.UserPrincipalName
Mail = $Employee.mail
Domain = $Domain
PasswordLastSet = $PwdLastSetDate
DaysTilExpiry = $DaysTilExpiry
}

# Add to array
$Employees += $EmployeeObj
}
catch {
Write-Warning "Failed to get users from $Domain"
}

# Export to CSV
$Employees | Export-Csv -Path "some path.csv" -NoTypeInformation
Write-Host "Report exported to some pathPasswordExpiryReport.csv"
```
Any advice on how to resolve this would be greatly appreciated!

4 Answers

Answered By ScriptMaster3000 On

You're already using Select-Object, which generates a custom object. The extra object creation is unnecessary since you already have your data! Check out this revised version of your script that should work:

```powershell
#Requires -Modules ActiveDirectory
$Domain = "mycompany.com"
$Filter = "(&(objectCategory=person)(objectClass=user)(employeeID=*)(!(userAccountControl:1.2.840.113556.1.4.803:=65536)))"

Write-Host "Getting all employees from $Domain"
if (-not (Test-Path "C:Temp")) {
New-Item -Path "C:Temp" -ItemType Directory -Force | Out-Null
}
try {
$DefaultPolicy = Get-ADDefaultDomainPasswordPolicy -Server $Domain
$Employees = Get-ADUser -LDAPFilter $Filter -Properties pwdLastSet, mail -Server $Domain | ForEach-Object {
$Policy = Get-ADUserResultantPasswordPolicy -Identity $_.DistinguishedName -Server $Domain -ErrorAction SilentlyContinue
$PwdLastSetDate = [DateTime]::FromFileTimeUtc($_.pwdLastSet)
# Further processing for $MaxAge, $DaysTilExpiry, etc.
[PSCustomObject]@{
UserPrincipalName = $_.UserPrincipalName
Mail = $_.mail
Domain = $Domain
PasswordLastSet = $PwdLastSetDate
DaysTilExpiry = $DaysTilExpiry
}
}
$Employees | Export-Csv -Path "C:TempPasswordExpiryReport.csv" -NoTypeInformation
Write-Host "Report exported successfully to C:TempPasswordExpiryReport.csv"
}
catch {
Write-Warning "Failed to get users from $Domain : $_"
}
```
Try this out tomorrow and let me know how it goes!

CuriousCoder -

Thanks for the helpful tips! I'm going to put this to the test.

Answered By CodeNinja77 On

You're definitely making this more complicated than it needs to be! You can simplify things significantly with a direct command:

```powershell
Get-ADUser -Filter {Enabled -eq $True -and PasswordNeverExpires -eq $False} -Properties DisplayName, msDS-UserPasswordExpiryTimeComputed | Select-Object -Property DisplayName, samaccountname, @{Name="PasswordExpirationDate";Expression={[datetime]::FromFileTime($_."msDS-UserPasswordExpiryTimeComputed")}}
```
This will get you the expiration dates directly without the extra fuss!

QuickFix99 -

I agree! I haven't tested this exact version, but I have something similar that works well and gives accurate results. Simple is usually better!

StraightTalker5 -

This approach is spot on!

Answered By ScriptingWhiz On

I’d say maybe consider using a tool like ChatGPT for help, but I've found it has its limitations with PowerShell scripts.

Answered By DataWiz84 On

Using the PasswordExpirationDate property directly could streamline your code further!

Related Questions

LEAVE A REPLY

Please enter your comment!
Please enter your name here

This site uses Akismet to reduce spam. Learn how your comment data is processed.