The script could not be executed because the maximum number of nested scripts was exceeded

Hello guys,

For the context : I would like to know who was the last person who changed a certain property.

For this, I created an Event Handler (AfterSetProperties) where I get my current user and check if the property was changed based on its previous version

Option Explicit

' Get the required properties for this script
Const CLASS_PROPERTY = 100 'Class Property
Const DOCUMENT_OBJECTTYPE = 0  ' Document Object Type

Dim PropertyValues : Set PropertyValues = Vault.ObjectPropertyOperations.GetProperties( ObjVer, True )

'If the object is a document and belongs to the "Document test" class
if( ObjVer.Type = DOCUMENT_OBJECTTYPE) and (PropertyValues.SearchForProperty(CLASS_PROPERTY).TypedValue.DisplayValue = "Document test") then

Dim employesDisplayValue : employesDisplayValue = PropertyValues.SearchForProperty(EMPLOYES).TypedValue.DisplayValue

	if NOT(employesDisplayValue="" AND ObjVer.Version > 1) then	
		dim previousVersion : previousVersion = (ObjVer.Version - 1)
		Dim newObjVer : set newObjVer = CreateObject("MFilesAPI.ObjVer")
		newObjVer.SetIDs 0, ObjVer.ID, previousVersion
		Dim previousProperties : set previousProperties = Vault.ObjectOperations.GetObjectVersionAndProperties(newObjVer).Properties
		dim previousEmployes : previousEmployes = previousProperties.SearchForProperty(EMPLOYES).TypedValue.DisplayValue
		if NOT(employesDisplayValue=previousEmployes)then
			Dim oLookup: Set oLookup = CreateObject("MFilesAPI.Lookup")
			oLookup.Item = currentUserID
			oLookup.ObjectType = 6
			Dim propValLoggedUser : Set propValLoggedUser = CreateObject("MFilesAPI.PropertyValue")
			propValLoggedUser.PropertyDef = USER_TEST	
			propValLoggedUser.TypedValue.SetValueToLookup oLookup
			Vault.ObjectPropertyOperations.SetProperty ObjVer, propValLoggedUser
		end if
	end if
End if

When i'm testing the script, I'm getting this error : 

  • AfterSetProperties::DocumentTestModifiedBy, 36, The script could not be executed because the maximum number of nested scripts was exceeded. (0x80040969)

I've already checked the execution order : and i'm pretty sure that's the event handler i need to use.

Any help will be very appreciated Slight smile

