Password Notify script not behaving

deriickmu
deriickmu used Ask the Experts™
on
passwordNotify.vbs is a script I am sure many have seen.  it is located at:

http://www.gelmir.com/index.php?option=com_content&task=view&id=7&Itemid=8

The script runs great... except it only runs through the users that start with "A" whose passwords expired before January 1st!  (We keep user accounts around for compliance reasons).

I pretty much used the script as is from the site listed above, and the instructions seem to be pretty clear that this should return all users whose accounts are either expired or will expire within 14 days.

As a follow up, it appears the script ends with this displayed:

C:\passwordNotify.vbs(156, 2) (null): 0x80005000
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Chris DentPowerShell Developer
Top Expert 2010

Commented:

Would you mind posting the full script you're using? Makes life easier :)

The Null error you're getting will be why it's not going beyond A, it just needs a little error control in there to get by and it's easier to glue that into what you have than assemble the script again from the article concerned.

Chris

Author

Commented:
hERE IT IS:


'==========================================================================
'
' NAME: passwordNotify.vbs
'
' AUTHOR: Eric Aarts
' DATE  : 7/21/2006
'
' COMMENT: Checks the age of the password against the maximum age set in
'               the domain. Sends a out an email to the user based on the age.
'
' VERSION: 1.1
'
' LOG:         1.0 - Initial release
'               1.1 - 9/12/2006
'                Fixed notification for default Windows 2003 settings
'                where .lowPart=0
'
'==========================================================================
Option Explicit

'Check the arguments
If WScript.Arguments.Count <> 5 Then
      WScript.Echo "USAGE:   cscript passwordNotify.vbs <SearchBase> <BindServer> <SendMail> <From Address> <SMTP Server>" & Chr(10) & _
                         "EXAMPLE: cscript passwordNotify.vbs ""DC=mydomain,DC=com"" myDC.mydomain.com TRUE me@mydomain.com smtp.mydomain.com"
      WScript.Quit
End If

Const E_ADS_PROPERTY_NOT_FOUND  = &h8000500D
Const strSubject = "Password Expiration warning."

Call Main

