On Idle handler

Hey All,

I’ve been working on this for a couple days and tried many different approaches (some of which were unnecessarily complicated) and the script itself may contain some unnecessary variables that I have yet to clean out. Anyway, this is supposed to be a backup script that will backup a folder or multiple folders and all their contents if it has not been backed up before and then will only backup any file therein that has been modified. The script works basically, but I wanted to make it a stay open app that would do its thing at a certain time of the day. When I added the on idle handler, and the app activates, it starts fine but ends up erroring saying that the variable “mainName” is not defined. If I move the on idle statement to just under the property declaration, then it has the same error but with a different variable. Is this error because of the call to the recursion handler and returning some sort of conflicting info or what? Thank you all.

PreTech

property backupList : {}

global foldCont, primeName, foldPath, filePath, testDate, thePath, thisPath, theDate, theTime, mainFold, theName, classCheck
set dun to 0
set astid to AppleScript's text item delimiters
set arch to "untitled archive.sit"
set tempList to {}
set tNames to {}
set iList to {}
set iNames to {}
set bMainNames to {}
set mainName to {}
set theName to ""
set backList to {}
set foldCont to {}
set bName to {}
set classCheck to {}
set searchCont to {}
set searchContName to {}
set theTime to time of (current date)
set testDate to ((current date) - theTime) -- Sets the test time to 12 AM of the current day. If modification date (time) of a file is greater than this, it is backed up.
tell (current date) to tell (its month as string) & year * 100 + day to set theDate to text -2 thru -1 & text 1 thru 3 & text -4 thru -3
-- I believe thanks go to kai for the preceeding line.
on idle
	if theTime is greater than 43200 then
		tell application "Finder"
			-- set initial destination for backup
			if not (exists folder "theBackupFolder" of desktop) then
				make new folder at desktop with properties {name:"theBackupFolder"}
				set label index of folder "theBackupFolder" to 4
			end if
			-- set final destination for backup
			if not (exists folder "compressedFolders" of desktop) then
				make new folder at desktop with properties {name:"compressedFolders"}
				set label index of folder "compressedFolders" to 4
			end if
			set destFold to folder "compressedFolders" of desktop
			-- choose to run the backup, search for files previously backed up, or quit.
			display dialog "What do you need to do?" buttons {"Search", "Backup", "Cancel"} default button 2 giving up after 10
			set buttChoice to button returned of the result
			if buttChoice is "Search" or "" then
				display dialog "Enter partial, or complete, file name to search for." default answer ""
				set search to text returned of the result
				repeat with aFile in destFold
					set theName to name of aFile
					if theName contains search then
						set searchCont's end to aFile as alias
						set searchContName's end to theName
					end if
				end repeat
				try
					set choice to choose from list searchContName with prompt "Choose files to retrieve." with multiple selections allowed
				on error
					display dialog "Sorry, nothing matching " & "\"" & search & "\"" & " was found."
				end try
				if choice is not false then
					set theDate to (current date)
					set m to month of theDate as text
					set d to day of theDate
					set t to time of theDate as text
					make new folder at desktop with properties {name:m & d & t}
					repeat with choiceItem in choice
						repeat with anItem in searchCont
							set thisName to name of anItem
							if thisName is (choiceItem as text) then
								copy anItem to folder (m & d & t) of desktop
							end if
						end repeat
					end repeat
				end if
			else if buttChoice is "Cancel" then
				quit me
			else
				-- if continuing with backup, this sets up to add or remove folders from the backup list or to continue with the folders already designated.
				display dialog "Do you need to add or remove more folders for backup?" & return & return & "If you have not used this program before, click add to setup folders for backup." buttons {"Add", "Remove", "Continue"} default button "Continue" giving up after 10
				set butChoice to button returned of the result
				if butChoice is not "Continue" then
					if butChoice is "Add" then
						choose folder with prompt "Choose folders for addition." with multiple selections allowed
						set addList to result
						repeat with anItem in addList
							set backupList's end to anItem
						end repeat
					else if butChoice is "Remove" then
						if backupList is not {} then
							choose from list backList with prompt "Choose folders to remove." with multiple selections allowed
							set removeList to result
							repeat with anItem in backupList
								if name of anItem is not in removeList then
									set tempList to tempList & anItem
								end if
							end repeat
							set backupList to tempList
						else
							display dialog "There are no folders in the Backup List to remove."
						end if
					end if
				end if
				-- get the names of all folders for backup 
				repeat with aName in backupList
					set mainName's end to name of aName
					repeat with folName in aName
						set backList's end to name of folName
					end repeat
				end repeat
				set thisPath to folder "theBackupFolder" of desktop as string
				-- if the initial backup folder destination has files then this sets a list of all folders in the backup folder.
				if entire contents of folder "theBackupFolder" of desktop is not {} then
					repeat with bFold in folder "theBackupFolder" of desktop
						set bMainNames's end to name of bFold
						repeat with backName in bFold
							set bName's end to name of backName
						end repeat
					end repeat
				end if
				-- start the process of getting folders and files out of the folder needing backup.
				repeat with aFolder in backupList
					-- this gets a folder of one of the folders for backing up.
					repeat with anFold in aFolder
						set theFold to anFold as alias
						-- if a folder has never been backed up, then this backs up the entire folder.
						if (name of theFold) is not in bMainNames then
							duplicate theFold to thisPath
						end if
						-- set a unique name for the files being backed up for ease of location when necessary.
						set theName to name of theFold & theDate & "~" & theTime as text
						-- set the path to the folder and subfolders
						make new folder in folder thisPath with properties {name:theName}
						set mainFold to (result)
						set primeName to mainFold
						-- call subroutine for getting nested folders.
						my theRecur(theFold)
					end repeat
				end repeat
				-- after the files are moved to the initial backup folder, then this compresses the folders and moves them to their final destination.
				set folToComp to folder "theBackupFolder" of desktop
				set destFold to folder "compressedFolders" of desktop
				set dest to destFold as string
				-- get list of names for comparison.
				repeat with anItem in folToComp
					set tempList's end to anItem as alias
					set tNames's end to (name of anItem)
				end repeat
				repeat with anItem in destFold
					set iList's end to anItem as alias
					set AppleScript's text item delimiters to "."
					set thisName to name of anItem
					set iNames's end to (first text item of thisName)
				end repeat
				set AppleScript's text item delimiters to ""
				repeat with aName in tNames
					if iNames does not contain aName then
						repeat with theItem in tempList
							if entire contents of theItem is not {} then
								set theName to name of theItem as text
								if theName is (aName as text) then
									-- set initial archive name to untitled archive.sit so it can be named later.
									set initArch to dest & arch
									set fullName to theName & ".sit"
									-- make compressed file.
									tell application "StuffIt Deluxe"
										with timeout of 6000 seconds
											make new archive with properties {location:file initArch}
											stuff {theItem} into archive arch with replacing
											close archive arch
										end timeout
									end tell
									-- rename the archive to that of the folder it was made of.
									select file "untitled archive.sit" of folder dest
									set thisFile to selection as alias
									set name of thisFile to fullName
								end if
							end if
						end repeat
					end if
				end repeat
				set AppleScript's text item delimiters to astid
			end if
			tell application "StuffIt Deluxe"
				quit
			end tell
		end tell
		set dun to 1
	else if dun is 1 then
		quit
	end if
	return 30
