Author Posts

February 19, 2018 at 10:09 pm

Been working this for a few days, and I tried a TON of different variations of what I'm about to post. For some reason, I just can't get it to pull JUST the users that match the specified expiring date. I tried putting Where-Object within the variable, calling the IF statement with [datetime], using Get-Date with .AddDays, specifying dates, using the full date/time and different date formats, taking out the pscustomobject table and just using Select, etc. No matter what, I cannot just specify a specific date to pull.

I feel like this is such an easy fix and I'm over-complicating it in my head.

$User_Passwords_Expiring = Get-ADUser -Filter {Enabled -eq $True -and PasswordNeverExpires -eq $False} -Properties "msDS-UserPasswordExpiryTimeComputed" | Select Name,
@{Name='ExpiringDate' ;expression={[datetime]::FromFileTime($_."msDS-UserPasswordExpiryTimeComputed")}}

        FOREACH ($User in $User_Passwords_Expiring) {
            
            IF ($User_Passwords_Expiring.ExpiringDate -like 'March 31, 2018' -or '3/31/2018') {
                    
                                        $Object = [pscustomobject] @{
                                                  'Username'=$User_Passwords_Expiring.Name
                                                  'Expiring'=$User_Passwords_Expiring.ExpiringDate.Where({$_DaysToExpire -ge (Get-Date).AddDays(40).Date -or (Get-Date).AddDays(40).ToString('M/dd/yyyy')})
                                                }

                Write-Output $Object
    } 
}

February 19, 2018 at 10:16 pm

Also, if you are wondering... yes. There is a test user on my test DC that has an expiration date of 3/31/2018.

February 19, 2018 at 10:19 pm

You should avoid posting the first reply to your own post. It removes you from the "posts with no replies" list, which many of us use to find posts needing help.

Try running just the Get-ADUser portion of your script – the top line, there, but without the Select-Object part. Run the results to Get-Member. What is the data type of msDS-UserPasswordExpiryTimeComputed?

Now, running it again with your Select put back, what is the data type of ExpiringDate?

February 19, 2018 at 10:31 pm

Looks like without Select-Object, it's a property/System.Int64.

With Select-Object, it's a NoteProperty/System.DateTime.

Originally, "msDS-UserPasswordExpiryTimeComputed" is a non-human readable integer. I'm using Select to create a has table and an expression to change it over to a human readable object with [datetime]::

Also, if possible.. not really looking for the full answer. Just a nudge in the right direction :).

February 19, 2018 at 10:40 pm

OK. So your comparison against ExpiringDate also needs to be a DateTime object. And -like won't work; that's only for String comparisons. You can use -eq, -ne, -gt, -lt, and their friends.

Also, bear in mind that:

$User_Passwords_Expiring.ExpiringDate -like 'March 31, 2018' -or '3/31/2018'

Is not a useful comparison. The second argument being given to -or is not Boolean, so PowerShell is just going to try and cast it as $True, which makes it pointless. -or is meant to be preceded and followed by a complete Boolean expression, such as another comparison. You perhaps meant:

$User_Passwords_Expiring.ExpiringDate -like 'March 31, 2018' -or $User_Passwords_Expiring.ExpiringDate -eq '3/31/2018'

Another maybe-problem you've got is the way you've used -like. Because you've not specified any wildcards, it will behave the same as -eq. That is perhaps what you want, but it's good to be clear.

February 19, 2018 at 11:18 pm

Okay great, thanks. A few notes;

1) Thanks for the tip with -like. I thought that could be used for integers as well.

2) I changed it up to use -eq instead of -like.

3) As for the -or statement not being boolean, I ended up adding or in because it would show zero output if I didn't. If I just had one or the other in (meaning the full date or the M/dd/yyy format) there would be zero output. I took your advice and changed it up a bit. I used $User_Passwords_Expiring.ExpiringDate -eq (Get-Date).AddDays(40).Date.DateTime -or $User_Passwords_Expiring.ExpiringDate -eq (Get-Date).AddDays(40).ToString('M/dd/yyyy') instead so I could utilize the .DateTime object.

