It has been a while since I have updated my blog, mainly because I was away to Vegas, followed by Nepal, and mainly due to the fact that I haven't had to do anything special for a while, just mundane administrative tasks.
There was a request to see if we can come up with some solution to the Windows 7 password prompt which many of our users seem to miss, and even when they don't miss the actual prompt, the fact that it almost never comes back makes people forget about it. Unlike the previous version of Windows which repeatedly prompted you for a password change when your password was nearing expiration, Windows 7 (and 8 from what I can tell) don't seem to do as good of a job.
I looked online to see if there was something in group policies which we could adjust, but it appears that there isn't, and based on my research, this is a common problem that many admins seem to experience yet not real good solution in place. It seems that at the end of the day, a solution needed to be crafted, which lead me to this post by Mark-K on TechNet. Mark-K posted a script that he has created (I believe so at least) which did the job. The script would run against your user account and the AD, verify how long there is before the password expires, and if it is within a specified period, prompt the user with the instructions on how to change it.
Now, I am not a big fan of scripts and doing things the OS should do itself, but after much looking around, this did seem like the best solution. I was set on using the script in it's entirety when I realized that I really did not like the way the script looked, as the popup window also brought up the taskbar icon for Windows Scripting Host, which didn't really seem like a complete product for a perfectionist like myself.
This is what the script looked like initially (normally pops up in the middle, but I moved it down to capture everything in one shot):
The above screenshot also shows the script running with a 90 days notification set, so that I can see the script output during testing.
I decided that I wanted the script to run as an executable instead, so I converted the script in its entirety to exe using ScriptCryptor and added an icon which, in my opinion, make it look a lot more professional and complete.
It's a very small change, but the file is now an exe file with the proper icon, vs. a .vbs file with the default windows icon for scripting host.
To make the whole thing run at the end of the day, I created a new users GPO which creates a scheduled task that will run daily at a predefined time. If the user's password is not within the predefined expiration window, the user will not see any prompts at all as the program runs in the background, but as soon as the program evaluates the password expiry condition as true, the prompt will pop up, and continue to do so on the interval defined in the scheduled task until the user changes their password. I placed the executable in the scripts directory on the SYSVOL so that it is accessible by everyone on the domain.
I have precompiled a bunch of different versions of the executable with different warning periods preset if anyone is interested (download links below), otherwise you can use the script below and adjust it as you see fit, and recompile it with ScriptCryptor (not freeware) to get the same results. In addition, if you want the popup box to always stay on top, you can simply change this portion of the script "Change a password' option.", 0, "Password Expiration Warning" to this "Change a password' option.", 262144, "Password Expiration Warning"
' Check for password expiring notification
' First, get the domain policy.
warningDays = 90
Set LoginInfo = CreateObject("ADSystemInfo")
Set objUser = GetObject("LDAP://" & LoginInfo.UserName & "")
strDomainDN = UCase(LoginInfo.DomainDNSName)
strUserDN = LoginInfo.UserName
' Check if password is non-expiring.
Const ADS_UF_DONT_EXPIRE_PASSWD = &h10000
intUserAccountControl = objUser.Get("userAccountControl")
If intUserAccountControl And ADS_UF_DONT_EXPIRE_PASSWD Then
'WScript.Echo "The password does not expire."
Set oDomain = GetObject("LDAP://" & strDomainDN)
Set maxPwdAge = oDomain.Get("maxPwdAge")
' Calculate the number of days that are
' held in this value.
numDays = CCur((maxPwdAge.HighPart * 2 ^ 32) + _
maxPwdAge.LowPart) / CCur(-864000000000)
'WScript.Echo "Maximum Password Age: " & numDays
' Determine the last time that the user
' changed his or her password.
Set oUser = GetObject("LDAP://" & strUserDN)
' Add the number of days to the last time
' the password was set.
whenPasswordExpires = DateAdd("d", numDays, oUser.PasswordLastChanged)
fromDate = Date
daysLeft = DateDiff("d",fromDate,whenPasswordExpires)
'WScript.Echo "Password Last Changed: " & oUser.PasswordLastChanged
if (daysLeft < warningDays) and (daysLeft > -1) then
Msgbox "Your password will expire in " & daysLeft & " day(s)" & " at " & whenPasswordExpires & chr(13) & chr(13) & "Press CTRL + ALT + DEL and select the 'Change a password' option.", 0, "Password Expiration Warning"
' Clean up.
Set oUser = Nothing
Set maxPwdAge = Nothing
Set oDomain = Nothing
Download links (select the one that matches the number of days you want before warning the user):
1 2 3 4 5 6 7 14 21 30 90