Blog Archives

how to add a hotkey for the ‘About’ menu

I often need to check version numbers of apps I’m using from the ‘About’ menu. However, unlike ‘Preferences’, ‘Hide’ and ‘Quit’, the About menu doesn’t have a default hotkey.

Normally, it’s no problem to add a menu hotkey through System Preferences > Keyboard > Shortcuts, but you can’t do that for the ‘About’ menu. That’s because the Shortcuts requires an exact menu name, and the ‘About’ menu is actually postfixed with the name of each app, so there’s no way to specify the menu universally.

However, we can solve the problem with a little AppleScript, which we can then make into a Service (via Automator) or add to a script runner like FastScripts.

The script is quite simple, but does require System Events, and that means you need to make sure that System Events itself or the app that’s going to run the script has Assistive Access allowed in System Preferences’ Privacy pane.

The raw text for the script is available from my pastebin here.

Enjoy! 🙂


BBEdit: remove whitespace with one click

remove whitespace

I often need to process lists of ‘dirty text’ which can contain lots of whitespace, new lines and so on. Fortunately, BBEdit allows you to run AppleScripts directly from its Script menu, which means we can define lots of useful little text processing scripts and have them ready to hand. I’ve got several that I’ll share over the next few posts, but probably the most oft-used of them is this one for removing whitespace.

Here’s what the script looks like. You can download the source from my pastebin here.

And here’s a little giffy showing it at work:






Share and enjoy! 🙂


how to easily spoof a user’s password





Spoofing or phishing – presenting a user with fake authentication requests – is a common email tactic, but it’s not the only vector where you need to be on your guard. Every version of macOS is vulnerable to a very simple phishing attack right on your desktop that doesn’t require admin privileges to run, would not be detected by GateKeeper or XProtect, and which could easily be placed on your mac by any of the nefarious malware / adware installer scripts that come with some less reputable software downloads.

This attack isn’t new, but it’s not often talked about. The easiest way to see how it works is in this quick 4-minute demo:

As you can see, it’s easy to grab the icon of any Application and put it in the script; it doesn’t even have to be the icon of an app that’s running. The simple demo I gave above could easily launch iTunes first to increase the coherence of the attack, or it could use a completely different icon, including the icon of security programs you may have running on your mac.

How can you check?

If you were presented with a password request like this and wanted to check whether it’s legitimate or not, an easy way would be to use my free utility DetectX Swift’s Profiler. Click the Profiler function, and search for ‘osascript’ within the Running Processes section. Note how DetectX Swift shows you the text of the script being run, confirming that this dialog is up to no good:


how to script with Objective-C



Is it me, or is AppleScript experiencing something of an Indian Summer? It seems everywhere I go, people are talking more about macOS automation, AppleScript and even Apple’s curious hybrid syntax AppleScriptObjC (ASObjC).

Of course, some people have suffered miserably at the hands of AppleScript in the past, and even though the thought of scripting with access to Cocoa APIs through Objective-C is tempting, they fear the AppleScript side of it.

If that’s you, bear in mind that AppleScriptObjC isn’t really “AppleScript + Objective-C” at all. It is actually just a dialect of Objective-C that will be accepted in the (Apple)Script Editor and can be run by an instance of the AppleScript component. In plainer English, you can use Objective-C in an AppleScript without any AppleScript whatsoever!

The point of doing so would be that one could package Objective-C code in a .scpt file (or scptd bundle or AppleScript .app), and also mix whatever scripting language you prefer with calls to Cocoa’s APIs.*

The problem that using ASObjC presents anyone familiar with Objective-C is how to translate ‘pure’ Objective-C into the dialect that Script Editor (and other applescript runners like FastScripts, Keyboard Maestro, Automator, etc) can understand. If you use LateNight Software’s Script Debugger for scripting, you’ll already know that the work is done for you by the app’s built-in code completion. If you’re battling on in Apple’s default Script Editor, you’ll need to do the translation manually.

By way of example, then, here’s some original Objective-C, and below it, a translation that would work in Script Editor:

Objective C
NSString *aString = @"hello";
NSString *bString = @" world";

aString = [aString stringByAppendingString:bString];

