While Triggering Macro is executing

Your terminology is wrong there. Every time a macro is triggered, an "instance" is created. If the same macro is initiated five times, then as long as they don't exit before the next copy runs, you've got five instances running, which happen to be the same macro.

That's why I told you about %MacroNameForUUID%.

That's why I asked for others to assist with this question, because I don't know either. There doesn't seem to be a mechanism in KM itself.

No, that would not be sufficient, because you would not be able to tell from that list which one was the caller.

That's the very definition of an instance. An instance is a new process which by definition is running in parallel. There's no such thing as two instances that are not in parallel of each other. Although now that I've said that, the whole point of semaphores is to synchronize two instances.

That's why I asked for help here. Or, maybe just give me more time to research.

1 Like

Thank you for the clarification about the terminology here. Still a bit confusing to me though. The processes that goes on backstage here are especially foreign to me, but I'll slowly learn more and more. Also again many thanks for continuing to ponder on this crooked subject with me!

About the %MacroNameForUUID%, I still do not understand why this token in particular would be useful. From the testing I’ve done so far it returns the Macro Name from a UUID regardless if the macro is currently executing or not. I’ve only gotten it to return the “Not found” if I delete the macro the UUID was from. But am I missing your point in how this token could be useful?

The way I was thinking was to set a variable to %ExecutingMacro% in the calling macro before asynchronously executing the Submacro, that could then later, for each run of the loop, be searched for to check if it is still present in a list of currently executing macros. But using the UUID would anyways be more precise.

Anyone reading this post should stop now, because inside this post I explain why I'm wrong. I will attempt to find the correct answer and post it later. I'm very sorry, and a little embarrassed about being wrong.

No! Not at all! It doesn't return anyone else's UUID, it returns your own UUID. That's why I said you had to pass it down to your asynchronous process from the parent one. It's the name of the parent process, but the only way the child process can get it is if you pass it down when you spawn the child process.

EDIT: I probably shouldn't write answers when I wake up first thing in the morning. Let me review that statement before you believe it. I'll be back soon. I'm preparing an improved answer. Please forgive me for being wrong. CORRECTION: I had made two mistakes, the first mistake was giving you the wrong token name. The token name that I had intended to give you was %ExecutingMacroUUID% but even that isn't quite right because the name is misleading, it doesn't return the UUID for the macro running, it returns the UUID for the instance running, which still isn't what we want. I need to dig deeper to find a token that returns the UUID of the current macro, not just the UUID for the instance. There are more macros, but I have to examine them closely.

No! Not at all! The child process already has access to %ExecutingMacro% because that token doesn't change when you spawn the child process. There's no point in saving something that the child process already knows.

Also, I should add a minor complexity at this point... If Macro A calls Macro B which calls Macro C, then both macro B and C return the value "A" when evaluating the token %ExecutingMacro%. That's because the token only returns the name of the macro that was "triggered" by the Engine. It's not really returning the name of the parent unless the parent was also the macro that the Engine triggered. In your case, I was assuming that you had only two, not three macros, in the stack. And I was probably correct about that assumption.

Okay, this is crazy, but I think I've found the solution!
In the wiki I found the token %ExecutingInstances%, and it returns a commaseparated list of all current instances!

test_While calling macro is executing Macros.kmmacros (4.6 KB)

Macro Images

I am sorry for the mistakes above. Ignore my discussion of tokens above.

But I do have a lead I'm working on. Each asynchronous process created by the KM Engine should be visible as a line of output to the command line command "ps -ax" but so far I haven't been able to spot it. This is perplexing me.

There's another lead that you may already know about. You can set a global variable at the end of the calling macro to tell the spawned macro when it is finished. That will work 100% guaranteed. But I like to investigate alternate solutions, just as I think you like to do.

1 Like

I took a long look at the token you are using, but I couldn't find a way to make it work. I will examine your solution after lunch.

1 Like

Very curious to hear your thoughts on this solution! I might be missing something, but as of now it seems to be able to do what I wanted

And do not at all worry about giving the wrong token name, I had a feeling that this was part of my confusion, and it anyways set me out on an exploration of a token I had yet to explore!

Before you posted your solution, I was looking very carefully at those tokens. The documentation said the entires are "Opaque IDs" and I spent a half hour trying to find a definition for them. The KM docs don't seem to define that term. I was googling it and couldn't find a clear and simple explanation. If your code works, then I can't deny that it does what you want.

But bear in mind that this isn't really any different from setting a global variable manually, as I suggested earlier. You are still using a global variable. What's more, you are using two global variables. One thing you could do to improve this macro is replace your second global variable by a local variable. That could prevent a bug whereby two separate macros are referring to this global variable. Moreover, you may also want your first global variable to be modified to a local variable and pass its value to the second macro. Doing this will make your code more robust from failure, and it will also ensure that there are no global variables cluttering your environment. If you don't want to change that, then you may at least want to delete the global variables after you do this. Generally speaking, a saved value that's no longer needed should be cleared or deleted.

I also couldn't understand what "Opaque IDs" meant, but that it where suppose to return a list of instances made me intrigued enough to give it a go.

The global variables was mostly a product of me usually working with global variables while developing a macro; swapping them out with local ones while finalising it after getting it all working properly. I was so exited earlier when a solution, after days of pondering, finally seemed to emerge, that I posted it right away, haha. And good idea about passing the %ExecutingInstance% from the Calling macro as a parameter, first didn't think of that!

