Applescript Frustration

Okay I’m seriously frustrated. I’ve been trying to deal with icons for a while now. I have a pretty good iChatStatus script that finds cover images from album folders and changes my buddy icon correctly. Now I am trying to create a script that will take a dropped folder and set it’s icon to whatever image file it contains (the album cover).

I’ve grabbed a bunch of similar scripts to get ideas and found one called Bite! v1.0 that contains this line.


set icon of folder (theFile as string) to icon of folder folderMe

When I try and adapt my script to reflect this line OR simply copy the entire line into my script, I get this error.

it seems to change the icon from a keyword (blue colored in the orginal script) to a variable (green colored in my script) and then complains about the identifier after the “of folder” part. I know Apple has been in transition for years over how to deal with Icons and nothing is ever easy but this is the supreme frustration of it working in one script but not an other. In order to provide due diligence I discovered that “working” means it loads classic. So somehow ScriptEditor is able to tell if a script was written for Classic or not?

Any help on how to set a folder icon based on a known image, would be greatly appreciated.

thanks in advance,

Greg

You have to bear in mind that AppleScript knows very little about files themselves. In most cases it relies on other applications to fill in the blanks.

In this case AppleScript knows nothing about an ‘icon’ property of a file. To get that you need to target a program that understands about file icons, with the Finder being the most obvious example.

