“System Events” behaves differently inside a handler… why?

When working with “System Events” there have been several occasions (in completely unrelated scripts targetting completely unrelated objects) where two seemingly identical commands produce entirely different results. This only happens with “System Events” and I end up writing work-arounds for the problems. However, I’m getting tired of not knowing why this behavior occurs, so here I ask.

Here is a simple example, I want to delete a picture with “System Events”:

-->‡METHOD #1: works fine‡<--
	tell application "System Events" to make new file at end of (path to downloads folder) with properties {name:"Some Image.jpg"}
	set ImageFile to the result
	tell application "System Events" to delete (a reference to ImageFile)

Great! it works! but I need it do operate from a handler, where it doesn’t work: :o

-->‡METHOD #2: error -1700‡<--
	tell application "System Events" to make new file at end of (path to downloads folder) with properties {name:"Some Image.jpg"}
	set ImageFile to the result
	my DeleteHandler(ImageFile)
	on DeleteHandler(myImage)
		tell application "System Events" to delete (a reference to myImage)
	end DeleteHandler

Method #3 has the same result as method #2:

-->‡METHOD #3: error -1700‡<--
	on DoEverything()
		tell application "System Events"
			make new file at end of (path to downloads folder) with properties {name:"Some Image.jpg"}
			set myImage to the result
			tell application "System Events" to delete (a reference to myImage)
		end tell
	end DoEverything

Is ther something I’m missing here? These look identical to me. :confused:

Aesthir

Model: iMac 7,1
AppleScript: AppleScript 2.2.1
Browser: Firefox 11.0
Operating System: Mac OS X (10.7)

The fact that the last one fail is normal.

You wrote :

   set [b]ImageFile[/b] to the result
   tell application "System Events" to delete (a reference to [b]myImage[/b])

Must be :

   set [b]ImageFile[/b] to the result
   tell application "System Events" to delete (a reference to [b]imageFile[/b])

Yvan KOENIG (VALLAURIS, France) mercredi 11 avril 2012 22:09:09

Hi,

the created file object is a file reference anyway, so omit the explicit reference.
It seems that AppleScript is more tolerant in the run handler


tell application "System Events" to make new file at end of (path to downloads folder) with properties {name:"Some Image.jpg"}
set ImageFile to the result

my DeleteHandler(ImageFile)
on DeleteHandler(myImage)
	tell application "System Events" to delete myImage
end DeleteHandler


Your reference (‘a reference to’) is to the variable ImageFile or myImage, not to the image itself. The only variables to which you can make references are properties, globals, and run-handler variables. ImageFile is a run-handler variable in the first script, so the reference works there. In your DeleteHandler() handler, myImage is a parameter variable and thus a local, which is why the reference doesn’t work in the second script. As Stefan suggests, just leave out ‘a reference to’. It’s not necessary anyway.


-->‡METHOD #2: edited, behave well
tell application "System Events" to make new file at end of (path to downloads folder) with properties {name:"Some Image.jpg"}
set ImageFile to path of the result -- Edited instruction
my DeleteHandler(ImageFile)

on DeleteHandler(myImage)
	tell application "System Events"
		activate
		delete disk item (myImage) --Edited instruction
	end tell
end DeleteHandler

Yvan KOENIG (VALLAURIS, France) mercredi 11 avril 2012 22:49:12

[b]

Thx Yvan, that’s been corrected. even though it wasn’t the cause of the problem.
[b]

[b]

Stefan and Nigel, the reason I put in the “a reference to” is because I can’t get it to work without it when the variable is set to a file directly:

set ImageFile to alias "Aesthir:Users:aesthir:Downloads:Some Image.jpg" -- (A)
set ImageFile to file "Aesthir:Users:aesthir:Downloads:Some Image.jpg" -- (B)
set ImageFile to "Aesthir:Users:aesthir:Downloads:Some Image.jpg" as file specification -- (C)
set ImageFile to "/Users/aesthir/Downloads/Some Image.jpg" -- (D)
set ImageFile to "/Users/aesthir/Downloads/Some Image.jpg" as POSIX file -- (E)
	
tell application "System Events" to delete ImageFile

Since most of the errors seem to be asking for a reference, I make the object a reference to make it work. As for Yvan’s suggestion of using the class “disk item”, the variable is set without calling an application.

