MacOS – Set Services keyboard shortcut via script OSX

applescriptautomatorcommand linekeyboardmacos

I need a way to set the following programmatically:

keyboard shortcut

Specifically for shortcuts under Services, if that makes a difference. I'm wondering if this is possible via shell or AppleScript?

EDIT:

I've seen https://stackoverflow.com/questions/7219134/programmatically-add-keyboard-shortcut-to-mac-system-preferences but I'm still not clear on how to set a shortcut for an existing service.

Best Answer

@chrisKnadler made a good point of using Applescript to do this.

I have used this before in the past but discounted it because of the new problem in Mavericks of preference being cached system wide.

Meaning you could only use the unix command

defaults write...

to get the results to actually change instead of manually changing them or using Applescript plist item commands.

But just now having a look around found a suggestion that you can simply flush the cache and initiate a the system to read the preference again by just calling a

defaults read ...

on the plist file you have change. This does indeed seem to work.

  set theServiceName to "(null) - Print to PDF - runWorkflowAsService"
set libPrefPath to POSIX path of (path to preferences folder from user domain as text)
set PlistFile to "pbs.plist"
set PlistPath to libPrefPath & PlistFile as text
set mainPropertyItem to "NSServicesStatus"
set theKey to "key_equivalent"

tell application "System Events"

    set gp to (get property list item theServiceName of property list item mainPropertyItem of property list file PlistPath)

    tell gp
        --set value of property list item "enabled_services_menu" to true
        --set value of property list item "enabled_context_menu" to true
        set value of property list item theKey to "@^h"

    end tell

end tell

do shell script " defaults read " & quoted form of PlistPath & > /dev/null

You may still need to quite individual apps for them to show the change ( as is normal)


UPDATE: Small change.

Added > /dev/null to the end of the defaults command so only errors are returned.