The topic discussed below is a bit esoteric, but will likely help some users avoid a common pitfall that can occur when modifying submacros and subroutines. So after sufficient sleep and your morning cup of coffee, consider reading this tutorial.
Introduction
If an updated version of a submacro/subroutine is properly installed, the links from the macros that call them will be automatically shifted to the updated version of the submacro/subroutine.
In contrast, if the updated version is installed before the older version is deleted, the caller links will not be shifted.
Let's discuss this possible disassociation and propose some safeguards.
Submacros and Subroutines
In the Keyboard Maestro wiki, submacros are referred to as traditional subroutines. Here's a excerpt from the wiki:
In Keyboard Maestro, traditionally subroutines were implemented with the Execute a Macro action, passing a single parameter to the %TriggerValue% token, and returning results in instance or global variables.
In version 10.0, Keyboard Maestro adds an explicit Subroutine trigger which lets you specify the parameters by name, and whether the macro returns a value via the Return from Subroutine action. Such subroutines are called with the Execute a Subroutine action.
In the remainder of this post, the term sub will refer to both.
Potential Issue When Sharing Subs On This Forum
When creating macros for myself, I often put reusable actions in subs. When sharing macros on this forum, however, I've typically avoided using them because they can be problematic, not when sharing Version 1, but when new versions need to be subsequently shared.
Here's a scenario that causes a problem:
-
You share Version 1 of sub on the forum. This distribution could include one or more calling macros.
-
A user downloads and installs your sub and calling macro(s).
-
The user uses your sub and calling macros. The user might also create their own calling macros that leverage your sub.
-
You share Version 2 of sub on the forum. In this example, there's no need to change the calling macro(s).
-
The user downloads and installs Version 2 of your sub before deleting Version 1. Once Version 2 is installed, the user notices that two versions are installed and then deletes Version 1.
-
The user runs one of the pre-Version 2 calling macros that you shared or the user created. The calling macro fails. Upon investigation, the user notices that the Execute a Macro or Execute a Subroutine does not specify a submacro or subroutine, respectively. Upon further investigation, the user notices that all calling macros have been disassociated.
What Causes the Calling Macros to Become Disassociated?
The Execute a Macro or Execute a Subroutine actions in calling macros appear to refer to submacros or subroutines by name, but actually these actions internally track a unique identifier called a UUID (e.g., 3DD41F1A-6C67-48F3-ACC7-68D930076DB1).
You can find the UUID for any macro by right-clicking, then selecting Copy as > Copy as UUID
When the user installed Version 2 of your sub, Keyboard Maestro checked if the UUID was already in use (by another macro), and since it was, assigned a new UUID to Version 2.
Thus since the calling macros were referring to the original UUID, not the newly assigned one, the calling macros fail.
This problem could have been avoided if the user had deleted Version 1 before installing Version 2. That sounds simple, but it is easy to overlook even if a forum poster includes upgrade instructions.
Including Caller(s) Protection in a Sub
Okay, before continuing, get a second cup of coffee.
As I was recently developing a submacro named sm.𝗽𝗮𝗹𝗲𝘁𝘁𝗲⇾MoveMouseToPalette, I was thinking about this issue. Soon after releasing the original version I wanted to share an update. In the post, I included the delete-before-upgrade warning, but I wanted to include some additional protection. After some head-scratching, here's what I created and added to the top of the submacro:
Download: Group.kmactions (3.4 KB)
The above group, in turn, calls this subroutine (which can be called from any sub that includes the above protection group):
Download: s.𝗸𝗺⇾CheckSubUUID.kmmacros (12 KB)
Macro-Notes
- Macros are always disabled when imported into the Keyboard Maestro Editor.
- The user must ensure the macro is enabled.
- The user must also ensure the macro's parent macro-group is enabled.
System Information
- macOS 14.2 (23C5030f) PRE-RELEASE SEED SOFTWARE
- Keyboard Maestro v11.0.1
Back to the scenario discussed above. If the user attempted to run Version 2 before deleting Version 1, the subroutine (s.𝗸𝗺⇾CheckSubUUID), called from the added group, would generate this dialog:
Whereas if the user ran this submacro after deleting Version 1, this dialog would appear:
In addition, I've included the following information in the submacro header comment.
PROTECTING CALLING MACROS
The first Group action in this macro includes a call to a subroutine (s.𝗸𝗺⇾CheckSubUUID) that will help ensure that current calling macros will work with this and future versions of this submacro.
If an upgraded version of this macro is installed before deleting the previous version (or if this submacro is duplicated), the upgraded version (or duplicate) submacro will display a warning and instructions for repair.
If the import-before-deletion (or duplication) was intended, the warning can be stopped two ways:
-
The OriginalUUID within the first group action can be modified to match the UUID of the newly imported (or duplicated) submacro.
-
The first group action can be deleted. If this is done, however, new calling macros will not be protected.
WARNING: If either of these changes is made, old calling macros will no longer refer to this submacro.
For more information (including a download link for s.𝗸𝗺⇾CheckSubUUID), refer to this Keyboard Maestro Forum Tutorial: Avoiding Upgrade Issues with Submacros and Subroutines
UPGRADING THIS MACRO
If upgrading from an earlier version of this submacro, it is imperative to first delete the older version prior to importing this version into Keyboard Maestro. Note that calling macros do not need to be deleted.
ACKNOWLEDGEMENTS
Thanks to @noisneil, @tiffle, and @troy for reviewing this information before I shared it here. As tedious as it reads now, it was much worse before their input.