Sub Main
      Dim dblMaxAge
      Dim dtmLastPwdChange
      Dim intTimeInterval,intExpireDays
      Dim objCMD,objADConn,ObjResult
      Dim strDomain, strLDAPServer
      Dim strAttributes,strFilter,strQuery
      Dim strSendMail
      Dim objMessage, strFrom, strTo, strSMTPServer, strBody
      
      strDomain = replace(WScript.Arguments(0),"""","")
      strLDAPServer = WScript.Arguments(1)
      strSendMail = WScript.Arguments(2)
      strFrom = WScript.Arguments(3)
      strSMTPServer = WScript.Arguments(4)
            
      dblMaxAge = getMaxPwdAge(strDomain)

      'Create an AD connection object to query the AD
      Set objADConn = Wscript.CreateObject ("ADODB.Connection")
      objADConn.Provider = "ADsDSOObject"
      
      'Open the Connection Object
      objADConn.Open "Active Directory Provider"
      
      'Create the command object
      Set objCmd  = Wscript.CreateObject ("ADODB.Command")
      objCmd.ActiveConnection = objADConn
      
      'Set Attributes to return
      strAttributes = "distinguishedName,mail"
      'Set the filter to only return enabled account with a know email address that don't have passwords set that will never expire.
      strFilter = "(&(objectClass=User)(objectCategory=person)(mail=*)(!userAccountControl:1.2.840.113556.1.4.803:=2)(!userAccountControl:1.2.840.113556.1.4.803:=65536))"
      'Create the querystring      
      strQuery = "<LDAP://" & strLDAPServer & "/" & strDomain & ">;" & strFilter & ";" & strAttributes & ";subtree"
      'Execute the query
      objCmd.CommandText = strQuery
      Set objResult = objCmd.Execute
      
      'Run through the results
      Do While Not objResult.EOF
            strBody = ""
            strTo = ""
            On Error Resume next
            dtmLastPwdChange = getPwdLastChanged(objResult.fields("distinguishedName"))
            If Err.Number = E_ADS_PROPERTY_NOT_FOUND Then
                WScript.Echo objResult.fields("distinghuishedName") & ": The password has never been set."
            Else
                  On Error goto 0
                intExpireDays = Int(dblMaxAge - Int((Now - dtmLastPwdChange)))
                Select Case intExpireDays
                      Case 0
                            strBody = composeBody("Your password has already expired!",ObjResult.Fields("distinguishedName"))
                      
                      Case 1
                            strBody = composeBody("Your password will expire in " & intExpireDays & " day!",ObjResult.Fields("distinguishedName"))
                      
                      Case 2,3,4,5,6,7
                            strBody = composeBody("Your password will expire in " & intExpireDays & " days.",ObjResult.Fields("distinguishedName"))
                      
                      Case 14
                            strBody = composeBody("Your password will expire in " & intExpireDays & " days.",ObjResult.Fields("distinguishedName"))
                            
                      Case Else
                            If intExpireDays < 0 Then
                                  strBody = composeBody("Your password has already expired!",ObjResult.Fields("distinguishedName"))
                            End if
                End Select
               
                If strBody <> "" Then
                      If UCase(strSendMail="TRUE") Then
                               strTo = ObjResult.Fields("mail")
                              Set objMessage = CreateObject("CDO.Message")
                              objMessage.From = strFrom
                              objMessage.To = strTo
                              objMessage.Subject = strSubject
                              objMessage.Textbody = strBody
                              objMessage.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
                              objMessage.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpserver")= strSMTPServer
                              objMessage.Configuration.Fields.Update
                              objMessage.Fields("urn:schemas:mailheader:return-receipt-to") = strFrom
                              objMessage.Fields.Update
                              objMessage.Send
                              Set objMessage = Nothing
                              WScript.Echo "Mail sent to: " & strTo
                        Else
                              WScript.Echo ObjResult.Fields("distinguishedName") & vbTab & strBody
                        End If
                  End if
            End If
            objResult.MoveNext
      Loop
      'clean up
      objResult.close
      objADConn.Close
      Set objResult = Nothing
      Set objADConn = Nothing
      Set objCMD=Nothing
      
End Sub

Function getPwdLastChanged(strDN)
      Dim objUser
      Set objUser = GetObject("LDAP://" & strDN)
      getPwdLastChanged = objUser.PasswordLastChanged
      Set objUser = Nothing
End Function

Function getMaxPwdAge(strDomain)
      Dim objDomain,objMaxPwdAge
      Set objDomain = GetObject("LDAP://" & strDomain)
      Set objMaxPwdAge = objDomain.Get("maxPwdAge")
      if objMaxPwdAge.lowPart = 0 and objMaxPwdAge.highPart = -2147483648 then
            WScript.Echo "The domain does not have password expiration set."
            WScript.Quit
      End If
      getMaxPwdAge = (Int(Abs(objMaxPwdAge.HighPart * 2^32 + objMaxPwdAge.LowPart) * .000000100)/86400)
      Set objMaxPwdAge = Nothing
End Function

Function composeBody(strWarning,strDN)
      Dim objUser
      Dim strText
      Set objUser = GetObject("LDAP://" & strDN)
      If objUser.givenName <> "" Then
            strText = "Hi " & objUser.givenName & "," & vblf & vblf
      End If
      strText = strText & "We would like to warn you that your password will expire soon, " & _
                    "please follow the instructions later in this message to make sure there will " & _
                    "be no interuption to your network access." & vblf & vblf & _
                    strWarning & vblf & vblf & _
                    "Please go to this website: www.changemypassword.com to change your password."
      Set objUser = Nothing
      composeBody = strText
End Function

      
PowerShell Developer
Top Expert 2010
Commented:

Odd, it works well enough.

The error points to a problem with the Distinguished Name it's being passed for a user on this line in composeBody:

      Set objUser = GetObject("LDAP://" & strDN)

So we need to see what it's trying to connect to before it fails. To do that we'll just need to add a line in (or a line and a comment), and we'll only be interested in the very last line that it shows which should be the Distinguished Name of the User it's about to fail on:


'==========================================================================
'
' NAME: passwordNotify.vbs
'
' AUTHOR: Eric Aarts
' DATE  : 7/21/2006
'
' COMMENT: Checks the age of the password against the maximum age set in
'               the domain. Sends a out an email to the user based on the age.
'
' VERSION: 1.1
'
' LOG:         1.0 - Initial release
'               1.1 - 9/12/2006
'                Fixed notification for default Windows 2003 settings
'                where .lowPart=0
'
'==========================================================================
Option Explicit

'Check the arguments
If WScript.Arguments.Count <> 5 Then
      WScript.Echo "USAGE:   cscript passwordNotify.vbs <SearchBase> <BindServer> <SendMail> <From Address> <SMTP Server>" & Chr(10) & _
                         "EXAMPLE: cscript passwordNotify.vbs ""DC=mydomain,DC=com"" myDC.mydomain.com TRUE me@mydomain.com smtp.mydomain.com"
      WScript.Quit
End If

Const E_ADS_PROPERTY_NOT_FOUND  = &h8000500D
Const strSubject = "Password Expiration warning."

Call Main

Sub Main
      Dim dblMaxAge
      Dim dtmLastPwdChange
      Dim intTimeInterval,intExpireDays
      Dim objCMD,objADConn,ObjResult
      Dim strDomain, strLDAPServer
      Dim strAttributes,strFilter,strQuery
      Dim strSendMail
      Dim objMessage, strFrom, strTo, strSMTPServer, strBody
     
      strDomain = replace(WScript.Arguments(0),"""","")
      strLDAPServer = WScript.Arguments(1)
      strSendMail = WScript.Arguments(2)
      strFrom = WScript.Arguments(3)
      strSMTPServer = WScript.Arguments(4)
           
      dblMaxAge = getMaxPwdAge(strDomain)

      'Create an AD connection object to query the AD
      Set objADConn = Wscript.CreateObject ("ADODB.Connection")
      objADConn.Provider = "ADsDSOObject"
     
      'Open the Connection Object
      objADConn.Open "Active Directory Provider"
     
      'Create the command object
      Set objCmd  = Wscript.CreateObject ("ADODB.Command")
      objCmd.ActiveConnection = objADConn
     
      'Set Attributes to return
      strAttributes = "distinguishedName,mail"
      'Set the filter to only return enabled account with a know email address that don't have passwords set that will never expire.
      strFilter = "(&(objectClass=User)(objectCategory=person)(mail=*)(!userAccountControl:1.2.840.113556.1.4.803:=2)(!userAccountControl:1.2.840.113556.1.4.803:=65536))"
      'Create the querystring      
      strQuery = "<LDAP://" & strLDAPServer & "/" & strDomain & ">;" & strFilter & ";" & strAttributes & ";subtree"
      'Execute the query
      objCmd.CommandText = strQuery
      Set objResult = objCmd.Execute
     
      'Run through the results
      Do While Not objResult.EOF
            strBody = ""
            strTo = ""
            On Error Resume next
            dtmLastPwdChange = getPwdLastChanged(objResult.fields("distinguishedName"))
            If Err.Number = E_ADS_PROPERTY_NOT_FOUND Then
                WScript.Echo objResult.fields("distinghuishedName") & ": The password has never been set."
            Else
                  On Error goto 0
                intExpireDays = Int(dblMaxAge - Int((Now - dtmLastPwdChange)))

            ' Debug Check
            WScript.Echo objResult.Fields("distinguishedName")

                Select Case intExpireDays
                      Case 0
                            strBody = composeBody("Your password has already expired!",ObjResult.Fields("distinguishedName"))
                     
                      Case 1
                            strBody = composeBody("Your password will expire in " & intExpireDays & " day!",ObjResult.Fields("distinguishedName"))
                     
                      Case 2,3,4,5,6,7
                            strBody = composeBody("Your password will expire in " & intExpireDays & " days.",ObjResult.Fields("distinguishedName"))
                     
                      Case 14
                            strBody = composeBody("Your password will expire in " & intExpireDays & " days.",ObjResult.Fields("distinguishedName"))
                           
                      Case Else
                            If intExpireDays < 0 Then
                                  strBody = composeBody("Your password has already expired!",ObjResult.Fields("distinguishedName"))
                            End if
                End Select
               
                If strBody <> "" Then
                      If UCase(strSendMail="TRUE") Then
                              strTo = ObjResult.Fields("mail")
                              Set objMessage = CreateObject("CDO.Message")
                              objMessage.From = strFrom
                              objMessage.To = strTo
                              objMessage.Subject = strSubject
                              objMessage.Textbody = strBody
                              objMessage.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
                              objMessage.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpserver")= strSMTPServer
                              objMessage.Configuration.Fields.Update
                              objMessage.Fields("urn:schemas:mailheader:return-receipt-to") = strFrom
                              objMessage.Fields.Update
                              objMessage.Send
                              Set objMessage = Nothing
                              WScript.Echo "Mail sent to: " & strTo
                        Else
                              WScript.Echo ObjResult.Fields("distinguishedName") & vbTab & strBody
                        End If
                  End if
            End If
            objResult.MoveNext
      Loop
      'clean up
      objResult.close
      objADConn.Close
      Set objResult = Nothing
      Set objADConn = Nothing
      Set objCMD=Nothing
     
End Sub

Function getPwdLastChanged(strDN)
      Dim objUser
      Set objUser = GetObject("LDAP://" & strDN)
      getPwdLastChanged = objUser.PasswordLastChanged
      Set objUser = Nothing
End Function

Function getMaxPwdAge(strDomain)
      Dim objDomain,objMaxPwdAge
      Set objDomain = GetObject("LDAP://" & strDomain)
      Set objMaxPwdAge = objDomain.Get("maxPwdAge")
      if objMaxPwdAge.lowPart = 0 and objMaxPwdAge.highPart = -2147483648 then
            WScript.Echo "The domain does not have password expiration set."
            WScript.Quit
      End If
      getMaxPwdAge = (Int(Abs(objMaxPwdAge.HighPart * 2^32 + objMaxPwdAge.LowPart) * .000000100)/86400)
      Set objMaxPwdAge = Nothing
End Function

Function composeBody(strWarning,strDN)
      Dim objUser
      Dim strText
      Set objUser = GetObject("LDAP://" & strDN)
      If objUser.givenName <> "" Then
            strText = "Hi " & objUser.givenName & "," & vblf & vblf
      End If
      strText = strText & "We would like to warn you that your password will expire soon, " & _
                    "please follow the instructions later in this message to make sure there will " & _
                    "be no interuption to your network access." & vblf & vblf & _
                    strWarning & vblf & vblf & _
                    "Please go to this website: www.changemypassword.com to change your password."
      Set objUser = Nothing
      composeBody = strText
End Function
Exploring SQL Server 2016: Fundamentals

Learn the fundamentals of Microsoft SQL Server, a relational database management system that stores and retrieves data when requested by other software applications.

Author

Commented:
OK, that resulted in a stop at a user, and a new error:

C:\passwordNotify.vbs(160, 7) (null): 0x80005000

Author

Commented:
AHA!!

The script does not like OUs with slashes in the name.  I removed all slashed from my OUs and now it runs perfectly!  Thanks for helping track this down!
Chris DentPowerShell Developer
Top Expert 2010

Commented:

That'd do it :)

Glad you have it sorted out :)

Chris

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial