Bizarre Entourage display/redraw issue...

Hello, Everyone!

I’ve been working on this script a long time… it is designed to be used with Microsoft Entourage. In order to slim down the email database size, it saves attachments in a specified path (~/Documents/Archived Attachments/[current year]/[current date]), links the email to the newly saved version of the attachment, and then finally (assuming the save was successful) deletes the attachment from the email. I have a nearly identical version working with the older version of Entourage (version X), and it runs fine (mostly). However, this one, for the 2004 version of Entourage, has a really strange issue, which I can not figure out:

As the script is running, even though no windows are told to open (in fact, the script closes ever Entourage window before it begins the archiving procedure), little portions of message windows start appearing here, there & everywhere on the screen. Not complete windows, just small pieces of windows. You can not close them by any normal means, as they are not normal windows. The only way I’ve found to get rid of all these little window pieces that show up is to use Exposé. Hit F9, then F9 again, and all the artifacts that were there are gone… but new ones show up shortly again.

I’ve attached a copy of the script to this post… and it is a ˜SAFE’ version. That is, the line where the script deletes attachments from your email is commented out, just in case anyone would be willing to try out the script to help me out. If you do, please do make a backup copy of your current Entourage identity, just in case, though I can say I’ve done extensive testing and have never had a lost/damaged email, attachment, database, or what have you.

Can anyone tell me what I’m missing?

Thanks so much!

Jon


(*
Features to add:
Link archived attachment(s) to the message it came from. ***DONE***
Progress box (better yet, a bar) with constantly updating attachment count.

Bugs:
1) Throughout script, fragments of message windows appear for no apparent reason!

Pre-Production Changes:
1) Set duration before attachments are archived (6 months?)

*)

display dialog "Entourage is about to archive your attachments.  You may continue working in other applications, but it is best if you can avoid using Entourage." & return & return & "Another message like this one will come up when the archiving process is complete." buttons {"Go!"} default button 1


--declaration of global variables:
global totalAttachmentCount

--We're starting at 0 attachments archived.
set totalAttachmentCount to 0

--Generate the appropriate path to save attachments in:
set svPath to createSavePath()


tell application "Microsoft Entourage"
	try
		close every window
	on error errMsg number errNum
		display alert "Error: Failed close every window command." & return & errMsg & return & errNum
	end try
	try
		set outerFolders to every folder
	on error errMsg number errNum
		display alert "Error: Failure to set outerFolders to every folder." & return & errMsg & return & errNum
	end try
	
	try
		set outerFolderCount to (count outerFolders)
	on error errMsg number errNum
		display alert "Error: Failure to set outerFolderCount to (count outerFolders)." & return & errMsg & return & errNum
	end try
	
	try
		set todaysDate to (current date)
		my archive_and_save(svPath, outerFolders, outerFolderCount, todaysDate) --Main routine call
		set doneDate to (current date)
		set timeToRun to (doneDate - todaysDate)
		display dialog "All done!" & return & return & totalAttachmentCount & " attachments were archived in just " & timeToRun & " seconds." buttons {"Killer"} default button 1 with title "Spyder Attachment Archiver"
		open main window
	on error errMsg number errNum
		display alert "Error: Failure in archive_and_save sub call." & return & errMsg & return & errNum
	end try
	
end tell







--   SUBROUTINES     SUBROUTINES      SUBROUTINES    SUBROUTINES


on archive_and_save(savePath, outsideFolders, outsideFolderCount, todaysDate)
	tell application "Microsoft Entourage"
		repeat with i from outsideFolderCount to 1 by -1
			try
				set theFolder to item i of outsideFolders
			on error errMsg number errNum
				display alert "Failure to set theFolder to item i of outsideFolders." & return & errMsg & return & errNum
			end try
			
			try
				my extract_attachments(theFolder, savePath, todaysDate)
			on error errMsg number errNum
				display alert "Failure in extract_attachments call." & return & errMsg & return & errNum
			end try
		end repeat
	end tell
end archive_and_save




