Jump to content

Recommended Posts

Sry, by the time you posted, I had already left work for a beer :-D

To be honest, I never tried your first solution in isolation, as by the time I read it you had posted the full function. I did try it in conjuction with the full function, ie replace the full function, try it - replace the line (object=computer) and try it, then finally copy the function into my script etc

Sounds like you have a plan, but if you want me to try the single line replacement, let me know.

I really do appreciate all your efforts, but don't sweat it too much. I can work without this (I can run a DSQUERY to a txt file and then strip out the names from there, it's quite easy) and don't want to cause you unnecessary work. As I have several domains to identify stale machines on a daily basis from one machine, I was just trying to do the entire thing without writing text files, but it really isn't a big deal.

Anyway, I hope you had a good beer, you deserve it.

[font='Comic Sans MS']Eagles may soar high but weasels dont get sucked into jet engines[/font]

Link to post
Share on other sites
  • Replies 48
  • Created
  • Last Reply

Top Posters In This Topic

Top Posters In This Topic

Hi shornw,

I have replaced the I posted previously. This works for me now and returns a lot of machines. Can you please give it a try and post how it works?

Thanks

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2022-02-19 - Version 1.6.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download
Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki
PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki
Task Scheduler (2019-12-03 - Version 1.5.1.0) - Download - General Help & Support - Wiki

Standard UDFs:
Excel - Example Scripts - Wiki
Word - Wiki

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Link to post
Share on other sites

Hi Water,

I have copied the new function and I still get the same -

run without options it returns @error of 0 and a list of user accounts

