make a Sierra USB bootable installer

Screen Shot 2016-08-21 at 13.06.29
For those participating in Apple’s public beta program or developer program, here’s a script that will make a bootable flash drive installer of Sierra for you. Of course, you’ll need to have downloaded and saved the original installer before running it on your mac for this to work.

When an installer is made available to you from Apple, the first thing to do after downloading it is to quit the installer if it auto runs. Insert your blank USB thumb drive, and make sure it’s at least 8GB (16GB recommended).

Screen Shot 2016-08-21 at 13.36.22

You can either run the script immediately with the installer app still in your /Applications or /Downloads folder, or you can move the installer first to your preferred location. It doesn’t make any difference to the script since it’ll ask you for the location of both the Installer and the USB drive before doing its thing. It’ll also give you an option to cancel out if you made any mistake in specifying the location or you just change your mind. The script will ask you for an administrator password as it needs elevated privileges to run the createInstallMedia routine.

Note the script continues to run in the background until the installer has been created. It sleeps for an interval of 10 secs between checking the job status. Since it takes around ten minutes for the createInstallMedia routine to finish its work, you could comfortably increase that sleep time 30 secs or more if you desire. The script will present you a dialog when it detects all is done:

Screen Shot 2016-08-21 at 13.37.32



To use the bootable installer, just pop it into a mac, reboot holding down the ‘option’ key and choose the USB drive to kick off the installation process on a partition of your choice.

The full script is available here.

Enjoy!

how to fix a ‘file in use’ problem

script


Sometimes when you try to eject a disk, unmount a volume or empty the Trash, you get caught out by some app or process that’s using the file and won’t release it. This is usually signalled by a warning dialog telling you the said file is “in use” or is “locked”.

Part of the difficulty of dealing with this problem is that the warning message may not actually tell you which process is hanging on to the file or give you any options on what to do next to solve the problem.

Sounds like a job for a quick bit of bash scripting then!

We’ll write a one-stop script that leverages a few different command line utilities to help us out here. First, our script will call fuser to report the processes using the file. Then it’ll use ps to get those processes’ ID numbers and, after asking us to confirm what we want to do, it’ll feed those to the kill command to quit them and release the file.

The whole script is available here.

To use it, save the script as a plain text file in the root of your home folder (alternatively, save it in an /sbin folder. You can do echo $PATH on the command line to get a list of places you can save it to if you’re not sure).

Secondly, give it executable permissions with

chmod +x <script name>

When the problem strikes, jump into Terminal and type

./<script name>

Add a space, then type or drag the file from Finder onto the command line and hit ‘return’ if necessary. The script will do the rest.

In the image below, I first gave my script (named ‘releaseFile’) exec permissions. Then I called it and chose ‘a’ to quit all processes holding on to the file (in this case, only one process).



fuser



Hope that helps. 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: many buttons

Screen Shot 2016-07-21 at 18.04.41



I thought I’d share some code Shane Stanley wrote in response to a question I posed on ASUsers list a few weeks back. Both Shane and myself have modified that original answer, which wasn’t directly about how to display a dialog with more than three buttons like this.

This should work on all versions of OS X / macOS from 10.10 Yosemite onwards and produce something like the screenshot above. Obviously, you’ll want to adapt the size, message and buttons to fit your own circumstances. The parts you need to edit are near the end and begin with the commented line ‘set up the paramaters…’.

The script is helpfully peppered with notes but if you get stuck, just drop a question in the Comments below.


START
use AppleScript version "2.4" -- 10.10 or later
use framework "Foundation"
use framework "AppKit"
use framework "Carbon" -- AEInteractWithUser() is in Carbon
use scripting additions
property returnCode : missing value

