Class error only happens when run with idle handler

Edit: the error is no longer a class error, although I still want to know what was going on there. I assume the problem is the same as before, since the script still ays it can’t get a property of one of the files. The difference is that modification date has a fancy class name two, whereas “name” is just name i guess…

I’ve got a simple script as an application to check my desktop every two seconds and rename any new screenshots with a user-specified prefix and a number. The script runs fine when run without the idle handler with ASE, but I get an error, “can’t get class <> of…” when I run the script as an application with a run handler. The error has to do with a check I put in to only have screenshots renamed if they were made after the script was called, so a comparison is made between the date the script was called and the modification date of the screenshots. The class error has to do with accessing the modification date of the screenshot file.

Also, since I havn’t gotten this to work as an idle script yet, I don’t know if it works perfectly. Will the global counter variable continue to iterate with each run of the idle handler?

Thanks,

Tim

Here’s the script:

on getFiles(kind_, folder_)
	tell application "Finder"
		set files_ to every item of folder_ whose kind is kind_
	end tell
	return files_
end getFiles

global now
global prefix
global counter
set prefix to ""
set now to current date
set counter to 1

on idle
	if prefix = "" then
		try
			tell me to display dialog "Enter prefix for screen shots" default answer ""
			set prefix to text returned of result
		on error
			return 2
		end try
	end if
	
	set desktop_ to (path to desktop)
	set allPNG to my getFiles("Portable Network Graphics image", desktop_)
	set countPNG to count of allPNG
	if countPNG < 1 then
		return 2
	end if
	set usePNG to {}
	repeat with i from 1 to countPNG
		if (modification date of item i of allPNG < now) and (name of item i of my allPNG) begins with "Screen Shot" then
			set end of my usePNG to item i of my allPNG
		end if
	end repeat
	set useCount to count of usePNG
	if useCount > 0 then
		repeat with i from 1 to useCount
			set name of item i of usePNG to (prefix & " " & counter & ".png") as string
			set counter to counter + 1
		end repeat
	end if
	return 2
end idle

I don’t know if it’s your real problem but I never use kind which is localized.
I use type identifier grabbed from System Events.

Here I started using kind as you do.
I was forced to edit the checked value which is “Image PNG (Portable Network Graphics)” when the system run in French.
Execution time was awfully long so I edited it this way to use type identifier.



on getFiles(kind_, folder_)
	tell application "System Events"
		set files_ to every disk item of folder_ whose type identifier is kind_
	end tell
	return files_
end getFiles

set desktop_ to (path to desktop)
set allPNG to my getFiles("public.png", desktop_)

modification date of item 1 of allPNG
name of item 1 of allPNG

It return the results quite instantaneously.

Yvan KOENIG (VALLAURIS, France) dimanche 16 septembre 2012 09:54:08

Another thing is that ‘allPNG’ and ‘usePNG’ are local variables, so putting ‘my’ in front of them will cause errors.

You haven’t specified the application to get the modification dates and names of the files, which ideally you should. It should be the same as the one in the getFiles() handler.

And it may help to set a variable to item i of allPNG each time round the loop and use that instead of ‘item i of allPNG’ in the references for the modification dates and names.

Instead of polling the Finder and wasting resources every two seconds it might be better to use a folder action for this task.
As the desktop folder is actually not suitable the location to save the screenshots can be changed with

defaults write com.apple.screencapture location /Full/Path/To/Folder

Thanks for the responses guys. I appreciate it. I tried changing things around but it still gave errors only when run as an idle handler. I opted for initiating each rename manually through dialog boxes rather than having it keep checking.

Thanks again,

Tim

Hello

As my screenshots aren’t created on the Desktop, for years I use this folder action script to edit the names so that they fit my needs.


on adding folder items to this_folder after receiving added_items
	set destination to (path to documents folder as text) & "tempo:"
	set destination_unix to quoted form of POSIX path of destination
	tell application "System Events" to set added_items to path of every file of this_folder whose visible is true
	repeat with un_fichier in added_items
		tell application "System Events" to tell disk item un_fichier to set vieux_nom to name
		
		copy vieux_nom to nouveau_nom
		if nouveau_nom contains " Ã  " then set nouveau_nom to my remplace(nouveau_nom, " Ã  ", "T")
		# on my machine the string before the date in the screenshot name is "@ "
		if nouveau_nom starts with "© " then set nouveau_nom to text 3 thru -1 of nouveau_nom
		if nouveau_nom ends with ".JPG" then set nouveau_nom to text 1 thru -4 of nouveau_nom & "jpg"
		do shell script "mv " & quoted form of POSIX path of (un_fichier) & space & destination_unix
		tell application "System Events" to set name of disk item (destination & vieux_nom) to nouveau_nom
	end repeat