4) Yes. I'm looking to specify specific dates, or 40 days in advance for testing purposes.

I changed things around a bit, but it doesn't seem to working. Is this more of what you wanted to see via your explanation?

$User_Passwords_Expiring = Get-ADUser -Filter {Enabled -eq $True -and PasswordNeverExpires -eq $False} -Properties "msDS-UserPasswordExpiryTimeComputed" | Select Name,
@{Name='ExpiringDate' ;expression={[datetime]::FromFileTime($_."msDS-UserPasswordExpiryTimeComputed")}}

        FOREACH ($User in $User_Passwords_Expiring) {
            
            IF ($User_Passwords_Expiring.ExpiringDate -eq (Get-Date).AddDays(40).Date.DateTime -or $User_Passwords_Expiring.ExpiringDate -eq (Get-Date).AddDays(40).ToString('M/dd/yyyy')) {
                    
                                        $Object = [pscustomobject] @{
                                                  'Username'=$User_Passwords_Expiring.Name
                                                  'Expiring'=$User_Passwords_Expiring.ExpiringDate
                                                }

                Write-Output $Object
    } 
}

February 19, 2018 at 11:43 pm

This variation gives me output, but gives me all users. Not just users 40 days from now. I ensured I used (Get-Date).AddDays(40).DateTime as I needed a DateTime object for that specific member.

$User_Passwords_Expiring = Get-ADUser -Filter {Enabled -eq $True -and PasswordNeverExpires -eq $False} -Properties "msDS-UserPasswordExpiryTimeComputed" | Select Name,
@{Name='ExpiringDate' ;expression={[datetime]::FromFileTime($_."msDS-UserPasswordExpiryTimeComputed")}}

        FOREACH ($User in $User_Passwords_Expiring) {
            
            IF ($User_Passwords_Expiring.ExpiringDate -eq (Get-Date).AddDays(40).DateTime -or (Get-Date).AddDays(40).ToString('M/dd/yyyy')) {
                    
                                        $Object = [pscustomobject] @{
                                                  'Username'=$User_Passwords_Expiring.Name
                                                  'Expiring'=$User_Passwords_Expiring.ExpiringDate
                                                }

                Write-Output $Object
    } 
}

February 20, 2018 at 12:34 am

If you use your code like this you have a DateTime object with a date and time in it. So if you like to compare this it would have to be exactly the same date and time. That's pretty much impossible I think. You could use only the day date to compare like this:

$User_Passwords_Expiring = Get-ADUser -Filter {Enabled -eq $True -and PasswordNeverExpires -eq $False} -Properties 'msDS-UserPasswordExpiryTimeComputed' | 
    Select-Object Name,@{Name='ExpiringDate' ;expression={([datetime]::FromFileTime($_."msDS-UserPasswordExpiryTimeComputed")).Date}}
foreach ($User in $User_Passwords_Expiring) {
    IF ($User_Passwords_Expiring.ExpiringDate -eq (Get-Date).AddDays(40).Date) {
        $Object = [pscustomobject] @{
            'Username'=$User_Passwords_Expiring.Name
            'Expiring'=$User_Passwords_Expiring.ExpiringDate
        }
        Write-Output $Object
    }
}

If you like to combine to expressions with an -or you should do it like this:

IF ($User_Passwords_Expiring.ExpiringDate -eq (Get-Date).AddDays(40).Date -or $User_Passwords_Expiring.ExpiringDate -eq (Get-Date).AddDays(41).Date ).....

This way you're checking for 40 days or 41 days.

February 20, 2018 at 12:46 am

Olaf,

Thank you. I know it seems strange to use both, but if I don't call for both in my IF statement, I get no results at all.

As far as comparisons, I'm not necessarily looking for them to be the same. I'm just looking for the output of users and their passwords that are expiring in 40 days. Because AD holds the info in a Int64 format, it holds the data as such.