end idle

-- the recursion handler. This gets every subfolder of the parent.
on theRecur(thisFold)
	tell application "Finder"
		repeat with anItem in folder thisFold
			set thisItem to anItem as alias
			if class of anItem is folder then
				set theName to name of thisItem
				make new folder in mainFold with properties {name:theName}
				set mainFold to (result)
				set newFold to anItem as alias
				my theRecur(newFold)
			end if
			if class of anItem is document file then
				if modification date of thisItem is greater than testDate then
					duplicate anItem to mainFold
				end if
				set foldCont's end to thisItem
			end if
			if class of anItem is folder then
				set classCheck's end to 1
			end if
			if contents of classCheck contains 1 then
				set mainFold to primeName
				set classCheck to {}
			end if
		end repeat
	end tell
end theRecur

Well, I played around with this a little and this is what I am trying at the moment.

on idle
	set dun to 0
	if time of (current date) is greater than 50520 then
		set dun to 1
		tell application "theBackup V 1.0.0"
			activate
		end tell
		
	end if
	if dun is 1 then
		quit
	end if
	return 120
end idle

I removed the idle handler in the backup script and used an idle handler to activate my backup application. This starts the app and it runs completely but the idle handler errors saying “Connection is invalid” with an “Ok” or “Edit”. Not sure what this means. Thanks.

PreTech

In response to the first post, mainName hasn’t been declared as a property or a global.

It’s really just a question of scope, PreTech.

When you added the idle handler, I assume that you moved a good deal of code from the top level of your original script into it. Since the variable “mainName” isn’t defined within the handler, it needs to be declared either as a property or a global variable.

My guess is that the stay-open app is expecting a response from the one being called, which it doesn’t get. Try something like this, which should execute the idle handler only a couple of times - once after being launched, and again when the backup is due:

on idle
    set time_to_backup to 50520 - ((current date)'s time)
    if time_to_backup ≤ 0 then
        ignoring application responses
            tell application "theBackup V 1.0.0" to run
        end ignoring
        quit
        return 0.1
    end if
    time_to_backup
end idle

It does look kinda familiar… :wink:

I forgot to say Thanks. So - Thanks Kai!:slight_smile:

PreTech