Make sure this command is in a ‘tell application “Finder”’ block and you should have more luck (although I still question the ‘… folder (theFile as string)…’ - is it a file or a folder you’re dealing with?

It means nothing of the sort.
While it’s possible that a ‘working’ script runs in Classic and does not run in OS X, it’s also entirely possible that a script that ‘works’ in OS X doesn’t work in Classic. I have many scripts that don’t work in Classic and by your definition they are not ‘working scripts’.
As applications (and OS versions) develop their dictionaries evolve and it’s entirely possible for a script that ‘works’ with AnyApp 1.0 doesn’t work with the latest AnyApp 9.1 and vice versa.

Something like:

tell application "Finder"
   set icon of folder "path:to:your:folder" to myImage
end tell

provided that myImage is a compatible image reference.

Camelot, thanks your right I did attempt that out of the scope of my tell finder block.

Yet I am still not able to set a folder icon. Here is my relevant code incorporating your suggestion. Where this_item is a image file and folderName is an alias to the Album folder.


tell application "Finder"
  --set newIcon to icon of file this_item
  set icon of folder folderName to this_item
end tell

upon dragging the folder to the application, gives me this error. (of which the error dialog box isn’t copiable!?)

I even replaced folderName with the actual path “MemoryCore:totally:Music:Solcircle:Solcircle:” with same effect.

as the commented out section shows I’ve also tried setting newIcon to the icon of this_item and then

set icon of folder folderName to newIcon

this ends up with a similar error

This code is being executed right after the process_item(this_item) function that happens to [open and save with icon] the cover image in question. So I know an icon exists on this_item.

obviously newIcon isn’t getting set as expected, and trying to set the icon from the image file itself doesn’t work either.

So any more thoughts of how to programmatically set my Album Folder(s) icon to the Image file they contain, would be greatly appreciated.

Thanks again,

Greg

Hi,

I don’t know if they fixed it in Panther, but icon family isn’t implemented yet. That’s why you’re getting missing value when getting the ‘icon’.

I have a workaround to this puzzle. The only thing I don’t like about it is that you need to begin with a template folder with its ‘uses custom icon’ flag set. Also, getting the custom icon of the picture may take a while.

gl,

Hi,

Here’s the theory and simple raw script. It uses Satimage.osax:

http://www.satimage.fr/software/en/

When you give a custom icon to a folder, an ivisible file named “Icon” in that folder. The name “Icon” ends with a return and I didn’t place the carriage return here in this post. Anyway, the “Icon” file contains an icns resource in its resource fork with index -16455. So you can replace this custom icon or modify its icns resource at the index. You then need to update the Finder’s view of the folder. You can get the icns data from a picture file if it has a custom icon. I’m still thinking about how to make the icns data from the picture if it doesn’t have a custom icon. Here’s the simple raw script:

– first make a folder named “Folder Template” and give it a custom icon
– you can give it custom icon by get info, click on icon in upper left corner of info window
– copy and paste, the folder now has custom icon
set the_pic to (choose file with prompt “Choose a picture:”)
try
set icns_data to (load resource -16455 type “icns” from the_pic) – uses satimage.osax
on error – file has no custom icon
beep 2
return
end try
tell application “Finder”
set custom_folder to (duplicate folder “Folder Template” of desktop) as alias
set name of custom_folder to “Target Folder”
end tell
set icon_ref to ((custom_folder as string) & “Icon” & return) as alias
put resource icns_data to icon_ref type “icns” index -16455 – might need to clear it first
tell application “Finder” to update custom_folder

Remember to first create a new folder named “Folder Template” on the desktop with custom icon. The script will beep twice if the user selects a file without custom icon

You can modify the idea from there.

If your ‘icon’ property of the Finder works, then disregard this. I’m running os10.2.8 and just updated everything in the system.

gl,

I’m running 10.3.8 and icons are not yet implemented in finder’s scriptability. Below is a gui scripting method I found to work, which automates the copy/paste of one icon from a file to the icon of a folder. Can’t attest to how reliable it is, but it seemed to be pretty stable for me. I didn’t mess with cleaning it up so it’s easy to break down. If anything, it may need some delays put in to slow it down just a bit.

I’m a bit worried about the “keystroke tab” part, only because I’m skeptical that the info window actually opens every time with nothing selected… allowing the tab to focus the ‘image’ button consistently and ready it for copy/paste. It seems that making sure to close the copy window before opening the paste window ensures that the tabbing works correctly.

set targetFolder to alias "Macintosh HD:Users:jed:Desktop:TargetFolder:"
set tmpIcon to alias "Macintosh HD:Users:jed:Desktop:75.jpg"

tell application "Finder"
	activate
	set tmpIconWindow to name of (open information window of tmpIcon)
end tell

tell application "System Events"
	tell application process "Finder"
		tell window tmpIconWindow
			keystroke tab
			keystroke "c" using command down
		end tell
	end tell
end tell

tell application "Finder"
	close window tmpIconWindow
	set targetWindow to name of (open information window of targetFolder)
end tell

tell application "System Events"
	tell application process "Finder"
		tell window targetWindow
			keystroke tab
			keystroke "v" using command down
		end tell
	end tell
end tell

tell application "Finder" to close window targetWindow

Note, that using this method you could realistically cut and paste any image into the icon field. To insert an image without copying it from another info window, you’d need to find a method of acquiring an image representation of the icon bitmap. I opened photoshop and copied a gif, and then used only the paste part of the code above, which successfully set the icon of the file to the gif.

Cheers…
j

Hi,

I found that app “Image Capture Scripting” here in Jaguar creates a custom icon. Not sure if they renamed it to “Image Events” in Panther or it’s a completely new app and they got rid of “Image Capture Scripting”. Anyway, this works in Jaguar:

– first make a folder named “Folder Template” and give it a custom icon
– you can give it custom icon by get info, click on icon in upper left corner of info window
– copy and paste, the folder now has custom icon
set the_pic to (choose file with prompt “Choose a picture:”)
set dp to (path to desktop) as string
try
set icns_data to (load resource -16455 type “icns” from the_pic) – uses satimage.osax
on error – file has no custom icon
– make temporary file with custom icon
set temp_file to (dp & “MyTempPic”) as file specification
tell application “Image Capture Scripting”
set the_image to (open the_pic)
scale the_image to size 128
save the_image in temp_file
end tell
set icns_data to (load resource -16455 type “icns” from temp_file)
–tell application “Finder” to delete temp_file
end try
tell application “Finder”
set custom_folder to (duplicate folder “Folder Template” of desktop) as alias
set name of custom_folder to “Target Folder”
end tell
set icon_ref to ((custom_folder as string) & “Icon” & return) as alias
put resource icns_data to icon_ref type “icns” index -16455 – might need to clear it first
tell application “Finder”
update custom_folder
delete temp_file
end tell

It still needs the “Folder Template” folder on the desktop. If the user selects a picture file without custom icon then one is created.

gl,

Hi, Kel. That’s great. :slight_smile:

I couldn’t get it to work on my (Jaguar) system at first. I’m not sure why. After some experimenting, I found that renaming the new folder is what activates the new icon (!?), so what works for me is to change the icon first:

-- As Kel original down to end of 'try' block, then:

tell application "Finder" to set custom_folder to (duplicate folder "Folder Template" of desktop) as alias

set icon_ref to ((custom_folder as string) & "Icon" & return) as alias
put resource icns_data to icon_ref type "icns" index -16455

tell application "Finder"
  set name of custom_folder to "Target Folder"
  update custom_folder
  delete temp_file
end tell

Hi Nigel,

Yeah, I think that works better. Maybe moving the Finder ‘duplicate’ up looks better.

– first make a folder named “Folder Template” and give it a custom icon
– you can give it custom icon by get info, click on icon in upper left corner of info window
– copy and paste, the folder now has custom icon
set the_pic to (choose file with prompt “Choose a picture:”)
tell application “Finder”
set custom_folder to (duplicate folder “Folder Template” of desktop) as alias
end tell
set dp to (path to desktop) as string
try
set icns_data to (load resource -16455 type “icns” from the_pic) – uses satimage.osax
on error – file has no custom icon
– make temporary file with custom icon
set temp_file to (dp & “MyTempPic”) as file specification
tell application “Image Capture Scripting”
set the_image to (open the_pic)
scale the_image to size 128
save the_image in temp_file
end tell
set icns_data to (load resource -16455 type “icns” from temp_file)
end try
set icon_ref to ((custom_folder as string) & “Icon” & return) as alias
put resource icns_data to icon_ref type “icns” index -16455 – might need to clear it first
tell application “Finder”
set name of custom_folder to “Target Folder”
update custom_folder
delete temp_file
end tell

Thanks for the feedback. I was wondering how it was working elsewhere. I seems like the Finder is a bit slow in duplicating.

gl,

Jobu’s code still works in 10.6.4, without modification.
Machines have gotten very much faster, though, so I had to add delays before and after the ‘paste’ code:

tell application "Finder"
		close window tmpIconWindow
		set targetWindow to name of (open information window of targetFolder)
		delay 1 -- cool off - TAAZ
	end tell
	
	tell application "System Events"
		tell application process "Finder"
			tell window targetWindow
				keystroke tab
				keystroke "v" using command down
			end tell
		end tell
	end tell
	
	tell application "Finder"
		delay 1 -- or paste will come too late - TAAZ
		close window targetWindow
	end tell