Volume Mount Trigger for Shortcuts
One of the most useful features of Shortcuts is its ability to respond to specific events or “triggers” that occur: such as achieving a time of day, or reaching a location. The following trigger example enables the execution of a chosen shortcut when a volume or disk image, is mounted on your computer.
On macOS, a volume mount trigger can be provided by a “stay-open” AppleScript applet that “watches” your system and runs a pre-chosen shortcut when a volume is mounted, passing the path to mounted volume to the shortcut when it is executed..
Trigger • Volume Mount Trigger for Shortcuts
Here is an example workflow that uses the “Run AppleScript” action to set the display of the contents of the mounted volume in its corresponding Finder window. (DOWNLOAD SHORTCUT)
NOTE: Install the shortcut and then choose it from the list of shortcuts displayed when the AppleScript applet is launched the first time.
The “Volume Watcher” Applet
The following is the AppleScript code of the “stay-open” applet that registers itself with macOS to receive a notification when a volume is mounted on the desktop.
This applet is written in AppleScriptObj-C which provides access the macOS frameworks through a “Cocoa Bridge” that exposes most of the functionality of the operating system to scripts.
Many thanks to the Script Debugger application for providing the tools for designing, editing, and notarizing AppleScript applications.
NOTE: Should you choose to edit or alter this script yourself, be sure to save it as a “Stay Open” applet that remains active until it is told to quit.
AppleScript Applet
use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use framework "AppKit"
use scripting additions
-- classes, constants, and enums used
property NSCharacterSet : a reference to current application's NSCharacterSet
property NSString : a reference to current application's NSString
property NSWorkspace : a reference to current application's NSWorkspace
property NSUserDefaults : a reference to current application's NSUserDefaults
property NSArray : a reference to current application's NSArray
property ignoredVolumes : {"home", "net", "Recovery HD"}
global workflowName
on run
-- SET VALUE OF PROPERTY TO STORED WORKFLOW PATH
my initializeDefaults()
-- CHECK STATUS OF STORED WORKFLOW PATH
if (workflowName as text) is "" then
my promptForWorkflow()
else
-- DISPLAY OPENING DIALOG
tell me to activate
display dialog "Shortcut: " & return & return & (workflowName as text) buttons {"Quit", "Change", "Start"} default button 3 with title (name of me)
set buttonPressed to the button returned of the result
if the buttonPressed is "Change" then
-- prompt for a new workflow
my promptForWorkflow()
else if buttonPressed is "Quit" then
tell me to quit
else -- check to see if workflow file exists
if my workflowCheck() is false then
tell me to activate
display alert "MISSING RESOURCE" message "There is no shortcut with the indicated name:" & ¬
return & return & workflowName buttons {"Select", "Quit"} default button 2
if button returned of the result is "Quit" then
tell me to quit
end if
-- prompt for a new workflow
my promptForWorkflow()
end if
end if
end if
-- REGISTER FOR NOTIFICATION
my registerToReceiveNotification()
end run
on initializeDefaults()
-- Initialize default if needed, retrieve current value
tell NSUserDefaults to set defaults to standardUserDefaults()
tell defaults to registerDefaults:{workflowName:""}
-- set the value of the applet property to the stored value
tell defaults to set workflowName to (objectForKey_("workflowName")) as text
end initializeDefaults
on workflowCheck()
set workflowTitles to (do shell script "shortcuts list|sort")
set AppleScript's text item delimiters to return
set workflowTitles to every text item of workflowTitles
set AppleScript's text item delimiters to ""
if workflowTitles contains workflowName then
return true
else
return false
end if
end workflowCheck
on promptForWorkflow()
-- prompt user to choose a workflow
try
set workflowTitles to (do shell script "shortcuts list|sort")
set AppleScript's text item delimiters to return
set workflowTitles to every text item of workflowTitles
set AppleScript's text item delimiters to ""
if workflowTitles is {} then
beep
display alert "Missing Resources" message "There are no saved shortcuts."
error number -128
end if
set the dialogResult to (choose from list workflowTitles with prompt "Choose shortcut to run when volume is mounted:")
if dialogResult is false then error number -128
set workflowName to dialogResult as string
tell NSUserDefaults to set defaults to standardUserDefaults()
tell defaults to setObject:workflowName forKey:"workflowName"
on error
tell me to quit
end try
end promptForWorkflow
on registerToReceiveNotification()
-- create an instance of the Shared Workspace
set workspace to NSWorkspace's sharedWorkspace()
-- identify the Shared Workspace's notification center
set noteCenter to workspace's notificationCenter()
-- register notification handlers for dealing with volume mounting
noteCenter's addObserver:me selector:"volumeWasMounted:" |name|:"NSWorkspaceDidMountNotification" object:(missing value)
end registerToReceiveNotification
on volumeWasMounted:notif
-- CHECK FOR WORKFLOW FILE
if my workflowCheck() is false then
my promptForWorkflow()
end if
-- get the path to the mounted volume
set mountedVolumePath to (notif's userInfo()'s NSWorkspaceVolumeURLKey's |path|())
-- get last path item
set thisVolumeName to (mountedVolumePath's lastPathComponent()) as text
if thisVolumeName is not in ignoredVolumes then
-- display alert
set currentApp to application (POSIX path of (path to frontmost application))
tell me to activate
delay 1
tell me to activate
display dialog "The volume “" & thisVolumeName & "” has been mounted on this system." & ¬
return & return & "Do you want to run the associated shortcut?" buttons {"No", "Yes"} default button 2
if the button returned of the result is "No" then error number -128
-- RUN WORKFLOW
try
set encodedWorkflowTitle to my encodeUsingPercentEncoding(workflowName)
set encodedVolumePath to my encodeUsingPercentEncoding(mountedVolumePath as string)
open location "shortcuts://run-shortcut?name=" & encodedWorkflowTitle & "&input=text&text=" & encodedVolumePath
tell currentApp to activate
on error errorMessage
activate
display alert "WORKFLOW EXECUTION ERROR" message errorMessage
tell me to quit
end try
end if
end volumeWasMounted:
on encodeUsingPercentEncoding(sourceText)
-- create a Cocoa string from the passed AppleScript string
set the sourceString to NSString's stringWithString:sourceText
-- indicate the allowed characters that do not get encoded
set allowedCharacterSet to NSCharacterSet's alphanumericCharacterSet
-- apply the indicated transformation to the Cooca string
set the adjustedString to sourceString's stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacterSet
-- convert from Cocoa string to AppleScript string
return (adjustedString as string)
end encodeUsingPercentEncoding