12 Replies Latest reply on May 23, 2017 3:01 PM by Smef

    Install On Timer Script ignores script parameter

    nilsw

      Summary

      Install On Timer Script ignores script parameter

      Product

      FileMaker Pro

      Version

      13.0v4 Advanced

      Operating system version

      Mac OS X 10.9

      Description of the issue

      If the Install On Timer Script script step is called with anything other than a static value as parameter, it is ignored when the timed script launches. This applies to passing script parameter by Get( ScriptParameter ) function or by $variable.

      Steps to reproduce the problem

      create a script A that shows a dialog with Get( ScriptParameter ) as message text, also call Install On Timer Script with empty values to reset the timer.

      create a script B that sets a $variable with "Hello World" and an Install On Timer Script that calls script A after one second, passing $variable as parameter.

      Actual result

      Dialog shows empty message. Also the script debugger shows clearly that script A launches without any parameter.

      Workaround

      none so far if you want to pass a non-static parameter.

      Untitled.png

        • 1. Re: Install On Timer Script ignores script parameter
          TSGal

          filemakergarage:

          Thank you for your post.

          The "Install OnTimer Script" script step will call a script at a specified interval.  When that interval occurs, the script executes.  Since the parameter you are calling is a local variable, the executed script will not have access to that local variable.  Therefore, change your script to use a global variable.  Your initial script should appear as follows:

          Set Variable [ $$variable ; Value: "Hello World" ]
          Install OnTimer Script [ "A" ; Parameter: $$variable; Interval: 1 ]

          Let me know if you need additional clarification.

          TSGal
          FileMaker, Inc.

          • 2. Re: Install On Timer Script ignores script parameter
            Smef

            I just found this response when searching after having the same problem. Your answer, TSGal, doesn't quite make sense, as local variables are never available outside of the scope of the currently running script, and the executed sub-script never has access to a local variable from the parent script, whether called by Install OnTimer Script or Perform Script.

             

            If I run the script Main as seen below:

             

            --Script: Main--

            Set Variable [$x; Value: 1]
            Perform Script ["sub"; Parameter $x]

             

            --Script: Sub--

            Set Variable [$y; Value: Get ( ScriptParameter )]

             

            The variable $y will have the value "1" as expected. The actual variable $x is not being passed and the subscript "Sub" does not have access to the variable $x. The parameter being passed is a calculation, and the result of the calculation (the number 1) is what (should be) is passed as a parameter.


            It seems to be that there is just some funny behavior with how script parameters are evaluated in FileMaker. It looks like they are not evaluated at the time the script step Install OnTimer Script (or probably Perform Script either) is called with the result of the calculation passed as a parameter as one would expect them to be, but are instead evaluated at the time the subscript is run with the context of the parent script. Since the parent script no longer exists once the OnTimer script is actually run the variables do not exist.

             

            This isn't a problem with using a local variable as a parameter within the general rules of how FileMaker works and programming works in general, but seems to be an odd behavior of how FileMaker actually calculates a script parameter. This is something that I believe should be considered a bug and addressed.


            EDIT: I've done some additional testing and this is exactly how it works. A script parameter calculation is not evaluated until the subscript is actually run, at which point is evaluated from the context of the parent script. I tested this by running Install OnTimer Script with a delay of 10 seconds and a parameter which included a plugin function to create a folder on my desktop. This allowed me to see when the calculation was actually evaluated. In this example the folder was not created until 10 seconds after the Install OnTimer Script step was executed, at the time the OnTimer script was run, meaning the script parameter wasn't evaluated until the subscript was actually run.


            This ends up being even weirder behavior if you use a field in your calculated parameter. The value of the field is not evaluated until the subscript is run, so you can call the script with a field with a specific value as a parameter, change the value of the field before the OnTimer script actually executes, and then see the new field value used in the subscript. Changing records, layouts, or editing a record can give you a different value for your script parameter from when you called it, which is totally incorrect behavior.

             

            This is definitely unexpected, unfortunate behavior for both Perform Script and Install OnTimer Script and should be considered a bug.

             

            What should happen: A calculated script parameter should be evaluated and the result of that calculation should be passed as a parameter.

             

            What is actually happening: The entire, un-evaluated calculation is passed as a parameter. The calculated script parameter is not evaluated until the subscript is run. The subscript then evaluates the calculation from the context of the parent script.

             

            EDIT 2: To clarify further, the script parameter isn't just a value that you're setting for the perform/ontimer script to evaluate at the time it is called (as that would be totally pointless). If this was the case you would never be able to use local variables from a parent script as a script parameter. FileMaker is actually "faking" evaluating the value at the time Perform Script or Install OnTimer Script is run by evaluating the parameter from the context of the parent script, but the delay with Install OnTimer Script makes this "faking" not work.

            • 3. Re: Install On Timer Script ignores script parameter
              alecgregory

              If I am understanding you correctly, which I may not be, I don't think there is a bug here.

               

              On Timer scripts are different to regular scripts. They are somewhat asynchronous and therefore they do not have parent scripts. And they are installed rather than performed.

               

              In practice this means that a script that is installed via the Install On Timer Script step will not launch until all other scripts in the stack have finished executing. This means that the script stack that exists when you run the Install On Timer Script step will definitely not exist when the script specified in the Install On Timer Script step runs. To put it another way, a script installed via the Install On Timer Script step is always a parent script and never a subscript.

               

              If you want a static parameter that remains constant for the life of the On Timer Script, use a global variable, global field or record data that you are confident will be static for the life of the timer. If you want a dynamic parameter, use a calculation that evaluates the condition at run time.

               

              Is there some other parameter scenario that isn't covered by the above?

              • 4. Re: Install On Timer Script ignores script parameter
                Smef

                On Timer scripts aren't any different than regular scripts and are not performed asynchronously from the script stack. If an OnTimer script would be triggered in the middle of execution of another script it waits until the completion of the script currently in progress to run.

                 

                You are correct, though, that it doesn't have a parent script like a script called with Perform Script would. The lack of a parent script shouldn't matter, though, as scripts don't have any knowledge of the script stack, their parent script, or their parent script's local variables.

                 

                EXCEPT

                 

                ...in the case of a script parameter. This is the really weird thing which I'm pointing out here. When a script parameter is passed the parameter's calculation is not evaluated until the child script is actually run. It is instead passed to the child script as an unevaluated calculation. When the child script is run, the parameter calculation is evaluated in the context of the parent script.

                 

                The script parameter calculation should be evaluated at the time the Perform Script or Install OnTimer Script script steps are executed and the result of that calculation should be the final value passed to the script being executed as the script parameter, but it isn't, which is weird.

                 

                 

                This isn't just a problem for variables, but getting field values as well as they are not evaluated until the OnTimer/subscript is actually called. It makes passing a field value also impossible (since it won't be the same when it's actually evaluated) and the fact that there is a parameter not useful, as it gives you no more features than a regular script step within the script. Why pass a calculation as a parameter if it will give you the same thing as a script step within the script?


                I've uploaded a sample file that demonstrates this unexpected behavior and the delay in evaluation which happens.

                • 5. Re: Install On Timer Script ignores script parameter
                  alecgregory
                  On Timer scripts aren't any different than regular scripts and are not performed asynchronously from the script stack.

                   

                  I am fairly confident that this is not the case. The OnTimer script does not run until the entire script stack it is called from resolves. That includes subscripts called after the install On Timer Script step and parent scripts of the script that runs the Install On Timer Script step. You can see this behavior clearly in the Script Debugger, assuming you are using Pro Advanced. This is why all the variables are gone by the time the On Timer script starts and why the script parameter is not evaluated until after the stack has resolved. You have not "Performed" the On Timer script, you have just "Installed" it, which means you have indicated that you want it to run after the current script stack completes with the specified parameter evaluated at run time.

                   

                  In any case, for the test file: If you want to see the id of the record you were looking at 2 seconds ago, just use a global as TSGal suggested earlier in the thread:

                   

                  Screen Shot 2016-12-12 at 5.10.50 PM.png

                   

                  This uses the the state of the parameter calculation at installation time, rather than run time.

                  • 6. Re: Install On Timer Script ignores script parameter
                    Smef

                    FileMaker scripting doesn't do anything asynchronously or in a multi-threading way (other than soooort of Perform Script On Server without "wait for completion" selected). OnTimer scripts aren't part of the same stack, as you said, and are executed afterwards, but if they were executed asynchronously they would be run "asynchronously," (at the same time) while another script is already in progress and could both be running at the same time, but in a different thread and wouldn't need to wait until the main stack. Instead, OnTimer scripts aren't run until after the currently running script stack is competed, which is the opposite of asynchronous as the script must wait for the first one to finish. We may just be having a programming terminology discussion here, which we don't need to do as it's clear we understand when OnTimer scripts are run.

                     

                    I also understand the work-around for this, so there's not a problem with getting the desired end-result to work.

                     

                    The issue being brought up here is that FileMaker handles script parameters in a very odd, unexpected way that doesn't seem match conventional programming's standard order of operations. This is really some odd FileMaker behavior rather than a bug that needs to be fixed, but it would make sense to change this behavior in a future version of FileMaker to more closely match how a software developer might expect a calculation to be evaluated.

                    • 7. Re: Install On Timer Script ignores script parameter
                      alecgregory

                      Perhaps non-synchronus is a better term: the script specified in an on timer step does not get executed right away, and that is unusual for FileMaker. It was not clear that you had grasped that but now I see that you had.

                       

                      I don't see how you could maintain FileMaker's scoping rules and change the behaviour as you suggest. Where would the literal value of the parameter be stored in the dead time between installation stack completing and the run stack starting?

                      • 8. Re: Install On Timer Script ignores script parameter
                        Smef

                        The thing that what we're pointing out here is that this is a place where FileMaker currently ISN'T following its scoping rules. This is exactly what the problem is. If it followed the scoping rules this wouldn't be a problem here. A script being run, either by Perform Script or Install OnTimer Script shouldn't have any knowledge of any local variables outside of its scope (which is just the script itself), yet clearly it is depending on the script stack to evaluate the parameter. Parameters are being evaluated outside of a scripts normal scope, which is the problem.

                        Screen Shot 2016-12-13 at 12.46.21 PM.png

                         

                        I don't have the source code of FileMaker to suggest which blocks of memory the value should be stored in or which classes in the source code need to be edited, but the evaluated result of the script parameter calculation should be handled right along with the name (or ID or whatever) of the script that is being triggered after however many seconds.

                        • 9. Re: Install On Timer Script ignores script parameter
                          alecgregory

                          What you are saying makes sense only if you are still holding on to the idea that Installing a script is the same as performing it. Saying you want to install a script is the same as saying:

                           

                          1) After this script stack is finished, create an anonymous virtual button that is automatically present on all layouts visited in the current window

                          2) Assign a script to that button, with an optional parameter, just as you would with a regular button

                          3) Virtually press the virtual button as soon as the current script stack is finished* and repeatedly at the specified interval until the window is closed or the on timer is uninstalled

                           

                          The optional parameter attached to the virtual button behaves just as a parameter attached to a regular button would, it evaluates at the time the button is "pressed". To bind that parameter to an install-time state you can use a global variable. I see no need to remove the dynamic behavior in this instance. On Timers add functionality. The change you suggest would limit this functionality.

                           

                          *unless something in that script stack causes this window to close or the timer is uninstalled (via Install Timer with no script attached)

                          • 10. Re: Install On Timer Script ignores script parameter
                            Smef

                            Installing the script is definitely not the same as performing it, but in either case I would expect the parameter to be evaluated before the script is run, not at the time it is run, and evaluated within the current scope.

                             

                            Your description of how the Install OnTimer Script step works seems to be pretty accurate, and makes its behavior match the behavior of the Perform Script script step, which is good. Those two things should work pretty much the same way.

                             

                            At the same time, it makes buttons with Perform Script seem to have a weird scope. If you run a script, put a pause in the script, and then click a button you can use a variable from your paused script as a parameter for your button. This seems odd to me, as I would expect the button not to have any knowledge or way of interacting with the paused script stack, yet it's able to access the scope of the paused script.

                             

                            I think the way FileMaker handles scope is just a little different than I and some others may expect, and ends up explaining all of this behavior. Scope for a local variable isn't just within the script the local variable is defined in like you might find with a local variable in another programming language, but that local variable is available to lots of different things while the script it is defined in is the currently executing script in the script stack.

                            • 11. Re: Install On Timer Script ignores script parameter
                              jormond

                              I understand the issue you are referring to. I ran into this issue a couple weeks ago. A couple of thoughts:

                               

                              1. A local variable can indeed exist outside of a script. Let statements in conditional formatting or hide calcs can set them. Though they are not available to the script to use.

                              2. Because the originating script completes before the OnTimer script starts, the value in the variable is cleared. The script passes the variable in a non-evaluated state, because the variable could change before the OnTimer script actually runs.

                               

                              Set Variable [ $$var ; 1 ]

                              Install OnTimer Script [ "scriptName" ; parameter: $var ; Interval: .1 ]

                              Set Variable [ $$var ; 2 ]

                               

                              Which value should it use in the OnTimer? FMI says 2. To go the other route and evaluate at the runtime of the step, well, that would seem to break a lot of other principles that function in FM. Typically, the evaluation of variables happens as they are needed. I wouldn't expect that behavior to change.

                              1 of 1 people found this helpful
                              • 12. Re: Install On Timer Script ignores script parameter
                                Smef

                                Yeah, local variables are a bit larger than just local to the script they're in, which is a bit odd when compared to other programming languages, but it explains everything being discussed in this thread.