on extract_attachments(thisFolder, save2Path, todaysDate)
	set bogusPath to save2Path & "BOGUS:"
	tell application "Microsoft Entourage"
		try
			set thisFolderCount to (count folders of thisFolder)
		on error errMsg number errNum
			display alert "Error - unable to set thisFolderCount to (count folders of thisFolder).  Setting folder count to 0." & return & errMsg & return & errNum & return & "Folder Name: " & (name of thisFolder)
			set thisFolderCount to 0
		end try
		try
			if thisFolderCount is greater than 0 then
				try
					set innerList to every folder of thisFolder
					set innerListCount to (count innerList)
				on error errMsg number errNum
					display alert "Failed to set innerList to every folder of thisFolder, or to set innerListCount to (count innerList)." & return & errMsg & return & errNum
				end try
				repeat with m from innerListCount to 1 by -1
					try
						set innerFolder to item m of innerList
						my extract_attachments(innerFolder, save2Path, todaysDate)
					on error errMsg number errNum
						display alert "Failure in recursive extract_attachments call." & return & errMsg & return & errNum
					end try
				end repeat
			end if
		on error errMsg number errNum
			display alert "Failure in repeat digging into folders, recursively calling extract_attachments subroutine." & return & errMsg & return & errNum
		end try
		try
			try
				set folderMsgs to every message of thisFolder
				set messagesCount to (count messages of thisFolder)
			on error errMsg number errNum
				display alert "Failure to set folderMsgs to every message of thisFolder." & return & errMsg & return & errNum
			end try
			repeat with k from messagesCount to 1 by -1
				try
					set thisMsg to item k of folderMsgs
				on error errMsg number errNum
					display alert "Failure to set thisMsg to item k of folderMsgs." & return & errMsg & return & errNum
				end try
				try
					set howOldIsIt to ((time received) of thisMsg)
				on error errMsg number errNum
					display alert "Failure to set howOldIsIt to ((time received) of thisMsg)." & return & errMsg & return & errNum
					try
						set howOldIsIt to ((time sent) of thisMsg)
					on error errMsg number errNum
						display alert "Failure to set howOldIsIt to ((time sent) of thisMsg)." & return & errMsg & return & errNum
						set howOldIsIt to current date
					end try
				end try
				try
					try
						set attachmentCount to (count attachments of thisMsg)
					on error errMsg number errNum
						set attachmentCount to 0
						display alert "Failure to set attachmnetCount to (count attachments of thisMsg).  Setting attachment count to 0." & return & errMsg & return & errNum
					end try
					-- CHANGE THIS FOR PRODUCTION VERSION FROM 6 MINUTES TO 6 MONTHS OR 9 MONTHS!!!!!!!!!
					if (attachmentCount is greater than 0) and ((((current date) - (howOldIsIt))) > (minutes * 6)) then
						try
							set msgAttachments to every attachment of thisMsg
						end try
						repeat with l from attachmentCount to 1 by -1
							try
								set thisAttachment to item l of msgAttachments
							on error errMsg number errNum
								display alert "Failure to set thisAttachment to item l of msgAttachments." & return & errMsg & return & errNum
							end try
							try
								save thisAttachment in bogusPath
								set totalAttachmentCount to totalAttachmentCount + 1
								set attachName to name of thisAttachment
								set safeAttachName to my replacecolons(attachName)
								set newFileLocation to (save2Path & safeAttachName)
								link thisMsg to alias (newFileLocation)
								--Below is the DELETE ATTACHMENT line... please un-comment this for real use.
								--delete thisAttachment
							on error errMsg number errNum
								display alert "Failed to save thisAttachment in bogusPath." & return & "Message: " & (name of thisMsg) & return & "Attachment: " & (name of thisAttachment) & return & errMsg & return & errNum
							end try
							set thisAttachment to null
						end repeat
					end if
				on error errMsg number errNum
					display alert "Failure:" & return & errMsg & return & errNum
				end try
			end repeat
		on error errMsg number errNum
			display alert "Failure:" & return & errMsg & return & errNum
		end try
	end tell
end extract_attachments


--This subroutine simply creates and returns the path for saving attachments to
on createSavePath()
	set todaysDate to (current date)
	
	--Format months for save path
	if (month of (todaysDate) as integer) < 10 then
		set theMonth to 0 & (month of (todaysDate) as integer) as Unicode text
	else
		set theMonth to (month of (todaysDate) as integer) as Unicode text
	end if
	
	set theDay to day of (todaysDate) as Unicode text
	set theYear to year of (todaysDate) as Unicode text
	set theDate to ((theYear) & "_" & (theMonth) & "_" & (theDay)) as Unicode text
	
	-- Try to create Archived Attachments folder, simply fails out if it already exists.
	set docsPath to (path to documents folder)
	try
		tell application "Finder"
			make new folder at docsPath with properties {name:"Archived Attachments"}
		end tell
	end try
	
	--Create a folder for the year
	try
		do shell script "mkdir ~/Documents/Archived\\ Attachments/" & theYear
	end try
	
	--Create a folder for today's archive.
	try
		do shell script "mkdir ~/Documents/Archived\\ Attachments/" & theYear & "/" & theDate
	end try
	
	set svPath to ((docsPath as text) & "Archived Attachments:" & theYear & ":" & theDate & ":") as text
	return svPath