Thanks Nigel! The to methods seemed absolutely identical to me before, I understand the difference now.

What I’m trying to do (exactly):
I need to use “System Events” to delete a file from a handler. The file can contain the property (I think it’s a property anyway) “result”, a direct pointer to a file in any format, or a variable that points to the file in any format. Stefan, your example works, but when I tried to place it into my script, I get the same problem, “System Events” complaining it wants a reference. Here is the portion of my script that is causing the problem, with everything extraneous removed and nothing changed, except the values of 3 variables [“BackgroundFolder”/“PictureName”/“BackgroundPicture”], all of which are set elsewhere in the script to the values below:

global PictureName
set BackgroundFolder to "/Users/aesthir/Library/Application Support/Finder Window Re-Bounder/Finder Window Backgrounds/" as Unicode text
set PictureName to "│Users│aesthir│Downloads│Image_Info_Classes_for_RB│Images│background.jpg" as Unicode text
return my CopyBackgroundImage(BackgroundFolder)

on CopyBackgroundImage(BackgroundPictureFolder)
	--> .blah . blah . <--
	set BackgroundPicture to "/Users/aesthir/Downloads/Image_Info_Classes_for_RB/Images/background.jpg" as Unicode text
	--> Check to see if the image exists, if so, delete it <--
	try
		set PictureSavePath to ((BackgroundPictureFolder & PictureName) as POSIX file) as alias
		tell application "System Events" to delete PictureSavePath --> wtf?
	end try
	tell application "Finder" to set name of ((duplicate (BackgroundPicture as POSIX file) to POSIX file BackgroundPictureFolder with replacing without exact copy) as alias) to PictureName
	--> .blah . blah . <--
end CopyBackgroundImage

Aesthir

I don’t understand why you’re working with POSIX paths and millions of coercions and using System Events to delete the file instead of the Finder which is needed anyway to duplicate the file

Try this, I omitted without exact copy because it’s not available on 10.6


global PictureName
set BackgroundFolder to (path to application support folder from user domain as text) & "Finder Window Re-Bounder:Finder Window Backgrounds:"
set PictureName to "│Users│aesthir│Downloads│Image_Info_Classes_for_RB│Images│background.jpg"
return my CopyBackgroundImage(BackgroundFolder)

on CopyBackgroundImage(BackgroundPictureFolder)
	--> .blah . blah . <--
	set BackgroundPicture to (path to downloads folder as text) & "Image_Info_Classes_for_RB:Images:background.jpg"
	--> Check to see if the image exists, if so, delete it <--
	
	tell application "Finder"
		if exists file PictureName of folder BackgroundPictureFolder then
			delete file PictureName of folder BackgroundPictureFolder
		end if
		set duplicatedFile to duplicate file BackgroundPicture to folder BackgroundPictureFolder with replacing
		set name of duplicatedFile to PictureName
	end tell
	--> .blah . blah . <--
end CopyBackgroundImage


Hello Stephan

(1) we aren’t forced to use the Finder to duplicate a file.
(2) using System Events to delete files is interesting because it really delete while the Finder just move to the trash.

On my side I dropped entirely the use of the Finder except when I must deal with the windows and icons.

Yvan KOENIG (VALLAURIS, France) jeudi 12 avril 2012 08:38:06

Hi Stefan, I have it working with the “Finder” already but this is a temporary solution. here is what I use:

tell application "Finder"
	try
		set PictureSavePath to (((BackgroundPictureFolder & PictureName) as POSIX file) as alias)
		delete PictureSavePath
	end try
	set name of ((duplicate BackgroundPicture to POSIX file BackgroundPictureFolder with replacing without exact copy) as alias) to PictureName
end tell

However, the problems with the “Finder” are two-fold: :confused:

