![]() |
John VanDyk has been innovating with information technology for more than 20 years. Read more... |
Programmatically suspending, quitting, and resuming Parallels Desktop for scheduled backup
I wanted to do automatic scheduled backups with the awesomely amazing SuperDuper!. The computer to be backed up was a Mac Mini running Mac OS X 10.5 Leopard. But the problem was that Parallels Desktop was running all the time. And everyone knows that when you try to back up open files that may be changing, Bad Things Happen.
"No problem," I thought. Since SuperDuper! allows you to run a script before and after a scheduled backup (have I mentioned how brilliant SuperDuper! is?) I'll use a script to suspend the virtual machine before the backup, and resume it afterward.
So I fired up Script Editor and went to open up Parallels Desktop's AppleScript Dictionary.
Uh.
Apparently Parallels Desktop does not implement AppleScript.
I was stymied until I remembered something that the indefatigable Matt Neuburg had written in AppleScript: The Definitive Guide, Second Edition in a chapter titled Unscriptable Applications. The approach is to cheat by using the Accessibility API built into Mac OS X. From there you can direct mouse clicks, radio button selection...in short, all sorts of mayhem. "Aha!" I thought. "I'll just direct Parallels from the Accessibility API! Sort of like the puppeteer in Being John Malkovich."
First I made sure that accessibility was enabled by going to the Universal Access preference pane in System Preferences.
Then I made a shell script for SuperDuper! to run before backup. Here's the script:
#!/bin/sh
osascript /Users/john/suspendparallels.txt
sleep 35
osascript /Users/john/quitparallels.txt
sleep 10
The shell script first executes the suspendparallels.txt AppleScript to suspend the virtual machine:
-- Suspend a Parallels virtual machine.
-- Assumptions:
-- - only one virtual machine is running
-- - the "Enable access for assistive devices" checkbox is checked in the Universal Access control panel
-- Tested on Mac OS X 10.5.7 with Parallels Desktop 4.0.
-- John VanDyk 7/22/2009
tell application "Parallels Desktop" to activate
tell application "System Events"
tell application process "Parallels Desktop"
tell menu "Virtual Machine" of menu bar 1
click menu item "Suspend"
end tell
end tell
end tell
Then the shell script waits for 35 seconds (enough time for the virtual machine to be written to disk), and executes the quitparallels.txt AppleScript:
-- Quit Parallels.
-- Assumptions:
-- - only one virtual machine is running
-- - the "Enable access for assistive devices" checkbox is checked in the Universal Access control panel
-- Tested on Mac OS X 10.5.7 with Parallels Desktop 4.0.
-- John VanDyk 7/22/2009
tell application "Parallels Desktop" to activate
tell application "System Events"
tell application process "Parallels Desktop"
tell menu "Parallels Desktop" of menu bar 1
click menu item "Quit Parallels Desktop"
end tell
end tell
end tell
"But John," I can hear you asking, "why not put these together into one simple AppleScript and just use 'delay 35' to create the pause?" I'll tell you why. Because when you do it that way it doesn't work. Plus I got a scary error about "class released with no pool in place - just leaking". Seriously. So I figured, since AppleScript is always, well, flaky for me, I'd just put as much as I could in the shell script and call out to AppleScript only when necessary.
All right. So now SuperDuper! can clone the drive since the Parallels Desktop Windows XP virtual machine has been suspended and the program has been closed. But what about afterwards, when we want to bring Parallels Desktop up just like it was? Turns out, that's even easier. Here's the shell script that SuperDuper! runs after it completes the copy:
#!/bin/sh
osascript -e 'tell app "Parallels Desktop" to activate'
sleep 10
osascript /Users/john/resumeparallels.txt
That first osascript call is actually launching Parallels Desktop. We give it 10 seconds to launch, which is plenty.
Fortunately it launches with the suspended virtual machine. All we have to do is tell it to resume. Here's resumeparallels.txt:
-- Resume a Parallels virtual machine.
-- Assumptions:
-- - only one virtual machine is running
-- - the "Enable access for assistive devices" checkbox is checked in the Universal Access control panel
-- Tested on Mac OS X 10.5.7 with Parallels Desktop 4.0.
-- John VanDyk 7/22/2009
tell application "Parallels Desktop" to activate
tell application "System Events"
tell application process "Parallels Desktop"
tell menu "Virtual Machine" of menu bar 1
click menu item "Resume"
end tell
end tell
end tell
Presto! It works.
- Log in to post comments
Comments
I get an error with this in applescript
When I compile I get an error that say:
Expected “end” or “end tell” but found unknown token.
Seems to be with the first "tell" statement. I am on 10.5.8 but I doubt the applescript syntax has changed.
Anyone else get this problem?
Bill
Ignore my last but now I have a real issue
Turns out the problem was that I pasted the script and had leading spaces instead of tabs. I've rectified that.
Now I am having a functional issue. I run Parallels in full screen mode and the Parallels menu is not normally displayed at the top. So the tell menu functions have no effect unless I CONTROL/OPTION first. I tried adding a
keystroke (option down, control down} but it still doesn't invoke the menu.
Any ideas?
Just tried this out with
Just tried this out with parallels 6. worked like a charm. thanks for posting this.
Small Comment
As someone completely unfamiliar with scripting on a mac I found this page to be a god-send.
One small comment.
After your scripts are in place you need to give them execute permissions:
Run terminal and execute:
chmod u+x /users/john/stop.sh
chmod u+x /users/john/start.sh
I also had to make the scripts in BBEdit using Unix LF .
I found this page on macdevcenter.com to be most useful:
Common Script Mistakes: Line Endings
Perhaps the most common scripting error occurs when a script is created with BBEdit or some other text editor and the file is saved with Macintosh line endings. There is a Macintosh new line character, ASCII 13, and there is a UNIX new line character, ASCII 8. They are both valid in text documents, but UNIX will not treat a Macintosh line ending as the end of a line.
If you try to execute a script that has Macintosh line endings, you will get a "Command not found" error:
/path/to/script: Command not found.
There are a few ways to change the line endings from Macintosh to UNIX. The easiest is to open the document in BBEdit. Each document has a tool bar at the top. The fifth tool looks like a small document icon. Click on it and a pop-up menu appears. Scroll down and select "UNIX," and then save the script.
To change the line endings from the command line, execute this command in the Terminal:
tr \\r \\n < /path/to/script > /path/to/new_script
Replace /path/to/script with the path to the script with Macintosh line endings, and /path/to/new_script to where you want to save the new file. The two paths cannot be the same, or you will end up creating an empty file.
Common Script Mistakes: Execute Permissions
Another common mistake is incorrect execute permissions. In order to execute a script, the file must have execute permissions. If you try to execute a file that does not have execute permissions, you will get the following error:
/path/to/script: Permission denied
By default, all new text documents do not have execute permissions. To add execute permissions to a script, open the Terminal and type the following command:
"chmod u+x /path/to/script"
If you do not want to type the script path, you can always type chmod u+x and drag the script file to the Terminal window, and the Terminal will fill in the path. Then hit return.
thank you for a great resource!
Email SuperDuper! Results
OK - this is probably not going to get a response but Google is not working out for me on this one.
When the final resume Parallels script is run, do you have a way to email the results to an admin?
Pass / Fail ?
Pass but with these errors?
Any thoughts would be appreciated.
And thank you for the script!