end adding folder items to

--=====
(*
replaces every occurences of d1 by d2 in the text t
*)
on remplace(t, d1, d2)
	local oTIDs, l
	set oTIDs to AppleScript's text item delimiters
	set AppleScript's text item delimiters to d1
	set l to text items of t
	set AppleScript's text item delimiters to d2
	set t to l as text
	set AppleScript's text item delimiters to oTIDs
	return t
end remplace

--=====

As far as I know, there is something odd in your idle script.

You wrote :
global counter
.
set counter to 1

My understanding is that every time you explicitely call the script (on boot for instance) the global will be reset to 1.
If you want to keep the old value, replace your two instructions by

property counter : 1

or better store the value in a file.
Here is the script which I use to achieve this goal.



--[Script Renommer ebay-X]

property zenum : 0
property pourlui : "##"
property fichier_num : "le_numéro.txt"

-- my doYourDuty({"Western 2:Tout Gerbino:pour ebay:aqsd:" as alias}, "Western 2:Tout Gerbino:pour ebay:renommer_ebay_2010.app:Contents:le_numéro.txt")

--=====

on open (added_items) (* une liste d'alias *)
	local the_script, ma_classe
	set the_script to path to me as text
	tell application "System Events" to set ma_classe to (class of disk item the_script) as text
	if ma_classe is not in {"file package", "package", "«class cpkg»"} then
		error "ATTENTION ! " & the_script & " n'est pas un paquet !" & return & ma_classe
	end if
	my doYourDuty(added_items, the_script & "Contents:")
end open

--=====

on doYourDuty(items_ajoutes, chemin_contents)
	local chemin_num, f
	set chemin_num to chemin_contents & fichier_num
	tell application "System Events"
		if not (exists disk item chemin_num) then
			make new file at end of folder chemin_contents with properties {name:fichier_num}
		end if
	end tell -- System Events
	
	try
		set zenum to (read file chemin_num) as integer
	on error
		set zenum to 0
		display dialog "Attention, la numérotation va commencer à 1"
	end try
	
	repeat with f in items_ajoutes
		tell application "System Events" to class of disk item (f as text)
		if (result as text) is in {"folder", "«class cfol»"} then my traiteUnDossier(f, chemin_num)
	end repeat
	
end doYourDuty

--=====

on traiteUnDossier(ff, chemin_du_num)
	# Here ff is an alias
	local num1, un_fichier, nom, nomExt
	tell application "System Events" to tell folder (ff as text)
		set liste_des_fichiers to every file whose visible is true
		name
		make new folder at end with properties {name:result}
	end tell -- System Events
	copy zenum to num1
	
	--ici renommer les nouveautés
	if liste_des_fichiers is not {} then
		repeat with un_fichier in liste_des_fichiers
			tell application "System Events"
				tell un_fichier
					set {nom, nomExt} to {name, name extension}
				end tell
				
				if nom does not start with pourlui then
					if nomExt > "" then set nomExt to "." & nomExt
					set zenum to zenum + 1
					(100000 + zenum) as text
					text -5 thru -1 of result
					set name of un_fichier to (pourlui & result & nomExt)
				end if -- Nom does.
			end tell -- System Events
		end repeat
		
		if zenum > num1 then
			(100000 + num1 + 1) as text
			text -5 thru -1 of result
			set nomDossier to "_X" & result & "Æ’"
			tell application "Finder"
				set w1 to make Finder window to ff
				set current view of w1 to icon view
				set arrangement of icon view options of w1 to arranged by name
				close w1
				set name of ff to nomDossier
			end tell
			write (zenum as text) to file chemin_du_num starting at 0
		end if -- zenum > num1
	else
		beep 1
		display alert "ATTENTION, il n'y a pas de fichier dans" & return & "« " & ff & " » !" giving up after 120
	end if
end traiteUnDossier
--[/Script]

At the very beginning you will see the instruction which I use to test the script.

Yvan KOENIG (VALLAURIS, France) lundi 17 septembre 2012 11:01:42

Yvan,

Thank you so much. My problem is now more than solved! :smiley:

I owe so much to the macscripting gods on this forum…

-Tim