My goal is to launch a Mac Shortcut (Shortcuts App) from Xojo knowing the name of of the Shortcut.
When I was practicing, trying to understand the topic, I learned how to successfully launch a Shortcut from the Terminal with a command. I have read about but not really understood URL Schemes. I am willing to do more reading here if URL schemes are somehow the way to go. Apparently you can launch a Shortcut with a URL Scheme.
What I am looking for is the simplest, most straightforward way to launch a Shortcut from within Xojo. Any help appreciated.
I do not know if the below is the best way of accomplishing the task but it works.
Say Hi is the name of the Shortcut that is being fired off.
Var DQ As String = Encodings.UTF8.Chr(34)
Var theCommand As String
theCommand ="shortcuts run "+DQ+"Say Hi"+DQ
Var mShell As Shell
mShell = New Shell
mShell.ExecuteMode=Shell.ExecuteModes.Synchronous
mShell.Execute(theCommand)
As has been established, in this context we are talking about Mac Shortcuts which is an application provided by Apple in recent OS’s that allows the user to combine multiple steps from various apps to accomplish a task. Users can create a library of pre-built Shortcuts.
I have an application that itself wishes to call individual Shortcuts. It is possible to use the Shell.Execute command to fire off a Shortcut. I have the following code in a Xojo application to launch a Shortcut. You need the name of the shortcut. A Shell executes the Shortcut of the name that is passed.
Shell.Execute(“shortcuts run “+”“nameOfShortcut””) \ the basic form of the command
I am using the code below which allows me to pass any Shortcut that I have in my library by its name (whichShortcut)
Var nameQuote As String
nameQuote = UTF8.DQ + whichShortcut + UTF8.DQ
Var theCommand As String
theCommand = "shortcuts run " + nameQuote
Var theShell As Shell
theShell = New Shell
theShell.ExecuteMode = Shell.ExecuteModes.Synchronous
theShell.Execute(theCommand)
This works fine if I pass a simple Shortcut. Now a Shortcut can complete its task without any input from the user. I consider these “simple”.
But there are also Shortcuts that ask the user for additional information. One of my test Shortcuts is designed to email a recently taken photograph to a recipient. It prepares an email with a chosen photograph as an attachment and this pending email is presented to the user. At this point the user can for example add some verbiage to the email and then click on the send button. It would be possible for the Shortcut to then continue on doing various tasks. But the essential fact is that the Shortcut has “paused” and is waiting for the user to do something.
However, I (Xojo) get an error message which I believe is related to the fact that the Shortcut is complicated enough to ask for additional user input. The Error code is — Error 134. I check for this error after the Shell.Execute command.
If theShell.ExitCode = 0 Then
// all is well
Else
MessageBox("Error Code: " + theShell.ExitCode.ToString)
End If
With my limited testing, it seems to me that these Shortcuts that “pause” at some point to get more information are the Shortcuts that create this error. In some cases, the Shortcut actually does its task successfully despite my code getting sent an error message but that is often not the case and the situation is not satisfactory.
Has anyone successfully employed Shell commands to launch a Shortcut? Are there any suggestions of how to avoid this error? Or what causes it?
The Error Code is 134. I do not know exactly what the error is.
It is finding the Shortcut just fine. The Shortcut will actually run. In my experience, if there are no user interactions, it will be fine. If there is just one interaction with my small sample they might work although I get an error message. When I have expanded the shortcut to require two interactions with the user, it will not work at all.
The command that you are using in Xojo is not the name of a file. Individual Shortcuts are accessed through the Shortcuts app. They are not individual files.
This is the command:
theShell.Execute(“shortcuts run ““nameOfIndividualShortcut”””)
If theShell.ExitCode = 0 Then
// all is well
Else
MessageBox("Error Code: " + theShell.ExitCode.ToString)
End If
Maybe the code above is the issue. Perhaps I am asking for trouble. Things do better if I avoid looking for the error. I just skip the code that produces the message things seem to go smoothly with my limited testing. It does make me feel uncomfortable that an error is being created even if I do not see it.
To me, this sounds like the shell is waiting for more input, as if your parameter was “truncated”. Are you surrounding “nameQuote” with appropriate quotes?
If you’re doing this in a desktop app you can use
showurl("shortcuts://run-shortcut?name=OpenXojo")
Fastest way I found via terminal/console app is to use
dim s as new shell
s.Execute("open shortcuts://run-shortcut?name=OpenXojo")
You can replace any spaces between words with %20 as it follows typical URL rules too.
dim mystring as string = "Open Xojo"
mystring = mystring.replaceall(" ","%20")
showurl("shortcuts://run-shortcut?name=" + mystring)
// which would convert the URL to "shortcuts://run-shortcut?name=Open%20Xojo"
You can use callbacks to somewhat customise what happens depending on if the shortcut succeeds or fails.
Hope it helps
Edit:
If you go the route of using “shortcuts run” you can type “man shortcuts” into the terminal to get a little help file that tells you a little more of how to handle input and output.
Edit 92:
If you don’t want the shortcut app to open when you use URLs add &silent=true to the end of your url.
This is a Desktop app.
Quite interesting. Do you have an opinion as to which approach Is best?
Create new Shell & Execute
OR
Using URL schemes
Both seemed to work when I tried them. And I did not get an error message using the Shell/Execute approach. So it seems superior to my original approach. My own inclination is to use #1.
If you don’t want the shortcut app to open when you use URLs add &silent=true to the end of your url.
I am not sure how that would apply. It seems in my use case Shortcuts has to open.
man signal in the terminal can tell you more about these
I believe it’s possible to catch these and change what they do when the shell receives this request with trap Bash trap command
man trap
Or maybe the shell is just timing out? The following code will set your timeout to infinity.
Var s As New Shell
s.ExecuteMode = Shell.ExecuteModes.Synchronous
s.TimeOut = -1
The &silent=true won’t always have a use case, its more for those shortcuts where you want to say hit a button to have your brightness change but don’t want the Shortcut App to bounce/activate into your dock bar getting in the way of what you’re working. More of a User Experience thing than a functionality thing.
I tried this but I was not absolutely sure whereto put &silent=true. I tried both of the below. (note to reader — System.GotoURL and showurl have identical functionality. The latter has just been deprecated. In my code, noSpaces is just the name of the shortcut with spaces replaced by %20)
The first did not suppress the appearance of the Shortcuts app. It did nothing as far as I could tell. The second resulted in the Shortcuts app appearing but the nothing happening.
thing, But this is/was so far out of my wheelhouse that I could not make much of this.
I hear about using URL schemes on various podcast that I follow but I had concluded in my mind that it was some kind of brilliant hack that I was not destined to understand. So my personal preference, based on uninformed intuition, is to use the non-URL technique that Jefferies suggested. In my limited testing both worked just fine.