NSUserNotification *notif = [[NSUserNotification alloc] init];
notif.informativeText = aString;
[[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:notif];


AppleScriptObjC
set aString to NSString's stringWithString:"hello"
set bString to NSString's stringWithString:" world"

set aString to aString's stringByAppendingString:bString

set notif to NSUserNotification's alloc's init
set notif's informativeText to aString
NSUserNotificationCenter's defaultUserNotificationCenter()'s deliverNotification:notif


As you can see, there’s a direct 1-to-1 correspondence, with the 6 statements in Objective-C paralleled by the 6 statements in AppleScriptObjC.

The main peculiarity is the use of possessive word forms and that variable attribution is done by using "set X to Y" rather than "X = Y". Type declaration is done via the idiom 'set <var> to <NSObject>'s <class init method>', which returns an instance of the object just as it would normally. You call instance methods by putting the instance in front of the method just as you would in regular Objective-C (e.g, see line 3 of the examples).

As you can see in the screenshot below showing Xcode and Script Editor, they work in the same way. You’ll notice in Script Editor there is a 'use' statement (equivalent to Objective-C’s ‘import’), and there’s also a whole load of property statements. These latter are peculiar to the ASObjC translation, and don’t have a counterpart in pure Objective-C. All you need to know about these is for each kind of Objective-C object you want to use (NSString, NSArray, whatever*), you’ll want a property statement for it at the beginning of the script. The statement always has the same form:

property <NSObject> : a reference to current application's < NSObject>

I think the best way to think of ASObjC was recently summed up by Sal Saghoian, when he said that ASObjC is “…the ultimate duct tape. You can do anything you want with ASObjC. You own the computer.”

Enjoy! 🙂

*not all Cocoa frameworks nor all Objective-C objects can be bridged to, but pretty much all the most useful ones are available.



Further reading:

– Applehelpwriter’s review of Script Debugger 6
how to quickly toggle Swift Compiler warnings



Picture credits: Top image adapted from MilleniumBirdge by lesogard

Navigation markers added to SD6

screen-shot-2016-09-25-at-20-53-02

The recent update to Script Debugger 6 added a subtle, but much-needed new feature.

Now, scripters can take advantage of the same kind of navigation markers familiar to users of Xcode (pragma marks) to quickly navigate to user-defined sections of the script.

Scripters can now create a marker with a double-dash and double arrow marker, followed by whatever label they choose.

-->> myMarker here!

For me, this is a great boon, and I’ve changed all the section headings in my templates to the new navigation marker syntax, meaning I can easily jump to the various sections from the Navigation bar at the top of the script.

Nice! 🙂

Further Reading:
Script Debugger 6: The Complete Review


applescript: remove characters from a string

Screen Shot 2016-08-26 at 18.01.54

One of the things I’m often finding myself doing is trying to remove characters from strings, particularly html codes and other markdown clutter. Rather than laboriously messing around with offsets and the like, we can make our lives simpler by making a quick handler that leverages Cocoa’s stringByReplacingOccurrencesOfString method.

For example, suppose you’ve got a sourceString containing something like this

Screen Shot 2016-08-26 at 18.08.57

We can strip all the tags out by calling our handler like this, once for the opening tags and again for the closing tags. Note how the variable names have changed in the second call:

Screen Shot 2016-08-26 at 18.13.06

The beauty of this is it doesn’t just remove one instance of the tag, it removes all occurrences of them, so this handler is a real life-saver when you’ve got a whole page of markdown to clean.

To achieve this you’ll need to add a couple of declarations to the top of your script, as well as the handler:

Here’s the declarations you’ll need:

use scripting additions
use framework "Foundation"
property NSString : a reference to current application's NSString

Here’s the code for the handler:

on remove:remove_string fromString:source_string
set s_String to NSString's stringWithString:source_string
set r_String to NSString's stringWithString:remove_string
return s_String's stringByReplacingOccurrencesOfString:r_String withString:""
end remove:fromString:

Enjoy! 🙂

ejecting some, all or just specified disks

Screen Shot 2016-08-03 at 13.06.32

We posted this one liner some time ago in response to the fact that you can’t actually get the Finder to eject all volumes on multiple drives at the same time.

However, I thought it’d be good to have a slightly more useful version. In this version, you can choose individual volumes or all volumes from a list. Optionally, you could also include collections.

Screen Shot 2016-08-03 at 13.36.56
Suppose for example you wanted to eject one volume from one physical drive along with one from another and two from a third? To do that, just uncomment these two lines and supply your own volume names in the collection_1 list:

--if you want to create an item that groups some volumes together uncomment the following two lines:
# set collection_1 to {"Archive 1.5TB", "BUFFALO 500GB", "This disk", "That disk", "Another disk"} -- supply as many disks names you want to group together here
# set diskList to {"All Disks", "Disk Group 1"}
Then, when you run the script, choose ‘Disk Group 1’ to eject that collection of volumes. You could of course adapt the script to include more than one collection.

You can get the full script from my pastebin here.

Enjoy! 🙂

applescript: get item number of list item

Screen Shot 2016-07-31 at 21.45.31

One of the annoying ‘missing features’ in AppleScript is the lack of any way to get the item number of an item in a list.

Fortunately, since Cocoa does of course include an ‘indexOfObject’ function, we can leverage Cocoa in our AppleScript to write a nice little handler (you could add this to my list and string handlers library I posted here or just add it directly in your own scripts).

First, make sure your script or library already has two lines like these to import the Foundation framework and declare an NSArray:

use framework "Foundation"

property NSArray : a reference to current application's NSArray

Then after that add the handler:

on getIndexOfItem:anItem inList:aList
set anArray to NSArray's arrayWithArray:aList
set ind to ((anArray's indexOfObject:anItem) as number) + 1 # see note below
if ind is greater than (count of aList) then
display dialog "Item '" & anItem & "' not found in list." buttons "OK" default button "OK" with icon 2 with title "Error"
return 0
else
return ind
end if
end getIndexOfItem:inList:

You can now call the code like this:

# example
set thisList to {"I", "see", "a", "red", "door", "and", "I", "want", "to", "paint", "it", "black"}
set aNum to its getIndexOfItem:"paint" inList:thisList
(* Result --> 10 *)
if aNum is not 0 then
-- do something
end if

# Note: Remember AppleScript lists are indexed from 1, unlike Cocoa arrays which start at index 0.

Enjoy! 🙂

Using Cocoa in AppleScript

Script Debugger 6: the complete review

SD Shot 2



It feels like cheating. When you’ve spent pretty much your entire AppleScripting life behind the wheel of Apple’s austere Script Editor application, taking Script Debugger 6 out for a 20-day spin feels like someone’s let you in on a secret you’re not supposed to know. Hurdles you’ve taught yourself to clear – through considerable effort, frustration and no small amount of bloody-minded tenacity – are removed before you get to them; obstacles you’ve habitually steered around or avoided have disappeared, and dark holes of AppleScript mystery appear, in the light shone on them by SD6, to be not the menacing entities you once feared but new friends that offer ways to do things faster and more effectively. The secret that Script Debugger seems to lay bare is that AppleScripting doesn’t have to be as painful as we’ve been conditioned to believe. And that does feel like a cheat. Read the full review…


%d bloggers like this: