While Triggering Macro is executing

Hi!

Is there any way to set up a condition for While 'Triggering Macro' is executing?

I've been trying to create a progress bar that loops for visual confirmation while a long running macro is running. (Primarily for long running scripts without individual steps that would otherwise be displayed well by the KM11 Group action display progress feature).

My macro's core functionality is working quite well, and I am implemening this feature into the long running macro, as an Execute Macro action that (asynchronously) runs the Looping progress bar macro while the triggering macro runs.

But (and here comes the actual question) is there any way to set up a condition that I would not have to reset for each macro where I'd like to display my looping progress bar? Similar to the behaviour I'd get if the field (pointed out by the green arrow below) could be set to "Triggering Macro":

Macro status looping progress bar Macro (v11.0.1)

Macro status looping progress bar.kmmacros (6.4 KB)


(Used @cdthomer's macro as example here while testing my macro, as it was a long running script-based macro I had at hand)

(By the way: I realized while creating this thread (through the forum's existing thread suggestion feature) that @vincent_ardern have already pretty much created the macro I've been working on. But there there is no indication in his thread that he have a solution for the 'While Triggering Macro is executing' challenge so this here thread's main question stands.)

Have your long-running macro set a global variable to “running” at the start and reset the variable to empty just where it completes. Then your progress-displaying macro can test the global variable so that while it contains “running” it knows and can do its stuff.

2 Likes

This is such a simple solution! Embarrassingly simple, haha. Here I’ve been reading up on executing macro parameters and all kinds of tokens, scratching my head and testing different solutions …

I think I was also stuck in the idea of implementing this feature into macros as a simple step, a macro or group, at the very top. Also adding the step at the very end is of course no real compromise. But as I’ve been plundering with this for a bit I’d also be very interested in further input and other takes on how this challenge could be tackled!

1 Like

Like you I started thinking on using the executing macro UUID somehow then realised that a simple global variable would do the job. Ironic really since I normally go out of my way to avoid using globals.

I’m sure some bright spark can make this more complicated :wink:

1 Like

I’m thinking put the whole progress timer into a subroutine, and set a parameter of the subroutine to the token %Executing Macro% when calling the subroutine. Save that as a favourite action. Then the subroutine knows the calling macro. Or we could leave it simple but where’s the fun in that…?

2 Likes

Hmm, this sounds like an interesting approach! But as explicit Subroutines is a part of KM I have not yet delved into I must admit that I am a bit confused here.

I am exited though to try to use this here case as way to learn the very basics Subroutines!

First thing I am a bit confused about is just where to add the %ExecutingMacro% as a parameter.
This field is a Variables-field and does not take tokens directly.

I could of course add the token into a variable, but I can's seem to get my head around where to set this variable from for it to be updated as the long-running is finished.

And with putting the whole timer into a subroutine, you mean to engroup it as a Macro, right?

Screenshot 2023-11-14 at 16.14.54

Agreed! Mastering complexity is fun! But there is of course also allot of fun to be had with the challenge of making a macro as simple as possible — In this way the quest for simplicity brings with it it's own sett of interesting complexities!

And on the note of exploring the subject of simplicity: I now today learned (through @Airy's OCR-timing macro) what might very well be the simplest way to display a looping oscillating progress bar while a macro is running: Through KMs very own Display Progress Action, of course! It have a handy little built in feature to oscillate when set to a value below zero.

Display Oscillating Progress Bar While Macro is Running Macro (v11.0.1)

Display Oscillating Progress Bar While Macro is Running.kmmacros (1.8 KB)

Macro Image

However the discovery of this very simple way, of doing what I originally set out to do, will not halt my new challenge to learing how to use Subroutines to solve the same task. (I guess I am not the only one that spends time in the KM-editor, building macros, not only as a means to solve productive tasks, but also in the sole interest of learning this amazing application better, and having fun while doing so?)

That's the spirit! ... although technically that's a "dual interest."

2 Likes

%ExecutingMacro% should go into the action that calls the subroutine, not the subroutines triggers :slightly_smiling_face:

Good point. I missed that. But also, don't forget that there's no need to even pass the value of %ExecutingMacro% to a subroutine, because the value of %ExecutingMacro% doesn't change in a subroutine, it remains the same as it was from the calling macro.

Huh, thanks

Thanks, makes sense.

Using an actual Execute a Subroutine action makes this more clear:

For some reason I was confused into thinking that the Engroup > Macro would leave me a Execute a Subroutine action, while it, logically, leaves an Execute a Macro action. I think I was confused by reading a forum post from before KM10 or something. Execute a Macro was/is also often referenced as performing a subroutine, all though Subroutines now after KM10 also have a more explicit meaning.

This is what I've now experienced while testing here also.

Am I then right in thinking this Subroutine method will not work the way we where hoping here (to emulate 'While Triggering Macro is executing'-behaviour)? Or is there any way to make a parameter like this to update when the calling macro is done executing? (Without it being explicitly done so by setting the variable again as an action at the very end of the calling macro)

EDIT: And another reason I’ve come to realise for why Subroutines will probably not work in my originally described use case: Subroutines cannot be run asynchronously.

That's an important point.

Specifically, I couldn't understand your core question, "is there any way to set up a condition that I would not have to reset for each macro where I'd like to display my looping progress bar?"

Based on your realization that subroutines cannot run asynchronously, I think you are beginning to understand why a single progress bar spanning multiple calls to the same subroutine isn't a meaningful request. Macros can be called asynchronously, but you aren't asking about that.

1 Like

I do agree that this core question does not make sense now, as my looping progress bar example now does not make sense after having learned (through your OCR-timing macro) a much simpler way of obtaining this. And the explicit Subroutine-route now seems like a blind alley.

However I am not sure I agree that wanting to implement into macros a subtask (not necessarily an explicit Subroutine) of asynchronously doing something while the rest of the macro does it's thing, is inherently meaningless (but do elaborate if I am missing your point here, I really do want to wrap my head around this). I was able to achieve this ‘Asynchronously While'-behaviour by setting the while conditions in the asynchronously executed macro as displayed in the green rectangle in my first image. But as I at the time of creating this thread imagined wanted to implemetn this looping progress bar Submacro into numerous other macros, I was looking for a way to implementing it without effectively having to make a new copy of the Submacro, and reseting the while condition for the calling/triggering macro, every time I implemented it. This is why I was looking for the behaviour as if that while condition (pointed out by the green arrow) could be set as "triggering macro" or the like.

As @tiffle pointed out, there are workarounds, so I guess we are pretty much at ways end, but I've not yet been able to fully shake the feeling that this 'While Triggering/Calling Macro is executing' could be useful also in other situations (all though I am not here in this moment able to come up with a better example than the original looping progress bare one).

I realised now that I actually had stumbled upon another example of a macro that would take advantage of the 'While Triggering/Calling Macro is executing'-condition/behaviour.

Example form link

Coincidentally also a bit of a weird example, but if I wanted a Submacro that presses the OK button of the Prompt for snippet-window in several different macros; it seems to me that I would then need to hold a separate copy of the Submacro for each of it's implementations.

@tiffle's workaround would also not work here as the Prompt for snippet action cancels the whole macro if cancel is pressed.

I had to ponder your idea for a few minutes.

As I said earlier, when you use the token %ExecutingMacro% from a macro or one of its subroutines, the data it returns is always the same.

But in this example of yours, you are spawning the sub macro asynchronously. I had to ponder that for a few minutes, and realized that I had to test that to be sure what it does. And sure enough, that token no longer returns the name of the parent macro, but now it returns the name of the asynchronous macro. So my generalization was wrong, because that token returns a different value if the macro is run asynchronously. Now the question is, does this help you? I don't think so. What you need is a link to the parent calling macro.

I didn't mention this to you earlier because I didn't think it would solve your problem, but there is another token called %MacroNameForUUID%. Instead of returning the macro's name, it returns a unique string that is unique for each instance of the macro that runs. If you pass this string from the calling macro to the asynchronous sub macro, that may solve your problem. In that case, the asynchronous sub macro can potentially learn when the calling macro has completed.

However I don't see a conditional test within KM that will let you test for the existence of an instance/process using this UUID. However these UUID's are probably generated from macOS and therefore I'm sure there must be a test using AppleScript or Shell commands that will check if this process still exists. I will ponder this further, but I would prefer if someone more familiar with this UUID step forth and explain how a macro can test if a process with a given UUID can be checked for completion.

1 Like

Why do you want to press the ok button programmatically? I feel with more context we might be able to simplify this for you.

1 Like

Thank you so much for pondering on this with me!

Yes, and more particularly, a link that changes the moment the calling macro is no longer executing.

Or if I understand it correct that specific token returns the Macro name from a UUID, but it definitely feels like UUID might be part of the/a solution here! Only problem is how to check from the Submacro if the calling macro is still executing. Through my testing with the UUID-tokens, I have so far not been able to set it up in a way for this to be possible.

If there only where a way to return a list of all currently executing instances, (or I guess a list of names of currently executing macros would also be sufficient), and then recheck that list for each run of the loop to see if the parent macro instance/name is still on the list. (Mostly just repeating my understanding of what you've already written here.) But I realise now that I actually do not know how KM is handling different macros executing at he same time. Are there only one instance ran at any one moment (I guess then cycling through instances if macros are ran on top of each other), or are they ran parallelly in any way? (As probably becomes very evident through my wording here, I have no programming background, nor any programming experience outside KM.)

But AppleScript or Shell, I think you are right in that a solution can be found in this direction. I sadly have next to zero understanding of AppleScript, and absolute zero understanding of Shell. But yes, maybe someone with deep understanding of these languages can come to the aid here!

I don't, but @ronald from the thread I linked to wanted that. He ended up finding a different solution, but through my proposition for how to solve it emerged another useful example for this thread.

As it stands I actually do not have a practical/productive use case for the behaviour I am seeking, and this threads goal is now solely to seek deeper understanding of KM (and having fun while doing so (which makes ut a dual goal, as pointed out by @airy, haha!)).

I am struggling a bit to concisely and formally formulate just what the result I am seeking is; but in my eyes, and through my programatically illiterate wording, it again boils down to the behaviour one would get if that condition in the While-action (pointed out by the green arrow in my first post) could be set as "triggering macro" / “calling macro” / “parent macro” or the like.