[b](1)[/b] As [b]Yvan[/b] said, the "Finder" trashes the file, which I want deleted. Using [i]do shell script[/i] and [i]rm[/i] is ridiculously slow and not feasible unless there is no other choice.
[b](2)[/b] Your version (and my temporary one) are noisy, making a "trash-sound" every time it passes this point in my script. It's really not a problem to mute the sound and then un-mute again, but it seems like too much extra crap that doesn't need to be there if "System Events" can do it (and I know it can ” I just can't get the wording right).

Finally, this is a tiny section in a 10,000+ word (930 lines ” and that’s not including the library modules it depends upon) script I wrote that does a huge amount of string manipulation with filenames, constantly swapping sections. Every scripting addition required can handle POSIX files seamlessly, so can “System Events”, and I was a shell programmer long before learning AppleScript so POSIX files sit nicely in my world-view (meaning I know everything about how to handle them imaginatively, as well as their properties, quirks, and special cases). Since the “Finder” is the only application used in my script that doesn’t like POSIX paths, I only need to coerce when it’s required, like when duplicating a file.

Aesthir

Hello

the edited handler #2 which I posted on 11 avril 2012 22:49:12 use System Events to delete the file :rolleyes:

Trashing is noisy because you urged the System to behave this way (thru the System PrefPane entitled Sound.

Yvan KOENIG (VALLAURIS, France) jeudi 12 avril 2012 16:03:45

[b]

Yvan, I noticed your script worked even before you edited it. However, I could not integrate your solution into my script properly. I figured out the problem though, it seems “System Events” has trouble with coercing an alias into a disk item directly. Well, as it turns out, a string containing a POSIX path coerces nicely into a disk item, making your solution work. thank you! :slight_smile:

Doesn’t work:

tell application "System Events" to delete disk item (((BackgroundPictureFolder & PictureName) as POSIX file) as alias)

Works:

tell application "System Events" to delete disk item (BackgroundPictureFolder & PictureName)

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔

[b]

Yes, I know, but I like and want the sound when I manually trash something. I don’t want my script making sounds I didn’t specifically program into it though. Of course, I could add this, but unnecessary now:

set Mute to output muted of (get volume settings)
if not Mute then set volume with output muted
--> trash file <--
if not Mute then set volume without output muted

On that note, is it too much to ask “System Events” to copy a file? I like the “Finder” bong sound when manually moving/duplicating, but not while my script is executing. Is there a way to copy/duplicate a file without the “Finder”? (and without “do shell script” of course)

tell application "System Events" to duplicate disk item (BackgroundPictureFolder & PictureName) to folder BackgroundPictureFolder
	--> System Events got an error: Files can not be copied.
tell application "System Events" to copy disk item (BackgroundPictureFolder & PictureName) to folder BackgroundPictureFolder
	--> System Events got an error: Files can not be copied.

” [i][b]Aesthir[/b][/i]

Why not use Extra Suites ?


	tell application "Extra Suites"
		ES delete file ff --without warnings
	end tell

[b]

I can’t get Extra Suites to work with Lion… I even tried Extra Suites for Intel… wouldn’t so much as boot up. :confused: I searched for a Lion compatible version but it looks like the project is discontinued by the author, so any commands involving Extra Suites are out of the question on my end.

Aesthir


(*
Using the late free ASObjC Runner.app
available thru :
<http://www.macosxautomation.com/applescript/apps/runner.html>
We may duplicate quickly.
There is a short offset when we call ASObjC Runner.app for the 1st time but other calls are fast.
I added it to the list of items opened during the startup process.

Yvan KOENIG (VALLAURIS, France)
2012/04/18
*)

set aFile to choose file
--> alias "Macintosh HD:Users:<yourAccount>:Desktop: space2tab copie.applescript"
set aFolder to choose folder
tell application "System Events" to tell disk item (aFile as text)
	--> alias "Macintosh HD:Users:<yourAccount>:Desktop:4tests:"
	set fName to name
	--> " space2tab copie.applescript"
end tell

tell application "ASObjC Runner"
	manage file aFile copying into aFolder overwriting no silently
	--> {file "Macintosh HD:Users:<yourAccount>:Desktop:4tests:space2tab copie.applescript"} when there was no such file
	--> {} when the file already exists
	manage file aFile copying as ((aFolder as text) & "fake" & fName) overwriting no rename
	--> {file "Macintosh HD:Users:<yourAccount>:Desktop:4tests:fake space2tab copie-1.applescript"} when there was no such file
	--> {file "Macintosh HD:Users:<yourAccount>:Desktop:4tests:fake space2tab copie-1.applescript"} when the file already exists
	(*
Delete without moving to the trash
*)
	manage file ((aFolder as text) & "fake" & fName) with deleting and finality
	--> {}
end tell

Yvan KOENIG (VALLAURIS, France) mercredi 18 avril 2012 10:09:08