Ximeta's NDAS Utility - Quick & Dirty UI Scripting for NDAS Backups

Hi everyone. Recently I bought an external network attached hard drive that uses Ximeta’s NDAS driver, a proprietary system for network attached storage. I almost returned the darn thing, because – to my unbelievable frustration – there is no built-in scripting for the “NDAS Utility” application that you have to run every time you have to connect or disconnect the drive. The way it works is: first you eject the volume(s) in the Finder, but then you’re not finished! Unless you also run their stupid “NDAS Utility” program and “Unmount” the drive manually, you get error messages saying a device was not put away properly if you, say, move your laptop out of your home network to take it to work.

It’s kind of unbelievable that Ximeta would release a product incapable of doing the basic work that most of us buy it to do: automated backups. But they did. (If you can’t automatically mount and unmount the drive at 4 AM or whenever you want the automated backups to run, then you might as well just skip the network attached storage and buy a USB/FireWire drive instead – it’s easier to plug and unplug a cable than it is to run “NDAS Utility” twice!) I asked Ximeta about this problem; they were totally unhelpful. So I decided to take half a day of my life and do a quick, dirty, thrown-together version of the work they should have paid a real programmer to do a long time ago: I used UI Scripting, and a lot of trial and error, to write a script that mounts and unmounts an NDAS drive by running their “NDAS Utility.” (I am not a programmer and this is the first applescript snippet I’ve ever posted online.)

I make no guarantees about whether this script will work for you. It almost certainly won’t work without modification if you have more than one NDAS drive (although multiple partitions on one NDAS drive are fine - that’s what I have). But given the glaring lack of support from Ximeta, it seemed like this would be useful enough to others that I should try posting it. Try it and see if it works! NOTE: I am using NDAS Utility 1.6.6 on Mac OS X (10.4.8).

I also have one question that I wonder if others could help me solve. Ejecting volumes in the finder is kind of tricky: a lot of the time, maybe because of indexing or some other process, the Finder won’t let me eject some of my backup volumes. I find that if I try again and again, eventually it lets me eject them. The script below keeps trying, waits until they’re gone, and then finally Unmounts the drive (using NDAS utility, through UI scripting). But often, this leaves a whole pile of alert messages in the Finder that I have to click through after it’s all over, saying that various of my volumes could not be ejected because they were in use. When this error occurs, my script just waits around and keeps trying. However, that leaves a pile of alerts.

Does anyone know any way to either:
(a) tell the finder to eject a disk while SUPPRESSING the alert message if it doesn’t work, or
(b) click OK to the alert messages if they appear?

I tried to do the latter, but ran into lots of trouble because the finder was considered “Busy” when it had an alert message at the front, so it was tough to get UI scripting to do anything, including checking whether there was an alert message or hitting “OK.”

Thanks, and I hope some of you frustrated NDAS users out there find this script helpful!

  • Joey


-- SYNTAX:
--
-- NDAS_Unmount({"Michael", "Lindsay", "Buster", "GOB"})
-- In other words, NDAS_Unmount takes a _LIST_ of volume names.
-- Make sure you put them in a list, not as separate parameters.
-- 
-- NDAS_Mount()
-- In other words, NDAS_Mount() takes nothing.


on NDAS_Mount()
	return NDAS_stupid_workaround("Mount")
end NDAS_Mount

on NDAS_Unmount(disks_to_eject)
	if eject_my_disks(disks_to_eject) = true then
		delay 0.5
		return NDAS_stupid_workaround("Unmount")
	else
		return "Sorry, couldn't eject your disks, so I didn't try to unmount the NDAS."
	end if
end NDAS_Unmount

on eject_my_disks(disks_to_eject)
	
	-- sometimes it takes a few times before you can actually eject a disk.
	-- The "30" in the next line is totally arbitrary:
	-- you decide how persistent you want this thing to be.
	repeat with i from 1 to 30
		delay 2
		-- Let's try and eject the disks named in the array
		tell application "Finder"
			set my_disks to name of every disk
			set eject_error_count to 0
			repeat with which_disk from 1 to the number of items in disks_to_eject
				try
					set the_disk to item which_disk of disks_to_eject
					if my_disks contains the_disk then
						eject the_disk
					end if
				on error
					set eject_error_count to eject_error_count + 1
					-- the more errors we got, the more seconds we'll give it!
					delay (eject_error_count + 1)
				end try
				delay (eject_error_count + 1)
			end repeat
		end tell
		-- Now let's see if they got ejected successfully. If so, we return true
		if are_they_gone(disks_to_eject) is true then
			return true
		end if
		-- if not, keep on going through the repeat!
		delay eject_error_count
		
	end repeat
	
	-- if we REALLY couldn't eject the darn thing, we return false
	return false
end eject_my_disks

on are_they_gone(disks_to_eject)
	-- Check and see if they actually got ejected
	-- This function returns "True" if so, "False" if any is still there.
	tell application "Finder"
		set what_to_return to true
		set my_disks to name of every disk
		repeat with i from 1 to (the number of items in disks_to_eject)
			if my_disks contains item i of disks_to_eject then
				set what_to_return to false
			end if
		end repeat
	end tell
	return what_to_return
end are_they_gone

on NDAS_stupid_workaround(mount_or_unmount)
	
	-- Make sure UI Scripting is enabled...
	tell application "System Events" to set isUIScriptingEnabled to UI elements enabled
	if isUIScriptingEnabled = false then
		tell application "System Preferences"
			activate
			set current pane to pane "com.apple.preference.universalaccess"
			display dialog "Please \"Enable access for assistive devices\" and try again."
			return
		end tell
	end if
	
	--see whether we're trying to mount or unmount
	if mount_or_unmount = "Mount" then
		set the_goal to "Mount Read/Write"
	else if mount_or_unmount = "Unmount" then
		set the_goal to "Unmount"
	else
		return "I don't understand what you want me to do."
	end if
	
	--run NDAS Utility
	tell application "Finder"
		open application file "NDAS Utility.app" of folder "Utilities" of folder "Applications" of startup disk
	end tell
	delay 0.5
	
	-- click on the hard disk (I just have one NDAS drive)
	tell application "System Events"
		tell process "NDAS Utility"
			-- sometimes takes a few tries if the app was slow to load
			repeat with i from 1 to 10
				set try_again to false
				try
					delay 1
					tell window "NDAS Utility"
						tell scroll area 1
							tell outline 1
								select row 2
							end tell
						end tell
					end tell
				on error
					set try_again to true
				end try
				if try_again = false then exit repeat
			end repeat
			delay 1
			-- now use the menu bar to choose "Unmount" or "Mount Read/Write"
			tell menu bar 1
				tell menu bar item "Management"
					tell menu "Management"
						click menu item the_goal
					end tell
				end tell
			end tell
			
			-- now, for Unmount only, click "OK" in the dialog box
			if mount_or_unmount = "Unmount" then
				delay 0.5
				tell window 1
					click button "Unmount"
				end tell
			else
				-- The extra delay here is to avoid a weird error
				-- where sometimes it doesn't really mount...
				delay 4
			end if
			
		end tell
	end tell
	
	-- now quit NDAS Utility.
	delay 2
	tell application "NDAS Utility"
		quit
	end tell
	
end NDAS_stupid_workaround