It does seem to work for me, and have performed well through my tests so far, but I'd be very interested in hearing more of your thought about the shortcomings of this macro in its present state. I am all interested in improving it further!

Here is my cleaned up version of the macro as it stands now. And as the thread progressed complexity beat simplicity, so hope you are okay, @tiffle, with me moving the Solution-tick to this post, until it is dethroned again by an even more complex solution, haha!

Now set up demonstrating an oscillating progress bar, with a 5 second pause in the Calling macro simulating a time consuming task. The progress bar can simply be implemented into any macro by copying the magenta coloured action to the head of any macro to perform tasks while the calling macro is executing. The red actions in the Submacro can also be swapped out with all kinds of useful tasks one might want to perform asynchronously while (or after) a calling macro is executing.

As of now I do not have many ideas on other use cases for this approach, all though I am sure there must be many, haha! I’d therefore also be thrilled to hear any ideas on how this approach could be implemented, to perform other (maybe even more useful) tasks than the oscillating progress bar it now performes!

While Calling Macro is Executing – CALLING v1.2.0.kmmacros (2.0 KB)
While Calling Macro is Executing – SUBMACRO v1.2.0.kmmacros (5.4 KB)

Macro Images

Edit: Realised that a Semaphore Lock would be good here, if the Submacro where to be called by different macros at once. Therefore uploaded a new version of the macro implementing this. Also uploaded the two macros separately this time.
Edit2: Found a way to improve the macro, so moved the Solution-tick to post #31

Where actually here now able to create a simplified version of this macro not using any variables whatsoever!

While Calling Macro is Executing – CALLING v1.3.0.kmmacros (2.0 KB)
While Calling Macro is Executing – SUBMACRO v1.3.0.kmmacros (4.4 KB)

Macro Notes

(Keyboard Maestro v11.0.1)

In the uploaded state the macro is set up demonstrating an oscillating progress bar, with a 5 second pause in the Calling macro simulating a time consuming task. The progress bar can simply be implemented into any macro by copying the magenta coloured action to the head of any macro to perform tasks while the calling macro is executing. The red actions in the Submacro can also be swapped out to do other task one might want might want to perform asynchronously while (or after) a calling macro is executing.

Moving the Solution-tick to this post now — Once again simplicity beats complexity!

In tips and tricks territory here now, but set up in a similar way this approach can also be used to set the conditions for a Pause Until-action:

Pause Until Calling Macro is Done Executing – CALLING v1.0.0.kmmacros (2.0 KB)
Pause Until Calling Macro is Done Executing – SUBMACRO v1.0.1.kmmacros (4.3 KB)

Macro Notes

(Keyboard Maestro v11.0.1)

For demonstrating purpose the macro is in it's uploaded state set up with an oscillating progress bar, with a 5 second pause in the Calling macro simulating a time consuming task.

Macro Images

1 Like

To clarify, if I have a Macro that repeats 100 times (for simplicity), Which Macro do I add those actions to, and where within that Macro so that my progress is correctly calculated and displayed? I pasted in place of the 5-second pause and got a number displaying 7,100, which stayed halfway complete (per the animated visual bar) until the pasted Actions/Macro was complete. I appreciate your diligence in delivering the final anticipated result, but I'm waiting for your response instead of trying to deconstruct on a time crunch for this task completion :smiley: I certainly look forward to using this in every macro #ADHD :rofl:

Hi!

You could in theory just download both the macros (CALLING and SUBMACRO) from post #31, and paste the magenta colored action from the CALLING macro as the first action of any macro you'd want to display an oscillating progress bar, indicating that it is currently running. But doing this into every macro will in practice probably cause having many overlapping instances where macros are calling this SUBMACRO simultaneously.

The way it is set up now the Semaphore Lock at the head of the SUBMACRO would prevent this by canceling any instance of the SUBMACRO being run on top itself, whilst also returning an error message. This error message can be turned off, by right clicking the semaphore lock and unselecting "Notify on Timeout". Then the first macro CALLING for an oscillating macro would get it, and any overlapping macros triggered after the first would not — first come first served.

I did however try here now disabling the Semaphore Lock completely, while having numerous macros run on top of each other, each CALLING for this progress bar. This also kind of worked, only sometimes displaying slightly glitching/blinking progress bar text when run on top itself. So after this test I am now thinking that the Semaphore Lock is not really necessary at all in this case.

If your macro is simply repeating, literary utilising the Repeat action, you can display a correctly calculated progress bar simply by right clicking the Repeat action selecting "Display Progress".

Display Progress

Other times it can also work to simply wrap all your actions in a Group action, right clicking and selecting "Display Progress" in this same way.

In other cases where you'd want to display a correctly calculated progress value, not simply displaying an oscillating bar, it can become allot more complex. In this case it might be better if you ask your question in a new thread, and I'd happily try to help you there. Because I do not as of now understand the behaviour you are explaining above, and imagine it quickly progressing into something outside this threads scope.

As this thread progressed it wound up being less about the progress bar and more and more about setting up the conditionals to give the behaviour of 'While Triggering Macro is executing'. This especially after I found a much simpler way of displaying an oscillating progress bar than the crazy mess I started out this thread with. For demonstrating purpose the oscillating progress bar just got along for the full ride of the thread, but the 'While Triggering Macro is executing'-behaviour have also proven useful for other situations. The solution from post #31 is however a perfect viable way of displaying a progress bar, and I use ut in a number of my macros.