on showMessage:theMessage withTitle:boldBit textFrame:textFieldSize textMaxWidth:maxWidth withButtons:buttonsList
# credit to Shane Stanley for this handler
-- make attributed string system font with monospaced digits
set fontSize to current application's NSFont's systemFontSizeForControlSize:(current application's NSRegularControlSize)
set theFont to current application's NSFont's systemFontOfSize:fontSize
set attsDict to current application's NSDictionary's dictionaryWithObject:theFont forKey:(current application's NSFontAttributeName)
set attString to current application's NSAttributedString's alloc()'s initWithString:theMessage attributes:attsDict
-- make a text field to hold the message
set theField to (current application's NSTextField's alloc()'s initWithFrame:textFieldSize)
tell theField
(its setEditable:false)
(its setBordered:false)
its setDrawsBackground:false
its (cell()'s setWraps:true)
its setPreferredMaxLayoutWidth:maxWidth
its setAttributedStringValue:attString
end tell

-- make it fit; needs to be done on the main thread
my performSelectorOnMainThread:"fitToSizeView:" withObject:theField waitUntilDone:true
-- make sure we have permission
set theError to current application's AEInteractWithUser(-1, missing value, missing value) -- -1 is kAEDefaultTimeout
if theError is not 0 then error "User interaction disallowed" number theError
-- create an alert
set theAlert to current application's NSAlert's alloc()'s init()
tell theAlert
its setMessageText:boldBit
repeat with anEntry in buttonsList
(its addButtonWithTitle:anEntry)
end repeat
its setAccessoryView:theField
end tell
-- show the alert; needs to be done on the main thread
my performSelectorOnMainThread:"showTheAlert:" withObject:theAlert waitUntilDone:true
set buttonNumber to returnCode mod 1000 + 1 -- where 1 = right-most button
set buttonName to item buttonNumber of buttonsList
return buttonName
end showMessage:withTitle:textFrame:textMaxWidth:withButtons:

on showTheAlert:theAlert
# credit to Shane Stanley for this handler
-- check we are running in foreground
if not (current application's NSThread's isMainThread()) as boolean then error "This handler must be called on the main thread." from current application
set my returnCode to theAlert's runModal()
end showTheAlert:

on fitToSizeView:aView
# credit to Shane Stanley for this handler
aView's setFrameSize:(aView's fittingSize())
end fitToSizeView:

# set up the parameters for the showMessage call:
set theMessage to "How many buttons would you like? There's no real limit except for practical and aesthetic considerations." & return & "Of course, I hope you'll never really think about using something as ugly as this!" & return & return & "Choose your heart out!"
set theTitle to "Many Buttons"

# increase or decrease the second item's numbers
# to fit larger or smaller amounts of text
# the '650' here is the text field's width
# the '80' is its height
set theTextFieldSize to {{0, 0}, {650, 80}}
set buttonsToDisplay to {"OK", "Five", "Four", "Three", "Two", "One", "Cancel"}

set theButtonReturned to its showMessage:theMessage withTitle:theTitle textFrame:theTextFieldSize textMaxWidth:(650) withButtons:buttonsToDisplay
EOF



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!🙂

Hack That Mac 2: Bash & Root

applescript: how to rant on Twitter

Screen Shot 2016-07-27 at 16.07.19
Well, hopefully you won’t…but if you wanted to post something longer than the 142 character limit without manually having to break it all up, this script will do it for you.

All you do is set the ‘tweetRant’ variable to whatever missive of massive importance you want to convey, and run the script. It’ll break your text into tweet-sized strings, add ellipses to them where appropriate and post them in 10-second intervals.

Of course, using this for spamming would likely not win you many friends…and besides, it’s not the only way to abuse Twitter’s 142 rule.:p

A more responsible use would be to adapt this script to create your own kind of Buffer service. You’d need to add scheduling via Calendar or a launch agent to do that, a subject we’ll tackle in an upcoming post.

Download the script from my pastebin…

Enjoy!🙂

Hack That Mac 1: Who’s who

revealing Dropbox’s dirty little security hack

Screen Shot 2016-07-28 at 14.54.30

If you have Dropbox installed, take a look at System Preferences > Security & Privacy > Accessibility tab (see screenshot above). Notice something? Ever wondered how it got in there? Do you think you might have put that in there yourself after Dropbox asked you for permission to control the computer?

No, I can assure you that your memory isn’t faulty. You don’t remember doing that because Dropbox never presented this dialog to you, as it should have:

AskForPermission

That’s the only officially supported way that apps are allowed to appear in that list, but Dropbox never asked you for that permission. I’ll get to why that’s important in a moment, but if you have the time, try this fascinating experiment: try and remove it.

Ok, you say, no problem. We all know how to do that – open the padlock, un-click the checkbox. Click the ‘-‘ button to remove it from the list. Simple, right? Look there it goes, no more Dropbox in the the Preferences panel, right?

Wrong…like a bad penny it’ll be back again before you know it. Either log out and log back in again or quit Dropbox and restart it. Dropbox will surreptitiously insert itself back in to that list AND the checkbox will be checked. That’s the magic of Dropbox for you. If you don’t want to try it for yourself, watch me do it:

That leaves a couple of questions. First, why does it matter, and second, is there any way to keep using Dropbox but stop it having access to control your computer?

There’s at least three reasons why it matters. It matters first and foremost because Dropbox didn’t ask for permission to take control of your computer. What does ‘take control’ mean here? It means to literally do what you can do in the desktop: click buttons, menus, launch apps, delete files… . There’s a reason why apps in that list have to ask for permission and why it takes a password and explicit user permission to get in there: it’s a security risk.

Interlude: Contrary to Dropbox’s completely spurious “explanation”/obfuscation here, Accessibility has nothing at all to do with granting permissions to files. Accessibility frameworks were first introduced in Mac OS X 10.2 and expanded in 10.3 to allow control of user interface items via System Events and the Processes suite. As anyone can readily see, what that allows is GUI control just as if the program or script was clicking buttons and menu items.

But perhaps you implicitly trust Dropbox to not do anything untoward. After all, they’re a big name company who wouldn’t want to upset their customers, right?

There’s two flaws in reasoning that way. One: the bigger the name, the less effect customer dissatisfaction has. Let’s face it. If a 1000 people read this post and stop using Dropbox because of it, it’s not going to make much difference to Dropbox. So assuming you can trust a “big name” company not to “feck you off’ because they might lose your business is not “smart computing”, even less smart if they figure that you’re a customer on a free plan anyway… :p (See this for more reasons why big companies in general don’t pay much attention to ethical values). Two, and more importantly, you already have hard proof that Dropbox can’t be trusted. It just overrode your and Apple’s security preferences without asking you, and – as you’ve seen if you tried to remove it and noticed its magic reappearance act – it disregards your choices and re-inserts itself even after you’ve explicitly removed it (we’ll sort this naughty behaviour out in a minute).

It matters for another reason, too. Let’s assume for the sake of argument that Dropbox never does any evil on your computer. It remains the fact that the Dropbox process has that ability. And that means, if Dropbox itself has a bug in it, it’s possible an attacker could take control of your computer by hijacking flaws in Dropbox’s code. Of course, that’s entirely theoretical, but all security risks are until someone exploits them. The essence of good computer security and indeed the very reason why OSX has these kinds of safeguards in place to begin with is that apps should not have permissions greater than those that they need to do their job. Moreover, Dropbox is either clearly storing your Admin password in its own caches (very bad) or giving itself complete root privileges (also very bad); otherwise, it would have to ask you for the password again after you delete it from the list of apps allowed Accessibility privileges. This strikes me as not only underhand (because there’s no indication that it’s going to assume that kind of control) but also over the top.

Which is the third reason why it matters: Dropbox doesn’t appear to need to have access to Accessibility features in order to work properly. I figured out what Dropbox was up to in October 2015. Why has it taken me this long to write about it? First, because after having reported it to Apple Product Security at that time, I wanted to see if they would force Dropbox to change this behaviour (they haven’t). Second, because the only way I could be sure that DB didn’t need to be in the list of apps with Accessibility privileges was to test it over a period of time. I use Dropbox across 3 different macs and an iPhone. I haven’t experienced any issues using it whatsoever while denying it access to Accessibility. Caveat: I haven’t tested Dropbox against all of OSX’s Accessibility features, but certainly for a ‘standard’ set up of OS X, it is not needed – and, let me repeat, even if it were needed for some particular feature to work, Dropbox should have explicitly asked for this permission, like every other app, and obeyed the user’s decision to revoke that permission when removing it from the list of allowed apps.

There really isn’t any excuse for Dropbox to ride roughshod over users’ security and preference choices. So that leaves us with just one last question: how to get Dropbox out of there? The short answer is that you first uninstall Dropbox (see my procedure here), then remove it from the Accessibility pane (see the description in paragraph 4 above or watch the video). Now you can re-install it, but you hit ‘Cancel’ when it asks you for an admin password:

Stop! Choose 'Cancel' !!!

Stop! Choose ‘Cancel’ !!!

The dialog box apparently lies (again, still trusting this big name firm?) when it says Dropbox won’t work properly and clearly deceives because this is NOT the dialog box that Dropbox should be showing you to get access into Accessibility. Indeed, even with your admin password, it still shouldn’t be able to get into Accessibility. Clearly Dropbox’s coders have been doing some OS X hacking on company time.

Now, there’s a slight catch. So long as you never give Dropbox your admin password, it won’t be able to install itself in Accessibility and you can keep on using Dropbox just as you have done before. However, it will throw up this dialog box on every restart of the machine or relaunch of Dropbox. So the catch is that you have to actually notice what’s asking you for your password and not just blindly throw your password into the box without looking. :O

But you shouldn’t be doing that anyway, of course, cos that’s not good security practice…😉 , but given that the dialog box looks just like*** an authentic password request from the OS itself, that may be a habit you have to train yourself into.

Slightly annoying, but not as annoying as having an app hack your mac (of course, if you forget, you’ll have to go uninstall Dropbox again, remove it from Accessibility, then reinstall it).

 

***But not “like” enough – note the ‘Type your password…’ sentence is both misaligned and is spaced into a separate paragraph, unlike genuine authentication requests from OS X. The phrasing of the first sentence is also very “un-OS X”.

 

applescript: file & folder handlers

Screen Shot 2016-07-26 at 17.06.40

Here’s a few of
the AppleScript handlers I use for getting contents of folders (examples 1 & 2), or for getting the text of a file (example 3).

In all three cases, you give the handler a path string in POSIX form, e.g, ~/Desktop or (for example 3), ~/Desktop/sometext.txt.

In example 1, what you get back is a list of the item names in the folder. It doesn’t include hidden or invisible files.

In example 2, what you get back is a record of all the items and their properties. This can be an immensely useful and powerful handler.

In example 3, what you get back is a text variable whose value is the complete text of the file.

Hope these come in as handy for you folks as they have for me!

Click here to get the handlers from my pastebin.

Enjoy!🙂

Note: The getFileContents() handler requires OSX 10.10 or higher.

%d bloggers like this: