[Virtual attributes on User form] Populate virtual attribute values, when user form is opened

Hello,
I have the following business scenario: When 'User form' is opened within Active Roles, then couple of virtual attributes (e.g.: badPasswordTime, lastLogonTimestamp -> INTEGER8 types) should be populated with their recent values (taken from Primary Domain Controller emulator).
Unfortunately, tried solution, which is based on the following article (www.oneidentity.com/.../last-bad-password-time) does not work. It throws the following error: Recursion is too deep; nested policy execution limit has been exceeded
From my testing, mentioned error is occurring on SetInfo method (whether it's DirObject or objUser defined in my script). ARS best practices article (www.oneidentity.com/.../ars-script-policy-best-practices) suggests to use Request.Put method instead. However, it looks, that Request.Put method would not work under onPreGet event.
Therefore I am looking for some solution, which will still allow me to use onPreGet event (opening User form event), which will set virtual attribute value during the load without ending in infinity loops. See my scripts below for your reference.
Many thanks in advance

VBScript:

Sub onPreGet(Request)
    'continue with flow only on User form    
    If Request.Class <> "user" Then Exit Sub
    
    'verification of requested attributes
    If Request.IsAttributeRequested("AccountingCode") = False Or Request.IsAttributeRequested("sAMAccountName") = False Then
        Exit Sub
    End If

    Logit "Entered script"
    Dim strPDCEmulator: strPDCEmulator = EnumeratePDCEmulator
    Dim objUser: Set objUser = GetObject("LDAP://" & strPDCEmulator & "/" & Request.Get("distinguishedName"))
    Set objLargeInteger = CreateObject("AelitaEDM.EDMLargeInteger")

    ' Specify badPasswordTime as custom date = 6 months from current date
    badPwdTimeAttr = DateAdd("m", 6, Now)
    objLargeInteger.SetDate(badPwdTimeAttr)
    Logit "Logit badPwdTimeAttr -> " & CStr(badPwdTimeAttr)
    Logit "Logit badPwdTimeAttr GetString -> " & objLargeInteger.GetString

    On Error Resume Next
    Set objUser = GetObject("EDMS://" & Request.Get("distinguishedName"))
    objUser.Put "edsvaBadPasswordTime", objLargeInteger.GetIADsLargeInteger
    objUser.SetInfo
    If Err.Number <> 0 Then
        Logit "Set info failed -> " & Err.Description
        Err.Clear
    End If 
    Set objUser = Nothing

    Logit "Finished script"
    
End Sub

Sub Logit(inputString)

    Dim inputPath: inputPath = "C:\TEMP\last_logon_bad_password\ScriptLogVB.txt"
    Dim dateTimeNow: dateTimeNow = FormatDateTime(Now)
    Set fso = CreateObject("Scripting.FileSystemObject")
    Set MyFile = fso.OpenTextFile(inputPath , 8, True)
    MyFile.WriteLine(dateTimeNow + " -> " + inputString)
    MyFile.Close

End Sub


Private Function EnumeratePDCEmulator()

    Dim objRootDSE, objDomain, strPDCEmulator, objNtds, objComputer
    Set objRootDSE = GetObject("LDAP://rootDSE")
    Set objDomain = GetObject("LDAP://" & objRootDSE.Get("defaultNamingContext"))
    strPDCEmulator = objDomain.Get("fSMORoleOwner")
    Set objNtds = GetObject("LDAP://" & strPDCEmulator)
    Set objComputer = GetObject(objNtds.Parent)
    
    EnumeratePDCEmulator = objComputer.dNSHostName
    
    Set objComputer = Nothing
    Set objNtds = Nothing
    Set objDomain = Nothing
    Set objRootDSE = Nothing

End Function


Log file, which is generated during opening User form, when VBScript was triggered:
2/5/2021 10:32:22 AM -> Entered script
2/5/2021 10:32:22 AM -> Logit badPwdTimeAttr -> 8/5/2021 10:32:22 AM
2/5/2021 10:32:22 AM -> Logit badPwdTimeAttr GetString -> 132726331420000000
2/5/2021 10:32:23 AM -> Entered script
2/5/2021 10:32:23 AM -> Logit badPwdTimeAttr -> 8/5/2021 10:32:23 AM
2/5/2021 10:32:23 AM -> Logit badPwdTimeAttr GetString -> 132726331430000000
2/5/2021 10:32:23 AM -> Entered script
2/5/2021 10:32:23 AM -> Logit badPwdTimeAttr -> 8/5/2021 10:32:23 AM
2/5/2021 10:32:23 AM -> Logit badPwdTimeAttr GetString -> 132726331430000000
2/5/2021 10:32:23 AM -> Entered script
2/5/2021 10:32:23 AM -> Logit badPwdTimeAttr -> 8/5/2021 10:32:23 AM
2/5/2021 10:32:23 AM -> Logit badPwdTimeAttr GetString -> 132726331430000000
2/5/2021 10:32:23 AM -> Entered script
2/5/2021 10:32:23 AM -> Logit badPwdTimeAttr -> 8/5/2021 10:32:23 AM
2/5/2021 10:32:23 AM -> Logit badPwdTimeAttr GetString -> 132726331430000000
2/5/2021 10:32:23 AM -> Entered script
2/5/2021 10:32:23 AM -> Logit badPwdTimeAttr -> 8/5/2021 10:32:23 AM
2/5/2021 10:32:23 AM -> Logit badPwdTimeAttr GetString -> 132726331430000000
2/5/2021 10:32:24 AM -> Entered script
2/5/2021 10:32:24 AM -> Logit badPwdTimeAttr -> 8/5/2021 10:32:24 AM
2/5/2021 10:32:24 AM -> Logit badPwdTimeAttr GetString -> 132726331440000000
2/5/2021 10:32:24 AM -> Finished script
2/5/2021 10:32:24 AM -> Finished script
2/5/2021 10:32:24 AM -> Finished script
2/5/2021 10:32:25 AM -> Finished script
2/5/2021 10:32:25 AM -> Finished script
2/5/2021 10:32:25 AM -> Finished script
2/5/2021 10:32:25 AM -> Finished script
2/5/2021 10:32:25 AM -> Entered script
2/5/2021 10:32:25 AM -> Logit badPwdTimeAttr -> 8/5/2021 10:32:25 AM
2/5/2021 10:32:25 AM -> Logit badPwdTimeAttr GetString -> 132726331450000000
2/5/2021 10:32:26 AM -> Entered script
2/5/2021 10:32:26 AM -> Logit badPwdTimeAttr -> 8/5/2021 10:32:26 AM
2/5/2021 10:32:26 AM -> Logit badPwdTimeAttr GetString -> 132726331460000000
2/5/2021 10:32:26 AM -> Entered script
2/5/2021 10:32:26 AM -> Logit badPwdTimeAttr -> 8/5/2021 10:32:26 AM
2/5/2021 10:32:26 AM -> Logit badPwdTimeAttr GetString -> 132726331460000000
2/5/2021 10:32:26 AM -> Entered script
2/5/2021 10:32:26 AM -> Logit badPwdTimeAttr -> 8/5/2021 10:32:26 AM
2/5/2021 10:32:26 AM -> Logit badPwdTimeAttr GetString -> 132726331460000000
2/5/2021 10:32:26 AM -> Entered script
2/5/2021 10:32:26 AM -> Logit badPwdTimeAttr -> 8/5/2021 10:32:26 AM
2/5/2021 10:32:26 AM -> Logit badPwdTimeAttr GetString -> 132726331460000000
2/5/2021 10:32:26 AM -> Entered script
2/5/2021 10:32:26 AM -> Logit badPwdTimeAttr -> 8/5/2021 10:32:26 AM
2/5/2021 10:32:26 AM -> Logit badPwdTimeAttr GetString -> 132726331460000000
2/5/2021 10:32:27 AM -> Entered script
2/5/2021 10:32:27 AM -> Logit badPwdTimeAttr -> 8/5/2021 10:32:27 AM
2/5/2021 10:32:27 AM -> Logit badPwdTimeAttr GetString -> 132726331470000000
2/5/2021 10:32:27 AM -> Entered script
2/5/2021 10:32:27 AM -> Logit badPwdTimeAttr -> 8/5/2021 10:32:27 AM
2/5/2021 10:32:27 AM -> Logit badPwdTimeAttr GetString -> 132726331470000000
2/5/2021 10:32:27 AM -> Set info failed -> Administrative Policy returned an error.
Recursion is too deep; nested policy execution limit has been exceeded.


2/5/2021 10:32:27 AM -> Finished script
2/5/2021 10:32:27 AM -> Finished script
2/5/2021 10:32:27 AM -> Finished script
2/5/2021 10:32:28 AM -> Finished script
2/5/2021 10:32:28 AM -> Finished script
2/5/2021 10:32:28 AM -> Finished script
2/5/2021 10:32:28 AM -> Finished script
2/5/2021 10:32:28 AM -> Finished script
2/5/2021 10:32:29 AM -> Entered script
2/5/2021 10:32:29 AM -> Logit badPwdTimeAttr -> 8/5/2021 10:32:29 AM
2/5/2021 10:32:29 AM -> Logit badPwdTimeAttr GetString -> 132726331490000000
2/5/2021 10:32:29 AM -> Entered script
2/5/2021 10:32:29 AM -> Logit badPwdTimeAttr -> 8/5/2021 10:32:29 AM
2/5/2021 10:32:29 AM -> Logit badPwdTimeAttr GetString -> 132726331490000000
2/5/2021 10:32:30 AM -> Entered script
2/5/2021 10:32:30 AM -> Logit badPwdTimeAttr -> 8/5/2021 10:32:30 AM
2/5/2021 10:32:30 AM -> Logit badPwdTimeAttr GetString -> 132726331500000000
2/5/2021 10:32:30 AM -> Entered script
2/5/2021 10:32:30 AM -> Logit badPwdTimeAttr -> 8/5/2021 10:32:30 AM
2/5/2021 10:32:30 AM -> Logit badPwdTimeAttr GetString -> 132726331500000000
2/5/2021 10:32:30 AM -> Entered script
2/5/2021 10:32:30 AM -> Logit badPwdTimeAttr -> 8/5/2021 10:32:30 AM
2/5/2021 10:32:30 AM -> Logit badPwdTimeAttr GetString -> 132726331500000000
2/5/2021 10:32:30 AM -> Entered script
2/5/2021 10:32:30 AM -> Logit badPwdTimeAttr -> 8/5/2021 10:32:30 AM
2/5/2021 10:32:30 AM -> Logit badPwdTimeAttr GetString -> 132726331500000000
2/5/2021 10:32:30 AM -> Entered script
2/5/2021 10:32:30 AM -> Logit badPwdTimeAttr -> 8/5/2021 10:32:30 AM
2/5/2021 10:32:30 AM -> Logit badPwdTimeAttr GetString -> 132726331500000000
2/5/2021 10:32:31 AM -> Finished script
2/5/2021 10:32:31 AM -> Finished script
2/5/2021 10:32:31 AM -> Finished script
2/5/2021 10:32:31 AM -> Finished script
2/5/2021 10:32:32 AM -> Finished script
2/5/2021 10:32:32 AM -> Finished script
2/5/2021 10:32:32 AM -> Finished script

Top Replies

  • hi , I was able to make it work, see the solution below:
    1. Option "Store values of this virtual attribute in the Active Roles Administration database" for created virtual attributes is…

  • Couple of thoughts:

    1) Powershell is now the "preferred" language for authoring policy scripts

    2) I believe you could use a "Control" to suppress the error by setting the control the first time through your code and then looking for it.  If it's set, then exit.

    So something like this:

    # Place at the top of your code

    Try

    {

    $RecurseStop = $Request.GetinControl("StopRecursion")

    If ($RecurseStop){return}

    }

    Catch

    {

    # Prevent errors before the Control is set

    }

    # Place at the end of your code

    $Request.PutInControl("StopRecursion",$Constants.ADSTYPE_CASE_IGNORE_STRING,"1")

  • hi , correct, this is proper requested question (thread) to keep open
    can you please display (enable) my reply, which was given to this thread last week on Friday (5.Feb) ? thx

  • that is not possible. please post it again here as a new reply and if you encounter any issues I will be available to assist

  • hi , thanks for your suggestions, somehow my replies are often flagged as spam and therefore not posted.
    I've tried to incorporate "Control element" into my flow, but it's not working -> it looks like beginning of code is triggered multiple times before executing end of the code (assigning value to virtual attribute) and whole execution still shows "infinity loop error"...
    What could be the reason for that ?
    thanks
    VB script:

    Sub onPreGet(Request)
        On Error Resume Next
        'continue with flow only on User form    
        If Request.Class <> "user" Then Exit Sub
        
        'verification of requested attributes
        If Request.IsAttributeRequested("AccountingCode") = False Or Request.IsAttributeRequested("sAMAccountName") = False Then
            Exit Sub
        End If
    
        'if script was already processed, stop potential infinity loop
        RecurseStop = Request.GetInControl("StopRecursion")
        If Err.Number <> 0 Then
            Set RecurseStop = "0"
            Logit "Recurse Stop value -> " & RecurseStop
        Else
            Logit "RecurseStop value get was FINE -> " & RecurseStop
        End If
        
        If RecurseStop = True Then Exit Sub
    
        Logit "Entered script"
        Dim strPDCEmulator: strPDCEmulator = EnumeratePDCEmulator
        Dim objUser: Set objUser = GetObject("LDAP://" & strPDCEmulator & "/" & Request.Get("distinguishedName"))
        Set objLargeInteger = CreateObject("AelitaEDM.EDMLargeInteger")
    
        ' Specify badPasswordTime as custom date = 6 months from current date
        badPwdTimeAttr = DateAdd("m", 6, Now)
        objLargeInteger.SetDate(badPwdTimeAttr)
        Logit "Logit badPwdTimeAttr -> " & CStr(badPwdTimeAttr)
        Logit "Logit badPwdTimeAttr GetString -> " & objLargeInteger.GetString
        
        Set objUser = GetObject("EDMS://" & Request.Get("distinguishedName"))
        objUser.Put "edsvaBadPasswordTime", objLargeInteger.GetIADsLargeInteger
        objUser.SetInfo
        If Err.Number <> 0 Then
            Logit "Set info failed -> " & Err.Description
            Err.Clear
        End If 
        Set objUser = Nothing
    
        Request.PutInControl "StopRecursion", ADSTYPE_CASE_IGNORE_STRING, "1"
        Logit "Finished script"
        RecurseStopSecondCheck = Request.GetInControl("StopRecursion")
        If Err.Number <> 0 Then
            Set RecurseStopSecondCheck = "0"
            Logit "Recurse Stop 2nd check value -> " & RecurseStopSecondCheck
        Else
            Logit "RecurseStop value 2nd check get was FINE -> " & RecurseStopSecondCheck
        End If
        
    End Sub
    
    Sub Logit(inputString)
    
        Dim inputPath: inputPath = "C:\TEMP\last_logon_bad_password\ScriptLogVB.txt"
        Dim dateTimeNow: dateTimeNow = FormatDateTime(Now)
        Set fso = CreateObject("Scripting.FileSystemObject")
        Set MyFile = fso.OpenTextFile(inputPath , 8, True)
        MyFile.WriteLine(dateTimeNow + " -> " + inputString)
        MyFile.Close
    
    End Sub
    
    
    Private Function EnumeratePDCEmulator()
    
        Dim objRootDSE, objDomain, strPDCEmulator, objNtds, objComputer
        Set objRootDSE = GetObject("LDAP://rootDSE")
        Set objDomain = GetObject("LDAP://" & objRootDSE.Get("defaultNamingContext"))
        strPDCEmulator = objDomain.Get("fSMORoleOwner")
        Set objNtds = GetObject("LDAP://" & strPDCEmulator)
        Set objComputer = GetObject(objNtds.Parent)
        
        EnumeratePDCEmulator = objComputer.dNSHostName
        
        Set objComputer = Nothing
        Set objNtds = Nothing
        Set objDomain = Nothing
        Set objRootDSE = Nothing
    
    End Function


    Log file:

    2/5/2021 5:47:11 PM -> Recurse Stop value -> 
    2/5/2021 5:47:11 PM -> Entered script
    2/5/2021 5:47:11 PM -> Logit badPwdTimeAttr -> 8/5/2021 5:47:11 PM
    2/5/2021 5:47:11 PM -> Logit badPwdTimeAttr GetString -> 132726592310000000
    2/5/2021 5:47:11 PM -> Recurse Stop value -> 
    2/5/2021 5:47:11 PM -> Entered script
    2/5/2021 5:47:11 PM -> Logit badPwdTimeAttr -> 8/5/2021 5:47:11 PM
    2/5/2021 5:47:11 PM -> Logit badPwdTimeAttr GetString -> 132726592310000000
    2/5/2021 5:47:11 PM -> Recurse Stop value -> 
    2/5/2021 5:47:11 PM -> Entered script
    2/5/2021 5:47:11 PM -> Logit badPwdTimeAttr -> 8/5/2021 5:47:11 PM
    2/5/2021 5:47:11 PM -> Logit badPwdTimeAttr GetString -> 132726592310000000
    2/5/2021 5:47:11 PM -> Recurse Stop value -> 
    2/5/2021 5:47:11 PM -> Entered script
    2/5/2021 5:47:11 PM -> Logit badPwdTimeAttr -> 8/5/2021 5:47:11 PM
    2/5/2021 5:47:11 PM -> Logit badPwdTimeAttr GetString -> 132726592310000000
    2/5/2021 5:47:11 PM -> Recurse Stop value -> 
    2/5/2021 5:47:11 PM -> Entered script
    2/5/2021 5:47:11 PM -> Logit badPwdTimeAttr -> 8/5/2021 5:47:11 PM
    2/5/2021 5:47:11 PM -> Logit badPwdTimeAttr GetString -> 132726592310000000
    2/5/2021 5:47:11 PM -> Recurse Stop value -> 
    2/5/2021 5:47:11 PM -> Entered script
    2/5/2021 5:47:11 PM -> Logit badPwdTimeAttr -> 8/5/2021 5:47:11 PM
    2/5/2021 5:47:11 PM -> Logit badPwdTimeAttr GetString -> 132726592310000000
    2/5/2021 5:47:12 PM -> Recurse Stop value -> 
    2/5/2021 5:47:12 PM -> Entered script
    2/5/2021 5:47:12 PM -> Logit badPwdTimeAttr -> 8/5/2021 5:47:12 PM
    2/5/2021 5:47:12 PM -> Logit badPwdTimeAttr GetString -> 132726592320000000
    2/5/2021 5:47:12 PM -> Finished script
    2/5/2021 5:47:12 PM -> RecurseStop value 2nd check get was FINE -> 1
    2/5/2021 5:47:12 PM -> Finished script
    2/5/2021 5:47:12 PM -> RecurseStop value 2nd check get was FINE -> 1
    2/5/2021 5:47:12 PM -> Finished script
    2/5/2021 5:47:12 PM -> RecurseStop value 2nd check get was FINE -> 1
    2/5/2021 5:47:13 PM -> Finished script
    2/5/2021 5:47:13 PM -> RecurseStop value 2nd check get was FINE -> 1
    2/5/2021 5:47:13 PM -> Finished script
    2/5/2021 5:47:13 PM -> RecurseStop value 2nd check get was FINE -> 1
    2/5/2021 5:47:13 PM -> Finished script
    2/5/2021 5:47:13 PM -> RecurseStop value 2nd check get was FINE -> 1
    2/5/2021 5:47:13 PM -> Finished script
    2/5/2021 5:47:13 PM -> RecurseStop value 2nd check get was FINE -> 1
    2/5/2021 5:47:14 PM -> Recurse Stop value -> 
    2/5/2021 5:47:14 PM -> Entered script
    2/5/2021 5:47:14 PM -> Logit badPwdTimeAttr -> 8/5/2021 5:47:14 PM
    2/5/2021 5:47:14 PM -> Logit badPwdTimeAttr GetString -> 132726592340000000
    2/5/2021 5:47:14 PM -> Recurse Stop value -> 
    2/5/2021 5:47:14 PM -> Entered script
    2/5/2021 5:47:14 PM -> Logit badPwdTimeAttr -> 8/5/2021 5:47:14 PM
    2/5/2021 5:47:14 PM -> Logit badPwdTimeAttr GetString -> 132726592340000000
    2/5/2021 5:47:14 PM -> Recurse Stop value -> 
    2/5/2021 5:47:14 PM -> Entered script
    2/5/2021 5:47:14 PM -> Logit badPwdTimeAttr -> 8/5/2021 5:47:14 PM
    2/5/2021 5:47:14 PM -> Logit badPwdTimeAttr GetString -> 132726592340000000
    2/5/2021 5:47:14 PM -> Recurse Stop value -> 
    2/5/2021 5:47:14 PM -> Entered script
    2/5/2021 5:47:14 PM -> Logit badPwdTimeAttr -> 8/5/2021 5:47:14 PM
    2/5/2021 5:47:14 PM -> Logit badPwdTimeAttr GetString -> 132726592340000000
    2/5/2021 5:47:14 PM -> Recurse Stop value -> 
    2/5/2021 5:47:14 PM -> Entered script
    2/5/2021 5:47:14 PM -> Logit badPwdTimeAttr -> 8/5/2021 5:47:14 PM
    2/5/2021 5:47:14 PM -> Logit badPwdTimeAttr GetString -> 132726592340000000
    2/5/2021 5:47:14 PM -> Recurse Stop value -> 
    2/5/2021 5:47:14 PM -> Entered script
    2/5/2021 5:47:14 PM -> Logit badPwdTimeAttr -> 8/5/2021 5:47:14 PM
    2/5/2021 5:47:14 PM -> Logit badPwdTimeAttr GetString -> 132726592340000000
    2/5/2021 5:47:15 PM -> Recurse Stop value -> 
    2/5/2021 5:47:15 PM -> Entered script
    2/5/2021 5:47:15 PM -> Logit badPwdTimeAttr -> 8/5/2021 5:47:15 PM
    2/5/2021 5:47:15 PM -> Logit badPwdTimeAttr GetString -> 132726592350000000
    2/5/2021 5:47:15 PM -> Recurse Stop value -> 
    2/5/2021 5:47:15 PM -> Entered script
    2/5/2021 5:47:15 PM -> Logit badPwdTimeAttr -> 8/5/2021 5:47:15 PM
    2/5/2021 5:47:15 PM -> Logit badPwdTimeAttr GetString -> 132726592350000000
    2/5/2021 5:47:15 PM -> Set info failed -> Administrative Policy returned an error.
    Recursion is too deep; nested policy execution limit has been exceeded.
    
    
    2/5/2021 5:47:15 PM -> Finished script
    2/5/2021 5:47:15 PM -> RecurseStop value 2nd check get was FINE -> 1
    2/5/2021 5:47:15 PM -> Finished script
    2/5/2021 5:47:15 PM -> RecurseStop value 2nd check get was FINE -> 1
    2/5/2021 5:47:15 PM -> Finished script
    2/5/2021 5:47:15 PM -> RecurseStop value 2nd check get was FINE -> 1
    2/5/2021 5:47:15 PM -> Finished script
    2/5/2021 5:47:15 PM -> RecurseStop value 2nd check get was FINE -> 1
    2/5/2021 5:47:16 PM -> Finished script
    2/5/2021 5:47:16 PM -> RecurseStop value 2nd check get was FINE -> 1
    2/5/2021 5:47:16 PM -> Finished script
    2/5/2021 5:47:16 PM -> RecurseStop value 2nd check get was FINE -> 1
    2/5/2021 5:47:16 PM -> Finished script
    2/5/2021 5:47:16 PM -> RecurseStop value 2nd check get was FINE -> 1
    2/5/2021 5:47:16 PM -> Finished script
    2/5/2021 5:47:16 PM -> RecurseStop value 2nd check get was FINE -> 1
    2/5/2021 5:47:17 PM -> Recurse Stop value -> 
    2/5/2021 5:47:17 PM -> Entered script
    2/5/2021 5:47:17 PM -> Logit badPwdTimeAttr -> 8/5/2021 5:47:17 PM
    2/5/2021 5:47:17 PM -> Logit badPwdTimeAttr GetString -> 132726592370000000
    2/5/2021 5:47:17 PM -> Recurse Stop value -> 
    2/5/2021 5:47:17 PM -> Entered script
    2/5/2021 5:47:17 PM -> Logit badPwdTimeAttr -> 8/5/2021 5:47:17 PM
    2/5/2021 5:47:17 PM -> Logit badPwdTimeAttr GetString -> 132726592370000000
    2/5/2021 5:47:17 PM -> Recurse Stop value -> 
    2/5/2021 5:47:17 PM -> Entered script
    2/5/2021 5:47:17 PM -> Logit badPwdTimeAttr -> 8/5/2021 5:47:17 PM
    2/5/2021 5:47:17 PM -> Logit badPwdTimeAttr GetString -> 132726592370000000
    2/5/2021 5:47:18 PM -> Recurse Stop value -> 
    2/5/2021 5:47:18 PM -> Entered script
    2/5/2021 5:47:18 PM -> Logit badPwdTimeAttr -> 8/5/2021 5:47:18 PM
    2/5/2021 5:47:18 PM -> Logit badPwdTimeAttr GetString -> 132726592380000000
    2/5/2021 5:47:18 PM -> Recurse Stop value -> 
    2/5/2021 5:47:18 PM -> Entered script
    2/5/2021 5:47:18 PM -> Logit badPwdTimeAttr -> 8/5/2021 5:47:18 PM
    2/5/2021 5:47:18 PM -> Logit badPwdTimeAttr GetString -> 132726592380000000
    2/5/2021 5:47:18 PM -> Recurse Stop value -> 
    2/5/2021 5:47:18 PM -> Entered script
    2/5/2021 5:47:18 PM -> Logit badPwdTimeAttr -> 8/5/2021 5:47:18 PM
    2/5/2021 5:47:18 PM -> Logit badPwdTimeAttr GetString -> 132726592380000000
    2/5/2021 5:47:18 PM -> Recurse Stop value -> 
    2/5/2021 5:47:18 PM -> Entered script
    2/5/2021 5:47:18 PM -> Logit badPwdTimeAttr -> 8/5/2021 5:47:18 PM
    2/5/2021 5:47:18 PM -> Logit badPwdTimeAttr GetString -> 132726592380000000
    2/5/2021 5:47:18 PM -> Finished script
    2/5/2021 5:47:18 PM -> RecurseStop value 2nd check get was FINE -> 1
    2/5/2021 5:47:19 PM -> Finished script
    2/5/2021 5:47:19 PM -> RecurseStop value 2nd check get was FINE -> 1
    2/5/2021 5:47:19 PM -> Finished script
    2/5/2021 5:47:19 PM -> RecurseStop value 2nd check get was FINE -> 1
    2/5/2021 5:47:19 PM -> Finished script
    2/5/2021 5:47:19 PM -> RecurseStop value 2nd check get was FINE -> 1
    2/5/2021 5:47:19 PM -> Finished script
    2/5/2021 5:47:19 PM -> RecurseStop value 2nd check get was FINE -> 1
    2/5/2021 5:47:20 PM -> Finished script
    2/5/2021 5:47:20 PM -> RecurseStop value 2nd check get was FINE -> 1
    2/5/2021 5:47:20 PM -> Finished script
    2/5/2021 5:47:20 PM -> RecurseStop value 2nd check get was FINE -> 1
    

  • Your Control is being set to 1 and not the Boolean value True - so I am not sure that your

    If RecurseStop = True Then Exit Sub

    ...is going to work.

    So what if you change to

    If RecurseStop = '1' Then Exit Sub

  • hi , thanks for your finding. I've corrected "if condition", but script still does not work as expected.
    It seems, that line 45 (putting value into control) is triggered even before line 38 (set value for virtual attribute) based on the log file. And those multiple triggers still worries me as well...
    1. Do you think, that intended solution (onPreGet event code, which will set virtual attribute value) is possible ?
    2. Would you know about other setup in Active roles, which could satisfy requested business scenario (when 'User form' is opened within Active Roles, then couple of virtual attributes are populated with their recent values) ?


    VB Script:

    Sub onPreGet(Request)
        On Error Resume Next
        'continue with flow only on User form    
        If Request.Class <> "user" Then Exit Sub
        
        'verification of requested attributes
        If Request.IsAttributeRequested("AccountingCode") = False Or Request.IsAttributeRequested("sAMAccountName") = False Then
            Exit Sub
        End If
    
        'if script was already processed, stop potential infinity loop
        RecurseStop = Request.GetInControl("StopRecursion")
        If Err.Number <> 0 Then
            Set RecurseStop = "0"
            Logit "Recurse Stop value -> " & RecurseStop
        Else
            Logit "RecurseStop value get was FINE -> " & RecurseStop
        End If
        
        If RecurseStop = "1" Then 
            Logit "Stop execution!"
            Exit Sub
        End If
    
        Logit "Entered script"
        Dim strPDCEmulator: strPDCEmulator = EnumeratePDCEmulator
        Dim objUser: Set objUser = GetObject("LDAP://" & strPDCEmulator & "/" & Request.Get("distinguishedName"))
        Set objLargeInteger = CreateObject("AelitaEDM.EDMLargeInteger")
    
        ' Specify badPasswordTime as custom date = 6 months from current date
        badPwdTimeAttr = DateAdd("m", 6, Now)
        objLargeInteger.SetDate(badPwdTimeAttr)
        Logit "Logit badPwdTimeAttr -> " & CStr(badPwdTimeAttr)
        Logit "Logit badPwdTimeAttr GetString -> " & objLargeInteger.GetString
        
        Set objUser = GetObject("EDMS://" & Request.Get("distinguishedName"))
        objUser.Put "edsvaBadPasswordTime", objLargeInteger.GetIADsLargeInteger
        objUser.SetInfo
        If Err.Number <> 0 Then
            Logit "Set info failed -> " & Err.Description
            Err.Clear
        End If 
        Set objUser = Nothing
    
        Request.PutInControl "StopRecursion", ADSTYPE_CASE_IGNORE_STRING, "1"
        Logit "Finished script"
        RecurseStopSecondCheck = Request.GetInControl("StopRecursion")
        If Err.Number <> 0 Then
            Set RecurseStopSecondCheck = "0"
            Logit "Recurse Stop 2nd check value -> " & RecurseStopSecondCheck
        Else
            Logit "RecurseStop value 2nd check get was FINE -> " & RecurseStopSecondCheck
        End If
        
    End Sub
    
    Sub Logit(inputString)
    
        Dim inputPath: inputPath = "C:\TEMP\last_logon_bad_password\ScriptLogVB.txt"
        Dim dateTimeNow: dateTimeNow = FormatDateTime(Now)
        Set fso = CreateObject("Scripting.FileSystemObject")
        Set MyFile = fso.OpenTextFile(inputPath , 8, True)
        MyFile.WriteLine(dateTimeNow + " -> " + inputString)
        MyFile.Close
    
    End Sub
    
    
    Private Function EnumeratePDCEmulator()
    
        Dim objRootDSE, objDomain, strPDCEmulator, objNtds, objComputer
        Set objRootDSE = GetObject("LDAP://rootDSE")
        Set objDomain = GetObject("LDAP://" & objRootDSE.Get("defaultNamingContext"))
        strPDCEmulator = objDomain.Get("fSMORoleOwner")
        Set objNtds = GetObject("LDAP://" & strPDCEmulator)
        Set objComputer = GetObject(objNtds.Parent)
        
        EnumeratePDCEmulator = objComputer.dNSHostName
        
        Set objComputer = Nothing
        Set objNtds = Nothing
        Set objDomain = Nothing
        Set objRootDSE = Nothing
    
    End Function


    Log file:
    2/9/2021 8:02:24 AM -> Recurse Stop value -> 
    2/9/2021 8:02:24 AM -> Entered script
    2/9/2021 8:02:24 AM -> Logit badPwdTimeAttr -> 8/9/2021 8:02:24 AM
    2/9/2021 8:02:24 AM -> Logit badPwdTimeAttr GetString -> 132729697440000000
    2/9/2021 8:02:24 AM -> Recurse Stop value -> 
    2/9/2021 8:02:24 AM -> Entered script
    2/9/2021 8:02:24 AM -> Logit badPwdTimeAttr -> 8/9/2021 8:02:24 AM
    2/9/2021 8:02:24 AM -> Logit badPwdTimeAttr GetString -> 132729697440000000
    2/9/2021 8:02:24 AM -> Recurse Stop value -> 
    2/9/2021 8:02:24 AM -> Entered script
    2/9/2021 8:02:24 AM -> Logit badPwdTimeAttr -> 8/9/2021 8:02:24 AM
    2/9/2021 8:02:24 AM -> Logit badPwdTimeAttr GetString -> 132729697440000000
    2/9/2021 8:02:25 AM -> Recurse Stop value -> 
    2/9/2021 8:02:25 AM -> Entered script
    2/9/2021 8:02:25 AM -> Logit badPwdTimeAttr -> 8/9/2021 8:02:25 AM
    2/9/2021 8:02:25 AM -> Logit badPwdTimeAttr GetString -> 132729697450000000
    2/9/2021 8:02:25 AM -> Recurse Stop value -> 
    2/9/2021 8:02:25 AM -> Entered script
    2/9/2021 8:02:25 AM -> Logit badPwdTimeAttr -> 8/9/2021 8:02:25 AM
    2/9/2021 8:02:25 AM -> Logit badPwdTimeAttr GetString -> 132729697450000000
    2/9/2021 8:02:25 AM -> Recurse Stop value -> 
    2/9/2021 8:02:25 AM -> Entered script
    2/9/2021 8:02:25 AM -> Logit badPwdTimeAttr -> 8/9/2021 8:02:25 AM
    2/9/2021 8:02:25 AM -> Logit badPwdTimeAttr GetString -> 132729697450000000
    2/9/2021 8:02:25 AM -> Recurse Stop value -> 
    2/9/2021 8:02:25 AM -> Entered script
    2/9/2021 8:02:25 AM -> Logit badPwdTimeAttr -> 8/9/2021 8:02:25 AM
    2/9/2021 8:02:25 AM -> Logit badPwdTimeAttr GetString -> 132729697450000000
    2/9/2021 8:02:25 AM -> Finished script
    2/9/2021 8:02:25 AM -> RecurseStop value 2nd check get was FINE -> 1
    2/9/2021 8:02:26 AM -> Finished script
    2/9/2021 8:02:26 AM -> RecurseStop value 2nd check get was FINE -> 1
    2/9/2021 8:02:26 AM -> Finished script
    2/9/2021 8:02:26 AM -> RecurseStop value 2nd check get was FINE -> 1
    2/9/2021 8:02:26 AM -> Finished script
    2/9/2021 8:02:26 AM -> RecurseStop value 2nd check get was FINE -> 1
    2/9/2021 8:02:26 AM -> Finished script
    2/9/2021 8:02:26 AM -> RecurseStop value 2nd check get was FINE -> 1
    2/9/2021 8:02:26 AM -> Finished script
    2/9/2021 8:02:26 AM -> RecurseStop value 2nd check get was FINE -> 1
    2/9/2021 8:02:27 AM -> Finished script
    2/9/2021 8:02:27 AM -> RecurseStop value 2nd check get was FINE -> 1
    2/9/2021 8:02:27 AM -> Recurse Stop value -> 
    2/9/2021 8:02:27 AM -> Entered script
    2/9/2021 8:02:27 AM -> Logit badPwdTimeAttr -> 8/9/2021 8:02:27 AM
    2/9/2021 8:02:27 AM -> Logit badPwdTimeAttr GetString -> 132729697470000000
    2/9/2021 8:02:27 AM -> Recurse Stop value -> 
    2/9/2021 8:02:27 AM -> Entered script
    2/9/2021 8:02:27 AM -> Logit badPwdTimeAttr -> 8/9/2021 8:02:27 AM
    2/9/2021 8:02:27 AM -> Logit badPwdTimeAttr GetString -> 132729697470000000
    2/9/2021 8:02:27 AM -> Recurse Stop value -> 
    2/9/2021 8:02:27 AM -> Entered script
    2/9/2021 8:02:27 AM -> Logit badPwdTimeAttr -> 8/9/2021 8:02:27 AM
    2/9/2021 8:02:27 AM -> Logit badPwdTimeAttr GetString -> 132729697470000000
    2/9/2021 8:02:27 AM -> Recurse Stop value -> 
    2/9/2021 8:02:27 AM -> Entered script
    2/9/2021 8:02:27 AM -> Logit badPwdTimeAttr -> 8/9/2021 8:02:27 AM
    2/9/2021 8:02:27 AM -> Logit badPwdTimeAttr GetString -> 132729697470000000
    2/9/2021 8:02:27 AM -> Recurse Stop value -> 
    2/9/2021 8:02:27 AM -> Entered script
    2/9/2021 8:02:27 AM -> Logit badPwdTimeAttr -> 8/9/2021 8:02:27 AM
    2/9/2021 8:02:27 AM -> Logit badPwdTimeAttr GetString -> 132729697470000000
    2/9/2021 8:02:28 AM -> Recurse Stop value -> 
    2/9/2021 8:02:28 AM -> Entered script
    2/9/2021 8:02:28 AM -> Logit badPwdTimeAttr -> 8/9/2021 8:02:28 AM
    2/9/2021 8:02:28 AM -> Logit badPwdTimeAttr GetString -> 132729697480000000
    2/9/2021 8:02:28 AM -> Recurse Stop value -> 
    2/9/2021 8:02:28 AM -> Entered script
    2/9/2021 8:02:28 AM -> Logit badPwdTimeAttr -> 8/9/2021 8:02:28 AM
    2/9/2021 8:02:28 AM -> Logit badPwdTimeAttr GetString -> 132729697480000000
    2/9/2021 8:02:28 AM -> Recurse Stop value -> 
    2/9/2021 8:02:28 AM -> Entered script
    2/9/2021 8:02:28 AM -> Logit badPwdTimeAttr -> 8/9/2021 8:02:28 AM
    2/9/2021 8:02:28 AM -> Logit badPwdTimeAttr GetString -> 132729697480000000
    2/9/2021 8:02:28 AM -> Set info failed -> Administrative Policy returned an error.
    Recursion is too deep; nested policy execution limit has been exceeded.
    
    
    2/9/2021 8:02:28 AM -> Finished script
    2/9/2021 8:02:28 AM -> RecurseStop value 2nd check get was FINE -> 1
    2/9/2021 8:02:28 AM -> Finished script
    2/9/2021 8:02:28 AM -> RecurseStop value 2nd check get was FINE -> 1
    2/9/2021 8:02:28 AM -> Finished script
    2/9/2021 8:02:28 AM -> RecurseStop value 2nd check get was FINE -> 1
    2/9/2021 8:02:28 AM -> Finished script
    2/9/2021 8:02:28 AM -> RecurseStop value 2nd check get was FINE -> 1
    2/9/2021 8:02:29 AM -> Finished script
    2/9/2021 8:02:29 AM -> RecurseStop value 2nd check get was FINE -> 1
    2/9/2021 8:02:29 AM -> Finished script
    2/9/2021 8:02:29 AM -> RecurseStop value 2nd check get was FINE -> 1
    2/9/2021 8:02:29 AM -> Finished script
    2/9/2021 8:02:29 AM -> RecurseStop value 2nd check get was FINE -> 1
    2/9/2021 8:02:29 AM -> Finished script
    2/9/2021 8:02:29 AM -> RecurseStop value 2nd check get was FINE -> 1
    2/9/2021 8:02:30 AM -> Recurse Stop value -> 
    2/9/2021 8:02:30 AM -> Entered script
    2/9/2021 8:02:30 AM -> Logit badPwdTimeAttr -> 8/9/2021 8:02:30 AM
    2/9/2021 8:02:30 AM -> Logit badPwdTimeAttr GetString -> 132729697500000000
    2/9/2021 8:02:30 AM -> Recurse Stop value -> 
    2/9/2021 8:02:30 AM -> Entered script
    2/9/2021 8:02:30 AM -> Logit badPwdTimeAttr -> 8/9/2021 8:02:30 AM
    2/9/2021 8:02:30 AM -> Logit badPwdTimeAttr GetString -> 132729697500000000
    2/9/2021 8:02:30 AM -> Recurse Stop value -> 
    2/9/2021 8:02:30 AM -> Entered script
    2/9/2021 8:02:30 AM -> Logit badPwdTimeAttr -> 8/9/2021 8:02:30 AM
    2/9/2021 8:02:30 AM -> Logit badPwdTimeAttr GetString -> 132729697500000000
    2/9/2021 8:02:31 AM -> Recurse Stop value -> 
    2/9/2021 8:02:31 AM -> Entered script
    2/9/2021 8:02:31 AM -> Logit badPwdTimeAttr -> 8/9/2021 8:02:31 AM
    2/9/2021 8:02:31 AM -> Logit badPwdTimeAttr GetString -> 132729697510000000
    2/9/2021 8:02:31 AM -> Recurse Stop value -> 
    2/9/2021 8:02:31 AM -> Entered script
    2/9/2021 8:02:31 AM -> Logit badPwdTimeAttr -> 8/9/2021 8:02:31 AM
    2/9/2021 8:02:31 AM -> Logit badPwdTimeAttr GetString -> 132729697510000000
    2/9/2021 8:02:31 AM -> Recurse Stop value -> 
    2/9/2021 8:02:31 AM -> Entered script
    2/9/2021 8:02:31 AM -> Logit badPwdTimeAttr -> 8/9/2021 8:02:31 AM
    2/9/2021 8:02:31 AM -> Logit badPwdTimeAttr GetString -> 132729697510000000
    2/9/2021 8:02:31 AM -> Recurse Stop value -> 
    2/9/2021 8:02:31 AM -> Entered script
    2/9/2021 8:02:31 AM -> Logit badPwdTimeAttr -> 8/9/2021 8:02:31 AM
    2/9/2021 8:02:31 AM -> Logit badPwdTimeAttr GetString -> 132729697510000000
    2/9/2021 8:02:31 AM -> Finished script
    2/9/2021 8:02:31 AM -> RecurseStop value 2nd check get was FINE -> 1
    2/9/2021 8:02:32 AM -> Finished script
    2/9/2021 8:02:32 AM -> RecurseStop value 2nd check get was FINE -> 1
    2/9/2021 8:02:32 AM -> Finished script
    2/9/2021 8:02:32 AM -> RecurseStop value 2nd check get was FINE -> 1
    2/9/2021 8:02:32 AM -> Finished script
    2/9/2021 8:02:32 AM -> RecurseStop value 2nd check get was FINE -> 1
    2/9/2021 8:02:32 AM -> Finished script
    2/9/2021 8:02:32 AM -> RecurseStop value 2nd check get was FINE -> 1
    2/9/2021 8:02:32 AM -> Finished script
    2/9/2021 8:02:32 AM -> RecurseStop value 2nd check get was FINE -> 1
    2/9/2021 8:02:33 AM -> Finished script
    2/9/2021 8:02:33 AM -> RecurseStop value 2nd check get was FINE -> 1
    


    thanks

  • hi , I was able to make it work, see the solution below:
    1. Option "Store values of this virtual attribute in the Active Roles Administration database" for created virtual attributes is enabled (it's located in Active roles console -> Configuration -> Server Configuration -> Virtual Attributes -> <select virtual attribute> -> Properties -> Attribute Storage tab -> Store values of this...)
    2. See VBScript and Powershell code snippets, which were uploaded into Script Modules

    Also infinity loops are not appearing anymore using mentioned code snippet.

    VBScript:

    Sub onPreGet(Request)
        'continue with flow only on User form    
        If Request.Class <> "user" Then Exit Sub
        
        'verification of requested attributes
        If Request.IsAttributeRequested("AttributeOne") = False Or Request.IsAttributeRequested("AttributeTwo") = False Then
            Exit Sub
        End If
        
        'primary Domain Controller Emulator is used to retrieve actual value of last bad password and last logon
        Dim strPDCEmulator: strPDCEmulator = EnumeratePDCEmulator
        Dim objUser: Set objUser = GetObject("LDAP://" & strPDCEmulator & "/" & Request.Get("distinguishedName"))
        Dim objLargeIntegerBadPassword: Set objLargeIntegerBadPassword = CreateObject("AelitaEDM.EDMLargeInteger")
        Dim objLargeIntegerLastLogon: Set objLargeIntegerLastLogon = CreateObject("AelitaEDM.EDMLargeInteger")
        objLargeIntegerBadPassword.Set objUser.Get("badPasswordTime")
        objLargeIntegerLastLogon.Set objUser.Get("lastLogon")
        
        'set values for virtual attributes on User form
        Set objUser = GetObject("EDMS://" & Request.Get("distinguishedName"))
        objUser.Put "edsvaBadPasswordTime", objLargeIntegerBadPassword.GetIADsLargeInteger()
        objUser.Put "edsvaLastLogonTimestamp", objLargeIntegerLastLogon.GetIADsLargeInteger()
        objUser.SetInfo
        Set objUser = Nothing
        
    End Sub
    
    Private Function EnumeratePDCEmulator()
    
        Dim objRootDSE, objDomain, strPDCEmulator, objNtds, objComputer
        Set objRootDSE = GetObject("LDAP://rootDSE")
        Set objDomain = GetObject("LDAP://" & objRootDSE.Get("defaultNamingContext"))
        strPDCEmulator = objDomain.Get("fSMORoleOwner")
        Set objNtds = GetObject("LDAP://" & strPDCEmulator)
        Set objComputer = GetObject(objNtds.Parent)
        
        EnumeratePDCEmulator = objComputer.dNSHostName
        
        Set objComputer = Nothing
        Set objNtds = Nothing
        Set objDomain = Nothing
        Set objRootDSE = Nothing
    
    End Function


    Powershell script:
    function onPreGet($Request)
    {
        # continue with flow only on User form    
        if($Request.Class -ne "user")  { return; }
    
        # verification of requested attributes
        if ($Request.IsAttributeRequested("AttributeOne") -eq $false -Or $Request.IsAttributeRequested("AttributeTwo") -eq $false)
        {
            return; 
        }
    
        # primary Domain Controller Emulator is used to retrieve actual value of last bad password and last logon
        $StrPDCEmulator = EnumeratePDCEmulator;
        $ObjUser = [adsi]("LDAP://" + $StrPDCEmulator + "/" + $Request.DN);
        $IntegerBadPassword = $ObjUser.ConvertLargeIntegerToInt64($ObjUser.badPasswordTime[0]);
        $IntegerLastLogon = $ObjUser.ConvertLargeIntegerToInt64($ObjUser.lastLogon[0]);
        $IntegerLastLogonTimestamp = $ObjUser.ConvertLargeIntegerToInt64($ObjUser.lastLogonTimestamp[0]);
    
        # define EDMLargeInteger objects, which are used to populate values for virtual attributes
        $ObjLargeIntegerBadPassword = New-Object -ComObject AelitaEDM.EDMLargeInteger;
        $ObjLargeIntegerLastLogon = New-Object -ComObject AelitaEDM.EDMLargeInteger;
        $DateTimeBadPassword = [DateTime]::FromFiletime([Int64]::Parse($IntegerBadPassword));
        $DateTimeLastLogon = [DateTime]::FromFiletime([Int64]::Parse($IntegerLastLogon));
        $ObjLargeIntegerBadPassword.SetDate($DateTimeBadPassword);
        $ObjLargeIntegerLastLogon.SetDate($DateTimeLastLogon);
    
        # set values for virtual attributes on User form
        $ObjUser = [adsi]("EDMS://" + $Request.DN);
        $ObjUser.Put("edsvaBadPasswordTime", $objLargeIntegerBadPassword.GetIADsLargeInteger());
        $ObjUser.Put("edsvaLastLogonTimestamp", $objLargeIntegerLastLogon.GetIADsLargeInteger());
        $ObjUser.SetInfo();
        $ObjUser = $null;
    
    }
    
    function EnumeratePDCEmulator()
    {
    
        $ObjRootDSE = [adsi]"LDAP://rootDSE";
        $ObjDomain = [adsi]("LDAP://" + $ObjRootDSE.defaultNamingContext);
        $StrPDCEmulator = $ObjDomain.fSMORoleOwner;
        $ObjNtds = [adsi]("LDAP://" + $StrPDCEmulator);
        $ObjComputer = [adsi]$ObjNtds.Parent;
    
        return $ObjComputer.dNSHostName;
    
    }