Display system icons of certain file types with «display dialog»

After reading Cocoa Programming for Mac OS X by Aaron Hillegass I discovered that I can easily enhance the functionality of my AppleScripts with foundation tools.

Foundation tools are scripts written in Obj-C who can make use of the Cocoa frameworks, which provide complete access to the full power of the operating system of our choice.

For example, a foundation tool can enable you to query the content of the Dictionary application, to directly create PDF files with Quartz 2D or to manipulate movies with the QTKit.

Now, something I always wanted to do was to dynamically display system icons for certain file types with the «display dialog» command, but without having to put all the different icons into the script bundle. I mean, all the icons are already available on every Mac OS X installation, so why blow the script’s size? Plus, some users may use different icons than the standard icons provided by the system:

So finally I wrote myself a tiny foundation tool to incorporate this functionality into my AppleScript projects. It’s just so much nicer to have the proper icon in an error or informational message:

And here is how it works:

Starting with Mac OS X 10.3 Apple introduced Uniform Type Identifiers (UTI) to identify a particular file type. For example, the UTI «public.html» identifies HTML files, the UTI «com.microsoft.word.doc» identifies a Microsoft Word document. If you want to get an overview of available UTIs, then please point your browser to this URL.

The UTIs can also be used to obtain the icon currently used for a certain file type. For this, you need to use the NSWorkspace class that features an iconForFileType method, which returns an image containing the icon for files of the specified type.

Once you have the image data for the icon, you can convert it to the TIFF format and finally create an ICNS icon file using tiff2icns on the command line. And that’s all the small foundation tool is doing: Get the image data for a certain Uinform Type Identifier, convert it to a TIFF file and finally create an ICNS icon file from the TIFF data.

If you want to try it on your own Mac, then I invite you to download the sample project right here:

UTIcon - Display icons for certain file types with the «display dialog» command (ca. 42 KB)

Please note that the script requires at least Mac OS X 10.4. It was successfully tested on Intel & PowerPC based Macs.

The source code of the (most simple) foundation tool can be studied here. A compiled version of the utility can be found in the sample project.

Merry Christmas!

Important: Opening and saving the below script code in Script Editor won’t result in a usable AppleScript! That is because the AppleScript internally relies on a foundation tool, which is located inside its Script bundle. Therefor please download the complete script here.

-- author: Martin Michel
-- created: 23.12.2008
-- version: 1.0
-- requires:
-- ¢ Mac OS X 10.4 or later
-- tested on:
-- ¢ Mac OS X 10.5.5
-- ¢ Intel & PowerPC based Macs

-- For a list of Uniform Type Identifiers please visit:
-- http://developer.apple.com/documentation/Carbon/Conceptual/understanding_utis/utilist/chapter_4_section_1.html#//apple_ref/doc/uid/TP40001319-CH205-CHDIJFGJ

property mytitle : "UTIcon"

-- main handler called when the script is opened with a double-click
on run
		set UTI to my askforUTI()
		-- user canceled...
		if UTI is missing value then
		end if
		set icnsfilepath to UTIcon's geticnsfilepath(UTI)
		if icnsfilepath is not missing value then
			tell me
				display dialog "On the left you can see the icon returned for the «" & UTI & "» UTI." buttons {"OK"} default button 1 with icon (POSIX file icnsfilepath) with title mytitle
			end tell
			-- calling the flush() handler removes all temporary ICNS icon files created
			UTIcon's flush()
		end if
	on error errmsg number errnum
		tell me
			display dialog "Sorry, an error occurred:" & return & return & errmsg & return & "(" & errnum & ")" buttons {"OK"} default button 1 with icon stop with title mytitle giving up after 30
		end tell
	end try
end run

-- I am asking the user to choose a Uniform Type Identifier (UTI)
-- If the user cancels, I return «missing value»
on askforUTI()
	set UTIs to {"com.microsoft.word.doc", "public.php-script", "public.png", "com.apple.applescript.script", "com.apple.colorsync-profile", "com.adobe.pdf"}
	choose from list UTIs with prompt "Please choose an UTI:" OK button name "Select" cancel button name "Cancel" with title mytitle without multiple selections allowed and empty selection allowed
	set usrchoice to result
	if result is not false then
		set UTI to item 1 of (usrchoice as list)
		return UTI
		return missing value
	end if
end askforUTI

script UTIcon
	-- list to save the paths of the created ICNS files,
	-- so that we can remove them later on
	property tempfilepaths : {}
	-- I return the file path of the icon for the given UTI
	on geticnsfilepath(UTI)
		set foundtoolpath to ((path to desktop as Unicode text) & "uticon")
		-- set foundtoolpath to ((path to me as Unicode text) & "Contents:Resources:uticon")
		if not _itempathexists(foundtoolpath) then
			error ("Could not locate the uticon foundation tool supposed to be at:" & return & return & "«" & foundtoolpath & "»")
			set foundtoolpath to quoted form of POSIX path of foundtoolpath
		end if
		set command to foundtoolpath & " " & UTI
			set icnsfilepath to (do shell script command)
			set end of tempfilepaths to icnsfilepath
			return icnsfilepath
		on error
			return missing value
		end try
	end geticnsfilepath
	-- I remove all temporary ICNS files created
	on flush()
		repeat with tempfilepath in tempfilepaths
			set command to "rm " & quoted form of tempfilepath
				do shell script command
			end try
		end repeat
	end flush
	-- Iindicate if an item exists at the given path
	on _itempathexists(itempath)
			set itemalias to itempath as alias
			return true
		on error
			return false
		end try
	end _itempathexists
end script