run with options (I assumed the same options you suggested for 20 days, @error of 1 and nothing further.

Just to confirm, looking at the function, the main difference is "$oAD_Command.CommandText" section.

[font='Comic Sans MS']Eagles may soar high but weasels dont get sucked into jet engines[/font]

Link to post
Share on other sites

Could you please run this modified version and post the results?

There are just two additional ConsoleWrite statements so we know how the LDAP query looks like and how many records are returned.

Func _AD_GetPasswordExpired($sAD_Root = "", $bAD_NeverChanged = False, $iAD_PasswordAge = 0, $bAD_Computer = False)

    If $sAD_Root = "" Then
        $sAD_Root = $sAD_DNSDomain
    Else
        If _AD_ObjectExists($sAD_Root, "distinguishedName") = 0 Then Return SetError(2, 0, "")
    EndIf
    If $iAD_PasswordAge <> 0 And Not IsNumber($iAD_PasswordAge) Then Return SetError(3, 0, "")
    Local $aAD_Temp = _AD_GetPasswordInfo()
    Local $sAD_DTExpire = _Date_Time_GetSystemTime() ; Get current date/time
    $sAD_DTExpire = _Date_Time_SystemTimeToDateTimeStr($sAD_DTExpire, 1) ; convert to system time
    If $iAD_PasswordAge <> 0 Then
        $sAD_DTExpire = _DateAdd("D", $iAD_PasswordAge * - 1, $sAD_DTExpire) ; substract maximum password age
    Else
        $sAD_DTExpire = _DateAdd("D", $aAD_Temp[1] * - 1, $sAD_DTExpire) ; substract maximum password age
    EndIf
    Local $iAD_DTExpire = _DateDiff("s", "1601/01/01 00:00:00", $sAD_DTExpire) * 10000000 ; convert to Integer8
    Local $sAD_DTStruct = DllStructCreate("dword low;dword high")
    Local $sAD_Temp, $iAD_Temp, $iAD_LowerDate = 110133216000000001 ; 110133216000000001 = 01/01/1959 00:00:00 UTC
    If $bAD_NeverChanged = True Then $iAD_LowerDate = 0
    Local $sAD_Category = "(objectCategory=Person)(objectClass=User)"
    If $bAD_Computer = True Then $sAD_Category = "(objectCategory=computer)"
    $oAD_Command.CommandText = "<LDAP://" & $sAD_HostServer & "/" & $sAD_Root & ">;(&" & $sAD_Category & _
        "(pwdLastSet<=" & Int($iAD_DTExpire) & ")(pwdLastSet>=" & $iAD_LowerDate & "));distinguishedName,pwdlastset,useraccountcontrol;subtree"
ConsoleWrite($oAD_Command.CommandText & @CRLF)
    Local $oAD_RecordSet = $oAD_Command.Execute
    If Not IsObj($oAD_RecordSet) Or $oAD_RecordSet.RecordCount = 0 Then Return SetError(1, 0, "")
ConsoleWrite("Records: " & $oAD_RecordSet.RecordCount & @CRLF)
    Local $aAD_FQDN[$oAD_RecordSet.RecordCount + 1][3]
    $aAD_FQDN[0][0] = $oAD_RecordSet.RecordCount
    Local $iAD_Count = 1
    While Not $oAD_RecordSet.EOF
        $aAD_FQDN[$iAD_Count][0] = $oAD_RecordSet.Fields(0).Value
        $iAD_Temp = $oAD_RecordSet.Fields(1).Value
        If BitAND($oAD_RecordSet.Fields(2).Value, $ADS_UF_DONT_EXPIRE_PASSWD) <> $ADS_UF_DONT_EXPIRE_PASSWD Then
            DllStructSetData($sAD_DTStruct, "Low", $iAD_Temp.LowPart)
            DllStructSetData($sAD_DTStruct, "High", $iAD_Temp.HighPart)
            $sAD_Temp = _Date_Time_FileTimeToSystemTime(DllStructGetPtr($sAD_DTStruct))
            $aAD_FQDN[$iAD_Count][1] = _Date_Time_SystemTimeToDateTimeStr($sAD_Temp, 1)
            $sAD_Temp = _Date_Time_SystemTimeToTzSpecificLocalTime(DllStructGetPtr($sAD_Temp))
            $aAD_FQDN[$iAD_Count][2] = _Date_Time_SystemTimeToDateTimeStr($sAD_Temp, 1)
        EndIf
        $iAD_Count += 1
        $oAD_RecordSet.MoveNext
    WEnd
    ; Delete records with UAC set to password not expire
    $aAD_FQDN[0][0] = UBound($aAD_FQDN) - 1
    For $iAD_Count = $aAD_FQDN[0][0] To 1 Step -1
        If $aAD_FQDN[$iAD_Count][1] = "" Then _ArrayDelete($aAD_FQDN, $iAD_Count)
    Next
    $aAD_FQDN[0][0] = UBound($aAD_FQDN) - 1
    Return $aAD_FQDN

EndFunc   ;==>_AD_GetPasswordExpired
Edited by water

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2022-02-19 - Version 1.6.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download
Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki
PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki
Task Scheduler (2019-12-03 - Version 1.5.1.0) - Download - General Help & Support - Wiki

Standard UDFs:
Excel - Example Scripts - Wiki
Word - Wiki

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Link to post
Share on other sites

Once again, if I run _AD_GetPasswordExpired() I get @error 0 and a list of users but _AD_GetPasswordExpired("", False, 20, True) returns @error 1 and nothing more.

I don't know if anyone else reading this post want to try this and post results. That way we can identify whether it's an issue with my local environment or not.

Water - I'm feeling guilty now that you are spending so much time on this!

[font='Comic Sans MS']Eagles may soar high but weasels dont get sucked into jet engines[/font]

Link to post
Share on other sites

What do you get from the two ConsoleWrite statements?

I get:

<LDAP://Servername.domain.TLD/DC=Domain,DC=TLD>;(&(objectCategory=computer)(pwdLastSet<=129641065730000001)(pwdLastSet>=110133216000000001));distinguishedName,pwdlastset,useraccountcontrol;subtree
Records: 889
Edited by water

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2022-02-19 - Version 1.6.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download
Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki
PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki
Task Scheduler (2019-12-03 - Version 1.5.1.0) - Download - General Help & Support - Wiki

Standard UDFs:
Excel - Example Scripts - Wiki
Word - Wiki

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Link to post
Share on other sites

Do you compile the script and run the exe or do you run the script from SciTe by pressing F5?

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2022-02-19 - Version 1.6.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download
Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki
PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki
Task Scheduler (2019-12-03 - Version 1.5.1.0) - Download - General Help & Support - Wiki

Standard UDFs:
Excel - Example Scripts - Wiki
Word - Wiki

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Link to post
Share on other sites

Something else must be wrong with the UDF :D

Can you please run this script from SciTe:

#include <ad.au3>
#include <array.au3>
_AD_Open()
Global $aResult = _AD_GetPasswordExpiredEx("", False, 20, True)
_AD_Close()

Func _AD_GetPasswordExpiredEx($sAD_Root = "", $bAD_NeverChanged = False, $iAD_PasswordAge = 0, $bAD_Computer = False)

    If $sAD_Root = "" Then
        $sAD_Root = $sAD_DNSDomain
    Else
        If _AD_ObjectExists($sAD_Root, "distinguishedName") = 0 Then Return SetError(2, 0, "")
    EndIf
    If $iAD_PasswordAge <> 0 And Not IsNumber($iAD_PasswordAge) Then Return SetError(3, 0, "")
    Local $aAD_Temp = _AD_GetPasswordInfo()
    Local $sAD_DTExpire = _Date_Time_GetSystemTime() ; Get current date/time
    $sAD_DTExpire = _Date_Time_SystemTimeToDateTimeStr($sAD_DTExpire, 1) ; convert to system time
    If $iAD_PasswordAge <> 0 Then
        $sAD_DTExpire = _DateAdd("D", $iAD_PasswordAge * - 1, $sAD_DTExpire) ; substract maximum password age
    Else
        $sAD_DTExpire = _DateAdd("D", $aAD_Temp[1] * - 1, $sAD_DTExpire) ; substract maximum password age
    EndIf
    Local $iAD_DTExpire = _DateDiff("s", "1601/01/01 00:00:00", $sAD_DTExpire) * 10000000 ; convert to Integer8
    Local $sAD_DTStruct = DllStructCreate("dword low;dword high")
    Local $sAD_Temp, $iAD_Temp, $iAD_LowerDate = 110133216000000001 ; 110133216000000001 = 01/01/1959 00:00:00 UTC
    If $bAD_NeverChanged = True Then $iAD_LowerDate = 0
    Local $sAD_Category = "(objectCategory=Person)(objectClass=User)"
    If $bAD_Computer = True Then $sAD_Category = "(objectCategory=computer)"
    $oAD_Command.CommandText = "<LDAP://" & $sAD_HostServer & "/" & $sAD_Root & ">;(&" & $sAD_Category & _
        "(pwdLastSet<=" & Int($iAD_DTExpire) & ")(pwdLastSet>=" & $iAD_LowerDate & "));distinguishedName,pwdlastset,useraccountcontrol;subtree"
ConsoleWrite($oAD_Command.CommandText & @CRLF)
    Local $oAD_RecordSet = $oAD_Command.Execute
    If Not IsObj($oAD_RecordSet) Or $oAD_RecordSet.RecordCount = 0 Then Return SetError(1, 0, "")
ConsoleWrite("Records: " & $oAD_RecordSet.RecordCount & @CRLF)
    Local $aAD_FQDN[$oAD_RecordSet.RecordCount + 1][3]
    $aAD_FQDN[0][0] = $oAD_RecordSet.RecordCount
    Local $iAD_Count = 1
    While Not $oAD_RecordSet.EOF
        $aAD_FQDN[$iAD_Count][0] = $oAD_RecordSet.Fields(0).Value
        $iAD_Temp = $oAD_RecordSet.Fields(1).Value
        If BitAND($oAD_RecordSet.Fields(2).Value, $ADS_UF_DONT_EXPIRE_PASSWD) <> $ADS_UF_DONT_EXPIRE_PASSWD Then
            DllStructSetData($sAD_DTStruct, "Low", $iAD_Temp.LowPart)
            DllStructSetData($sAD_DTStruct, "High", $iAD_Temp.HighPart)
            $sAD_Temp = _Date_Time_FileTimeToSystemTime(DllStructGetPtr($sAD_DTStruct))
            $aAD_FQDN[$iAD_Count][1] = _Date_Time_SystemTimeToDateTimeStr($sAD_Temp, 1)
            $sAD_Temp = _Date_Time_SystemTimeToTzSpecificLocalTime(DllStructGetPtr($sAD_Temp))
            $aAD_FQDN[$iAD_Count][2] = _Date_Time_SystemTimeToDateTimeStr($sAD_Temp, 1)
        EndIf
        $iAD_Count += 1
        $oAD_RecordSet.MoveNext
    WEnd
_ArrayDisplay($aAD_FQDN, "Before")
    ; Delete records with UAC set to password not expire
    $aAD_FQDN[0][0] = UBound($aAD_FQDN) - 1
    For $iAD_Count = $aAD_FQDN[0][0] To 1 Step -1
        If $aAD_FQDN[$iAD_Count][1] = "" Then _ArrayDelete($aAD_FQDN, $iAD_Count)
    Next
    $aAD_FQDN[0][0] = UBound($aAD_FQDN) - 1
_ArrayDisplay($aAD_FQDN, "After")
    Return $aAD_FQDN

EndFunc   ;==>_AD_GetPasswordExpired
Edited by water

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2022-02-19 - Version 1.6.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download
Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki
PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki
Task Scheduler (2019-12-03 - Version 1.5.1.0) - Download - General Help & Support - Wiki

Standard UDFs:
Excel - Example Scripts - Wiki
Word - Wiki

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Link to post
Share on other sites

I get

<LDAP://DC.xx.xxxxxx.xxx/DC=xx,DC=xxxxxxx,DC=xx>;(&(objectCategory=computer)(pwdLastSet<=129641133610000001)(pwdLastSet>=110133216000000001));distinguishedName,pwdlastset,useraccountcontrol;subtree

[font='Comic Sans MS']Eagles may soar high but weasels dont get sucked into jet engines[/font]

Link to post
Share on other sites

And you don't get the line?

Records: nnn
Edited by water

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2022-02-19 - Version 1.6.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download
Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki
PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki
Task Scheduler (2019-12-03 - Version 1.5.1.0) - Download - General Help & Support - Wiki

Standard UDFs:
Excel - Example Scripts - Wiki
Word - Wiki

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Link to post
Share on other sites

sry, I'm in the middle of a major rollout, so can only jump in and out at the moment, and my concentration is elsewhere.

I had scrolled to the far right to copy the text. Yes, I do get Records: nnnnn

[font='Comic Sans MS']Eagles may soar high but weasels dont get sucked into jet engines[/font]

Link to post
Share on other sites

Is this the number you expect?

I changed the example script in post a bit. it now displays the result araay before and after deleteing unnecessary records.

Could you please test and tell me how many records you get before/after?

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2022-02-19 - Version 1.6.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download
Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki
PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki
Task Scheduler (2019-12-03 - Version 1.5.1.0) - Download - General Help & Support - Wiki

Standard UDFs:
Excel - Example Scripts - Wiki
Word - Wiki

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Link to post
Share on other sites

Hi Water

Sorry for the delay - work interferes yet again.

The number looked about right for the number of expired accounts I expected to see.

Strange thing - I was working at another PC later on today when the test you suggested worked. I tried the entire function on the first PC I was using which reported a syntax error on line "If $sAD_Root = "" Then" which is crazy, but no matter what I did I still got the error, so - I UNC'd to the second PC, copied the .au3 file and opened it on the first PC - all OK.

On PC 1 I copied and pasted again from post 30 and F5'd it - syntax error!!! I tried copying several functions in their entirety from the AD help files, and they each errored in the same way, always on an IF comparison. If I deleted the comparison line, all is OK..... this is seriously messing with my head now. Tomorrow I will copy and paste from both PC's and use ExamDiff to compare the two results.

I will test this in more detail tomorrow at work (where I have a reasonably sized AD) and let you know how I get on. Thank you so much for all your help, effort and patience

[font='Comic Sans MS']Eagles may soar high but weasels dont get sucked into jet engines[/font]

Link to post
Share on other sites

Finally, some time! OK, I now have all working reliably (uninstall everything, AutoIT, SciTe, delete all residual files and purge registry then completely clean install)

I tried the original Func (post #8) to see if it was a local issue, but that still doesn't work.

Is the post #30 (minus the _ArrayDisplay()'s) going to be the final _GetPasswordExpired function?

[font='Comic Sans MS']Eagles may soar high but weasels dont get sucked into jet engines[/font]

Link to post
Share on other sites

Right. If you remove the "ConsoleWrite" and "_ArrayDisplay" statements then this will be the final function.

Good luck!

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2022-02-19 - Version 1.6.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download
Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki
PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki
Task Scheduler (2019-12-03 - Version 1.5.1.0) - Download - General Help & Support - Wiki

Standard UDFs:
Excel - Example Scripts - Wiki
Word - Wiki

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Link to post
Share on other sites

Great job. I guess this will eventually be rolled into the standard AD UDF with new helpfile.....I guess your work never ends :-)

Again, thank you very much

[font='Comic Sans MS']Eagles may soar high but weasels dont get sucked into jet engines[/font]

Link to post
Share on other sites

Right. Will be part of the next version of this UDF. I plan to release a version 1.2.0 in about a month (as soon as enough changes have accumulated).

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2022-02-19 - Version 1.6.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download
Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki
PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki
Task Scheduler (2019-12-03 - Version 1.5.1.0) - Download - General Help & Support - Wiki

Standard UDFs:
Excel - Example Scripts - Wiki
Word - Wiki

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Link to post
Share on other sites

On a related note, is there some way we could have the same type of array returned using lastLogonTimestamp instead of pwdLastSet? Currently the UDF has only _AD_GetLastLoginDate, which works for Computer and User Accounts, but you only can do one at a time. It would be nice to get an array of computers or users that have a lastLogonTimestamp a number of days old.

Adam

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...