Thank you very much
Claudio - EVOK - Altern8 SA

  • It is possible to increase the maximum number of scripts in Advanced Vault settings, but be careful and only increase in modest numbers if you are absolutely certain that is what you need. Otherwise you may allow the server to run endlessly if your scripting leads to a loop.

    I have not checked your code for errors!

  • It looks as if the following statement:

    Vault.ObjectPropertyOperations.SetProperty ObjVer, propValLoggedUser

    will cause an endless loop because this row of code will trigger the same event.
    In order to prevent endless loops there is such a mechanism. Changing this configuration of the server is highly dangerous.
    Maybe you should think about setting up an external log file.

  • Your statement seems completely logical to me however it is contradictory compared to the official documentation of M-Files which indicates:

    The event handlers are executed when the property values of the object stored in the document vault are re-set. Properties can be inspected during BeforeSetProperties before they are set. It is not, however, recommended to modify properties during BeforeSetProperties as they may be overwritten after the event handler has been executed. Properties, on the other hand, can be modified during the AfterSetProperties event.

    Available Event Handlers

    If you have any recommandations on this, i'll take them :)

  • Hi Claudio_Leitao,

    If I understood your idea correctly, you want to support an Employee who last changed something in the document. I have no idea how you can isolate a property and keep track of who changed it. But in general it can't happen the way you started, because as I said, it causes an endless cycle. I enclose a script that can give you some ideas

    'Setup some constants
    Const ForReading = 1, ForWriting = 2, ForAppending = 8
    Const Class_Property = 100 'Class Property
    'Define Log path (Feel free to change it)
    LogFolderPath = "D:\M-Files\Temp\log\"
    BuildFullPath LogFolderPath
    'Get All Property Values of Current Object
    Dim oPropVals: Set oPropVals = CreateObject("MFilesApi.PropertyValues")
    Set oPropVals = Vault.ObjectPropertyOperations.GetProperties(ObjVer)
    'Setting name of log we Using Class Name of Current object as part of LogName
    LogName = oPropVals.SearchForProperty(Class_Property).TypedValue.GetValueAsLookup.DisplayValue
    LogEH = "AfterSetProperties"
    'It is better to use aliases instead of id (Please change them with yours)
    Dim iCLTestDocument : iCLTestDocument = Vault.ClassOperations.GetObjectClassIDbyAlias("CL.TestDocument")
    Dim iPDLoggedUser: iPDLoggedUser = Vault.PropertyDefOperations.GetPropertyDefIDByAlias("PD.LoggedUser")
    'A test like this is enough to limit execution to a given class 
    If oPropVals.SearchForProperty(Class_Property).TypedValue.GetValueAsLookup.Item = iCLTestDocument Then
    	WriteLog "INFO", LogFolderPath & LogName, LogEH & "; " & ObjVer.ID & "; CurrentUserID: " & CurrentUserID
    	Dim oLookup: Set oLookup = CreateObject("MFilesAPI.Lookup")
    	oLookup.Item = currentUserID
    	'I don't know what type 6 you have, but it's not needed for test purposes 
    	'oLookup.ObjectType = 6
    	Dim propValLoggedUser : Set propValLoggedUser = CreateObject("MFilesAPI.PropertyValue")
    	propValLoggedUser.PropertyDef = iPDLoggedUser	
    	propValLoggedUser.TypedValue.SetValueToLookup oLookup
    	WriteLog "INFO", LogFolderPath & LogName, LogEH & "; " & ObjVer.ID & ";=== Before set CurrentUserID: " & CurrentUserID
    	Vault.ObjectPropertyOperations.SetProperty ObjVer, propValLoggedUser '<=== This is problematic because it performs "AfterSetProperties EH" again and causes an endless loop as I said 
    	WriteLog "INFO", LogFolderPath & LogName, LogEH & "; " & ObjVer.ID & ";=== After set CurrentUserID: " & CurrentUserID	
    End If
    'Functions and Procedures 
    Sub BuildFullPath(ByVal FullPath)
    	Set oFSO = CreateObject("Scripting.FileSystemObject") 
    	If Not oFSO.FolderExists(FullPath) Then
    		BuildFullPath oFSO.GetParentFolderName(FullPath)
    		oFSO.CreateFolder FullPath
    	End If
    	Set oFSO = Nothing
    End Sub
    Function TimeStamp
    	TimeStamp = PadDigits(Year(Date),4) & "-" & PadDigits(Month(Date),2) & "-" & PadDigits(Day(Date),2) & " " _
    		& PadDigits(Hour(Time),2) & ":" & PadDigits(Minute(Time),2) & ":" & PadDigits(Second(Time),2)
    End Function 
    Sub WriteLog (LogType, LogName, LogMessage)
    	Set oFSO = CreateObject("Scripting.FileSystemObject")
    	LogFileNameWithPath = LogName & "_" & PadDigits(Year(Date),4) & "-" & PadDigits(Month(Date),2) & "-" & PadDigits(Day(Date),2) & ".log"
    	Set LogFile = oFSO.OpenTextFile(LogFileNameWithPath , ForAppending, True)
    	LogFile.WriteLine(TimeStamp & "; "& LogType & "; " & LogMessage)
    	Set oFSO = Nothing
    End Sub
    Function PadDigits(val, digits)
    	PadDigits = Right(String(digits,"0") & val, digits)
    End Function

  • Hello everyone, 

    At the end, I proposed the client to send him an email or write the "Modified by User"  into a log file.
    Like said, the followed statement : Vault.ObjectPropertyOperations.SetProperty ObjVer, propValLoggedUser --> Creates an inifnite loop.

    Thanks one more time to for his contribution :)

  • Perhaps a bit late, but have you tried running your script in an 'BeforeCheckInchangesFinalize' Event Handler?

  • Hey there,

    I think i've tried it, and didn't work.