end createSavePath

--This routine borrowed from Paul Berkowitz's 'Save Attachments 2004'
to replacecolons(someText)
	set AppleScript's text item delimiters to {":"}
	set textItems to text items of someText
	set AppleScript's text item delimiters to {"-"}
	set someText to textItems as Unicode text
	set AppleScript's text item delimiters to {"/"}
	set textItems to text items of someText
	set AppleScript's text item delimiters to {"-"}
	set someText to textItems as Unicode text
	set AppleScript's text item delimiters to {""}
	return someText
end replacecolons

Moved to AppleScript | OS X forum

I have side question: are you sure that Entourage database contains attachments…?
I recall Entourage as having specific external storage folders that it uses for attachments…

Thanks for your reply, Eelco!

Entourage does indeed store it’s attachments in that one monolithic database file. If you open an attachment right from email, it will save it (temporarily) in a folder called “Saved Attachments” in the MUD folder.

Running this script, then doing a rebuild of the database typically shrinks the db down by about a factor of 10!

If I could just get the graphical artifacts of the messages to stop popping up, it would be just about ready for use!

Thanks again,
Jon

Jon,

Just a couple of thought’s:

  1. My first idea was that a some guys at M$ out there might need to be arrested - it is dysfunctional & outrageous to store attachments this way. On the other hand, Office was designed at the time that there was little metadata technology around - so there might be big linking issues out there when storing attachmets externally. And I must say, whatever big the gigabyte Entourage database grows, it is consistent and robust.
    This rises issues around the robustness of your solution, i.e. when someone rebuilds his hard drive’s directory, will the links persist…? If that’s questionable, it would only be useful as a shadow database, i.e. where the primary Entourage database remains intact on a server and you have a more compact, mobile image of it for just reading purposes.
  2. In my environment, M$ Apps have had redraw issues all their life, i.e. on PPC and the more on Intel (via Rosetta), as soon as they start working harder, are requiring more memory or system resources. Especially when called externally from scripts, which seems to require significant CPU power, this will happen.
    It is NOT just a M$ issue, other Rosetta apps have it either.
  3. That said, I’ve run your script and the redraw problems didn’t occur.
    I found out that the main message pane didn’t get closed when bringing Entourage up front again (although it should by the first paragraph of your script), which suggests that some action (link updates?) forces it to redraw, which it then probably can’t finish because of the sequence of Applescript calls being fired.
    Theoretically, it might be that the wicked Entourage internals do not “know” that its windows are closed, so you might try to make a bogey call “set r to the windows whose visible is true” but it’s doubtful if that works.
  4. You might consider hiding all its windows in the repeat loop, but that will require significantly more CU power.
  5. You might try to temprarily comment out any action that you suspect to force a redraw - painfully lots of work.
  6. Why bother at all…?

Concluding: I like your script (it is striking to flip through all the Finder previews that I’ve never seen before) but I can’t help as long as the problem does not occur with me.

Hi Eelco,

Thanks so much!! I greatly appreciate you trying out the script, and I’m glad to hear the redraw issue didn’t happen on your machine… how bizarre! I’ve found the issue (and others can arise too) to be worse & worse as it is run on larger & larger databases. I agree… LOL… someone at M$ should be arrested for storing attachments within the db! =)

I’ve actually tried putting the ‘close’ command in the repeat loop… no dice. Since the windows aren’t fully redrawing, but just little artifacts are showing up, the windows think they are indeed already closed.

I’ll give a shot to commenting out the linking command… that was a tough one to get working, and definitely a suspect. That being said, before I got the linking working, this issue was still happening.

I keep hoping an update to Entourage will fix the issue, but no luck so far!

As a potential alternative, does anyone know a way to trigger Apples Expose functions through an AppleScript? Hitting F9/F10/F11 twice re-draws the entire display, it seems, and clears everything out of the way. It would be an ugly fix, but at least it would clear things up…

Thanks again, Eelco! :smiley:

Just another shot:
If you’d experiment with


tell me to do shell script "sleep 5"

in several locations in your repeat loop in order to give Entourage some “puff” to do its redraw and admin tasks.
This will render your script to a drag, but that’s temporary and you could see (inspecting the event loop) when redraw happened.