The odd part is, if I use -or the way you and Don said, I get zero out. The only way it works is if I use it like this;

($User_Passwords_Expiring.ExpiringDate -eq (Get-Date).AddDays(40).Date.DateTime -or (Get-Date).AddDays(40).ToString('M/dd/yyyy'))

February 20, 2018 at 12:50 am

The odd part is, if I use -or the way you and Don said, I get zero out.

Because it is not equal. When you do it like you do it it will always be true no matter what expiring date the user has.
Try do output the dates to the console and calculate it by hand to check.

February 20, 2018 at 1:06 am

$User_Passwords_Expiring = Get-ADUser -Filter {Enabled -eq $True -and PasswordNeverExpires -eq $False} -Properties 'msDS-UserPasswordExpiryTimeComputed' | 
    Select-Object Name,@{Name='ExpiringDate' ;expression={([datetime]::FromFileTime($_."msDS-UserPasswordExpiryTimeComputed")).Date}}
foreach ($User in $User_Passwords_Expiring) {
    IF ($User_Passwords_Expiring.ExpiringDate -gt (Get-Date).AddDays(30).Date -and $User_Passwords_Expiring.ExpiringDate -lt (Get-Date).AddDays(50).Date) {
        $Object = [pscustomobject] @{
            'Username'=$User_Passwords_Expiring.Name
            'Expiring'=$User_Passwords_Expiring.ExpiringDate
        }
        Write-Output $Object
    }
}

This way you catch users with the expiring date between 30 and 50 days in the future.

February 20, 2018 at 1:30 am

So essentially there's no way to just specify a specific day? For example, all of the users that are expiring in exactly 30 days? You have to have a -gt and -lt for this type of syntax to work?

February 20, 2018 at 1:42 am

Even with that logic, I'm still getting the incorrect outcome. I have two test users. One expiring on 3/31/2018, and the other expiring on 4/2/2018. 4/2/2018 is 42 days away. So essentially, if I have my -gt at 39 days and my -lt at 41 days, the user expiring on 4/2/2018 shouldn't come up. However, they still do.

February 20, 2018 at 3:02 am

So essentially there's no way to just specify a specific day?

There's always a way. 😉
I only payed attention to your problem with the comparison and so I missed the other problem in your code ... shame on me ... sorry.

$User_Passwords_Expiring = Get-ADUser -Filter {Enabled -eq $True -and PasswordNeverExpires -eq $False} -Properties 'msDS-UserPasswordExpiryTimeComputed' | 
    Select-Object Name,@{Name='ExpiringDate' ;expression={([datetime]::FromFileTime($_."msDS-UserPasswordExpiryTimeComputed")).Date}}
foreach ($User in $User_Passwords_Expiring) {
    IF ($User.ExpiringDate -gt (Get-Date).AddDays(30).Date -and $User.ExpiringDate -lt (Get-Date).AddDays(50).Date) {
        $Object = [pscustomobject] @{
            'Username' = $User.Name
            'Expiring' = $User.ExpiringDate
        }
        Write-Output $Object
    }
}

What do you say now? 😀

February 21, 2018 at 5:17 pm

NO WAY. So the problem was using $User_Passwords_Expiring.ExpiringDate instead of $User.ExpiringDate? Man.... what a dumb mistake on my part.

I mean, I get it... but to a certain point. I understand that $User is calling each user, one at a time, in $User_Passwords_Expiring, but why wouldn't $User_Passwords_Expiring.ExpiringDate work if I'm still calling the (Get-Date).AddDays(39).Date against the entire list in $User_Passwords_Expiring.ExpiringDate

February 21, 2018 at 5:21 pm

Never mind, I essentially get it. $User_Passwords_Expiring is calling ALL of the objects, even though I'm only specifying a few with Get-Date. So the $User calls it one by one.

Man, for as much as I write code... I feel like such a noob right now! Hopefully others have been in the same boat so I feel a bit better, lol.