Query user accounts that will expire by certain date or via Get-Date?

This topic contains 15 replies, has 3 voices, and was last updated by  Mike 3 months ago.

  • Author
    Posts
  • #94099

    Mike
    Participant

    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
        } 
    }
  • #94101

    Mike
    Participant

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

  • #94107

    Don Jones
    Keymaster

    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?

  • #94117

    Mike
    Participant

    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 :).

  • #94119

    Don Jones
    Keymaster

    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.

  • #94120

    Mike
    Participant

    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
        } 
    }
    
  • #94122

    Mike
    Participant

    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
        } 
    }
    
  • #94125

    Olaf Soyk
    Participant

    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.

  • #94131

    Mike
    Participant

    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'))
  • #94134

    Olaf Soyk
    Participant

    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.

  • #94137

    Olaf Soyk
    Participant
    $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.

  • #94138

    Mike
    Participant

    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?

  • #94140

    Mike
    Participant

    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.

    • #94146

      Olaf Soyk
      Participant

      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? 😀

  • #94354

    Mike
    Participant

    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

  • #94357

    Mike
    Participant

    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.

You must be logged in to reply to this topic.