pwd last set; all users

I have this function that can find when a single user last changed their pwd:

Function get-pwdset{
Param([parameter(Mandatory=$true)][string]$user)
$use = get-aduser $user -properties passwordlastset,passwordneverexpires
If($use.passwordneverexpires -eq $true)
    {
 write-host $user "last set their password on " $use.passwordlastset  "this account has a non-expiring password" -foregroundcolor yellow
        }
Else
    {
$til = (([datetime]::FromFileTime((get-aduser $user -properties "msDS-UserPasswordExpiryTimeComputed")."msDS-UserPasswordExpiryTimeComputed"))-(get-date)).days
if($til -lt "5")
    {
 write-host $user "last set their password on " $use.passwordlastset "it will expire again in " $til " days" -foregroundcolor red
        }
else
    {
 write-host $user "last set their password on " $use.passwordlastset "it will expire again in " $til " days" -foregroundcolor green
        }
}}

…but wanted to get ALL users last changed PWD so tried this:

$AllUsers= Get-ADUser -Filter * | select samAccountName

…so that after I run the function, I type:

get-pwdset $AllUsers

but get the error “get-pwdset : Cannot process argument transformation on parameter ‘user’”

Which I expected but would like to know what adjustments I need to make to get this output (and dumped to a .csv) please.

Thanks

You need to loop through the user collection, you cannot pass a collection to a cmdlet, or function the way you are doing this.

Your function is only set to ask for one user at a time.

So, ForLoop, something this…

# Collect all AD users then loop and run each user through the function for resultset
(Get-ADUser -Filter * | select samAccountName) | %{get-pwdset -User $_}

# Or 
ForEach ($TargetUser in $AllUsers)
{get-pwdset -User $TargetUser}

both solutions more or less error out with:

@{samAccountName=SomeUser} last set their password on   it will expire again in    days
get-aduser : Cannot find an object with identity: ‘@{samAccountName=SomeOtherUser}’ un

I’ve also tried this script which was pretty slick but have a date:time error. It’s not converting correctly:

Get-ADUser -Filter * -SearchBase "dc=,dc=" -ResultPageSize 0 -Prop CN,samaccountname,lastLogonTimestamp | Select CN,samaccountname,@{n="lastLogonDate";e={[datetime]::FromFileTime  
($_.lastLogonTimestamp)}} | Export-CSV -NoType \

ERROR:

lastLogonDate
static datetime FromFileTime(long fileTime) 
static datetime FromFileTime(long fileTime) 
static datetime FromFileTime(long fileTime) 
static datetime FromFileTime(long fileTime) 
static datetime FromFileTime(long fileTime) 
static datetime FromFileTime(long fileTime) 
static datetime FromFileTime(long fileTime) 131745103348330831
static datetime FromFileTime(long fileTime) 
static datetime FromFileTime(long fileTime) 131745107633992789
static datetime FromFileTime(long fileTime) 
static datetime FromFileTime(long fileTime) 
static datetime FromFileTime(long fileTime) 131744261420866385

Whenever you have issues with attributes from AD, check one of the users with issues what the attributes are set to.

Some attributes are not replicated across DC’s, like lastlogontimestamp vs. lastlogondate.
Some attributes are not set until you actually do X, like reseting the password the first time.
Some attributes are not seen unless you run the command as administrator.
Some attributes have a different stored format, like the date time format is in ticks instead of a date.

Some attributes have a different stored format, like the date time format is in ticks instead of a date.

I hear ya and I’m fairly certain the conversion of those ticks is whats wrong with my last example. I just don’t how to fix it although I think it involves an Expression.

This would be a similar thing with proper DateTime format using the LastLogon property, so no convert is needed

Get-ADUser -Filter {Enabled -eq $true} -Properties CN,samaccountname,LastLogon | 
Select-Object CN,samaccountname,@{n='LastLogon';e={[DateTime]::FromFileTime($_.LastLogon)}}

# Or just
Get-ADUser -Filter * -properties * | Select samAccountName,PasswordLastSet

Well, minus the searchbase, and resutlpagesize

As for the errors. This is odd since it is only asking for the one property value, which is what your function is asking for.

So, this approach outputs what appears to be the expected results.

Function get-pwdset
{
    Param([parameter(Mandatory=$true)][string]$user)

    $use = get-aduser $user -properties passwordlastset,passwordneverexpires

    If($use.passwordneverexpires -eq $true)
    { write-host $user "last set their password on " $use.passwordlastset  "this account has a non-expiring password" -foregroundcolor yellow }
    Else
    {
        $til = (([datetime]::FromFileTime((get-aduser $user -properties "msDS-UserPasswordExpiryTimeComputed")."msDS-UserPasswordExpiryTimeComputed"))-(get-date)).days
        if($til -lt "5")
    { write-host $user "last set their password on " $use.passwordlastset "it will expire again in " $til " days" -foregroundcolor red }
    else
    { write-host $user "last set their password on " $use.passwordlastset "it will expire again in " $til " days" -foregroundcolor green}
    }
}

(Get-ADUser -Filter *).samAccountName | %{get-pwdset -user $_}

# Results

Administrator last set their password on  3/31/2017 2:34:34 PM this account has a non-expiring password
Guest last set their password on   this account has a non-expiring password
krbtgt last set their password on  3/31/2017 8:05:27 PM it will expire again in  -411  days

Usually you can use Get-Date to convert from the different formats.
Or the .Net methods if you prefer that.

Since the numbers above is in FileTime (actually it seems to be in FileTimeUtc).

$x = 131745103348330831

(Get-date $x).AddYears(1600)

The AddYears addition is because Get-Date use ticks which start counting from 1:st of January year 1.
FileTime starts at 1:st of January year 1601.

If there is a lot of iterations it might be worth checking the .Net methods since they are most likely faster than calling Get-Date every time.

Thanks postanote, that’s very handy. How would I also get the write-host to dump the same info to a .csv?

I tried:

(Get-ADUser -Filter *).samAccountName | %{get-pwdset -user $_} | Export-Csv .\PWDLastSet.csv