Eject Hanging Disks and Disk Images

Sometimes OS X will delay ejecting Disk Images or Disk drives, so much that sometimes you can wait a long time and nothing will happen. Also, sometimes Right-clicking and ejecting or dragging the icon to the Trash does no good and this can be very annoying when you want to get your thumb drive out and go without damaging your data.

You can use Disk Utility for ejecting images that are hanging, but there's also a good AppleScript out there that can help you eject them immediately too!

(*
Eject Disks © RickoKid 2008
Version 0.1

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*)

set prefaceMessage to ""
set confirm to false

-- check if current selection in Finder contains any ejectable disks
set ejectables to my findEjectable(selection of application "Finder")
if (count of ejectables) is greater than 0 then
-- Ejectable disks are selected in Finder, add them to the eject list
set ejectList to ejectables
set prefaceMessage to "Note: Ejecting disks selected in Finder." & return & return
else
-- No ejectable disks in Finder selection; look for all ejectable disks on the system ...
try
tell application "Finder" to set allEjectables to name of every disk whose ejectable is true
on error
-- Finder throws an error (tantrum?) if it can't match the 'whose' condition, ie when there are no disks to match
display alert "No ejectable disks" message "Couldn't find any ejectable disks on your system!" as informational buttons {"OK"} giving up after 10
return "Error: No ejectable disks."
end try

-- if ejectable disks are found ...
if (count of allEjectables) is 1 then
set ejectList to allEjectables
set confirm to true
else if (count of allEjectables) is greater than 1 then
set ejectList to choose from list allEjectables with title "Eject Disk" with prompt "Choose which disk(s) to eject" OK button name "Eject" with multiple selections allowed without empty selection allowed
end if
end if

my kickoffEject(ejectList, prefaceMessage, confirm)

on open droppedDisks
set ejectables to findEjectable(droppedDisks)
my kickoffEject(ejectables, "Note: Ejecting dropped disks." & return & return, false)
end open

on findEjectable(selectedList)
set ejectables to {}
tell application "Finder"
repeat with selectedItem in selectedList
if class of selectedItem is alias then
set nameOfItem to name of selectedItem
set matchingDisks to (every disk whose name is nameOfItem and ejectable is true)
repeat with matchItem in matchingDisks
set ejectables to ejectables & {name of matchItem}
end repeat
else if class of selectedItem is disk and ejectable of selectedItem then
set ejectables to ejectables & {name of selectedItem}
end if
end repeat
end tell
return ejectables
end findEjectable

on kickoffEject(ejectList, preface, confirm)
set textDelimiters to AppleScript's text item delimiters
set AppleScript's text item delimiters to return
-- if disks are chosen (don't try if Cancel is clicked) or 1 is confirmed or disks are selected in Finder
set messages to {}
set moreInfo to {}

if (count of ejectList) is greater than 0 then
if confirm then
set ejectIt to display alert "Eject" message "Are you sure you want to eject the following disk(s)?" & return & return & (ejectList as text) as warning buttons {"Cancel", "Eject"} default button "Eject" cancel button "Cancel" giving up after 20
if button returned of ejectIt is "Cancel" then return "User cancelled."
end if

set AppleScript's text item delimiters to return & tab
repeat with ejectDisk in ejectList
try
set ejectResult to (do shell script "touch /tmp/" & ejectDisk & "-report.txt; hdiutil detach '/Volumes/" & ejectDisk & "' &> /tmp/" & ejectDisk & "-report.txt &")
repeat while ejectResult is equal to ""
delay 0.5
set ejectResult to (do shell script "cat /tmp/" & ejectDisk & "-report.txt")
end repeat
do shell script "rm /tmp/" & ejectDisk & "-report.txt"
if ejectResult contains "error" then error ejectResult
set messages to messages & {"Ejected disk \"" & ejectDisk & "\" successfully."}
set moreInfo to moreInfo & {"Success: disk \"" & ejectDisk & "\": " & return & tab & (paragraphs of ejectResult as text)}
on error errorMsg
set messages to messages & {"Error: disk \"" & ejectDisk & "\" could not be ejected."}
set moreInfo to moreInfo & {"Fail: disk \"" & ejectDisk & "\":" & return & tab & errorMsg}
end try
end repeat

set AppleScript's text item delimiters to return

if (count of messages) is not 0 then
set report to display alert "Ejection Results" message preface & (messages as text) as informational buttons {"More info ...", "Close"} default button "Close" giving up after 60
if button returned of report is "More info ..." then
set moreDetailedInfo to {}
repeat with eachMessage in moreInfo
if eachMessage contains "error" then
set diskDev to do shell script "mount | grep " & word 3 of eachMessage & " |awk '{print $1}'"
set openFiles to paragraphs of (do shell script "lsof -Fc " & diskDev & " | sed -ne '/c/ s/c//p'")
if (count of openFiles) is greater than 0 then
set AppleScript's text item delimiters to return & tab & tab
set eachMessage to eachMessage & return & tab & "Processes open on disk:" & return & tab & tab & (openFiles as text)
set AppleScript's text item delimiters to return
end if
end if
set moreDetailedInfo to moreDetailedInfo & {return & eachMessage}
end repeat
display alert "Ejection Details" message (moreDetailedInfo as text) as informational buttons {"OK"} default button "OK"
end if
end if
end if
set AppleScript's text item delimiters to textDelimiters
end kickoffEject


This is very good for isolating those hanging Disks, when you're not sure which Application or Applications are keeping the Disk from ejecting.

0 Comments:

Post a Comment