TweetFollow Us on Twitter

GUI-up your Script

Volume Number: 22 (2006)
Issue Number: 8
Column Tag: Mac in the Shell

GUI-up your Script

OK - Perhaps the GUI is nice every now and then...

by Edward Marczak

Introduction

While I can extol the virtues of life in the shell, I do realize that sometimes, just sometimes, a GUI is more appropriate. Why would I say such a thing? Because there will be scripts that you write primarily to be used by other people. The kind of people that don't keep a terminal window open 100% of the time. On one hand, you've found a great solution to their issue. On the other, you don't want the cure to be more painful than the disease. The wonderful thing about Apple's XCode development environment is that you can take practically any shell solution and turn it into a GUI-based one without too much effort. That's where we'll be heading this month.

What's New in AppleScript

Did I just say AppleScript? Yes, yes I did. The history of AppleScript is outside the scope of this column; it is very lengthy. It is now, however, a mature technology. Even more exciting is the inclusion of "AppleScript Studio" into OS X and XCode.

Now, you won't find an application, or even a submenu that launches anything called "AppleScript Studio." AppleScript Studio refers to the ability of XCode to take an AppleScript app, tie it into all of the other XCode technologies and compile it into a native Cocoa app. This makes creating a basic application mind-blowingly simple. We're going to create a small sample app to prove this.

Fire Up XCode

If you've never launched XCode, now's your chance to dig in. If you're an XCoder already, you may have missed (or ignored) some of the AppleScript options. More importantly, if you've never installed XCode, you'll need to for the rest of this article. While the XCode environment ships with each copy of the OS, the retail disc is a little dated at this point. Bring yourself to <http://developer.apple.com>, sign up for a free account, and download the latest version of XCode (2.3, as of this writing, weighing in at 915MB).

With XCode installed, it's time to launch it. You'll find it at /Developer/Applications:



Figure 1: XCode icon

You may not notice that it's up and running. In its minimalist way, there's no splash screen or other trumpeting of its arrival. Choose New Project from the File menu:



Figure 2: New Project

When presented with the choice of the kind of project, choose "AppleScript Application" and click "Next". Name your project - the example this month is "Backup", if you're following along - and where you want it saved. XCode will create directories for you if necessary. Once you give it the go ahead, you'll be staring at a fresh new project.



Figure 3: Default Project

Lot of stuff - stay cool. In the "Groups & Files" pane, you'll see a 'Scripts' folder. Since we're going to be writing an AppleScript that will front-end a shell script, as you can imagine, this is where the bulk of the action will take place for us. Of course, we need to begin at the beginning. Let's write the shell script.

The Heart of the Matter

The real work will be done by a shell script, so we need to have that in place. This will be a 'lite' version of a solution I really have put in place. However, there were enough things that were specific to the environment in question, that I don't want to reproduce here. Additionally, I won't be getting into any heavy error checking or correction. Nor will I make the claim that this is a perfect fit for any other particular situation. That said, I'll offer this basic script as our base:

#!/bin/bash
ditto -rsrc /Files /Volumes/Backup_Drive/Files

This one-liner uses the OS X native ditto command to copy all files from /Files to /Volumes/Backup_Drive/Files. I'll stick the '-rsrc' switch in there as it only became the default behavior as of 10.4. What if we want to run this on a Panther machine? Use your favorite text editor to create this script, and then save it. Call it "backup.sh". Mark it executable with chmod 770 and test it. You may need to modify the path names, or, for testing purposes, simply copy between two folders on your local drive.

Have it working? Great. Now, we can drag-and-drop this script right into our XCode project. Locate this script in the Finder, and drag it into the Scripts folder. You'll be asked how to reference this file. Ensure that the "Copy items into destination group's folder" is checked, and click add.



Figure 4: Copying a script into XCode

You should see your backup.sh script listed alongside the preloaded AppleScript file. Like so:



Figure 5: Your script has been added

If you've never used XCode before, please do this now: click on the build icon in the toolbar. This will help you understand how XCode lays out your project. Open up the folder where you saved this project. Inside, you'll find a folder named 'build'. Inside of that, you'll find one named 'Debug', and it will contain your Backup.app. See how easy that was? OK, not so fast, right? Although this app actually will run (go on, try it), it won't do anything of use. Right-click (control-click) on the app and select "Show Package Contents". Open the resulting 'Contents' folder, and the 'Resources' folder beneath that. You should see three objects: backup.sh, English.lproj and Scripts. Well, there's our 'backup.sh' file! Now we know where it lives and how to access it.

Get GUI

Back in XCode, toggle the disclosure triangle next to the 'Resources' group. Double-click on the 'MainMenu.nib' file. This will launch Interface Builder, and even more windows will now litter your screen. Click once on the window labeled 'Window'. Let's immediately name it something more relevant. Change the Window Title in the inspector pane, and title the window "Backup". Also, we need to give it an AppleScript name. Change the drop-down menu in the inspector to "AppleScript". Name the window "wMain". Now, look for a button in the 'Cocoa-Controls' pane. Drag it to the lower right-hand corner of our window. You'll see guidelines appear to help you position it. With the button still selected, let's make it say and do something appropriate. Back on the attributes screen, update the button title in the inspector pane. (Change the drop-down menu to get back to the attributes screen). Additionally, change the 'Key equiv.' to '\R' - type it in or use the drop down menu to select 'Return', and check the 'Selected' checkbox. Flip the inspector back to AppleScript, and give this button a name. How about "bBackup"?

Now to begin to tie it together: Making sure that you're still in the AppleScript portion of the inspector, place a check-mark in the 'Action' box, and select the 'Backup.applescript' in the list at the bottom of the Inspector. Save and quit. Not too terrible, right? Of course, now we have to make that AppleScript do something.

I am not, nor will I pretend to be an AppleScript guru. I can deal with the basics well enough, and they are easy to pick up. However, once you start doing this, and you get hooked on it, do yourself a favor and hit some of the many fine AppleScript resources available. This includes Ben Waldie's AppleScript column right here in MacTech. He's also written some excellent books, available through SpiderWorks (http://www.spiderworks.com). There's also <http://www.macscripter.net>, another web-based resource. However, to simply front-end a shell script - no matter how complex - you'll find all you need in this one column. Just do realize that you can do some very complex scripting with AppleScript, and in an all Mac environment is well-worth learning.

With that out of the way, let's continue. Back in XCode proper, double-click on the 'Backup.applescript' in the 'Scripts' group. You'll see that XCode give you some pre-populated comments for you to tailor to this project. But comments don't cause any action! Place these lines into the script:

on clicked theObject
   -- setup
   set myPath to POSIX path of (path to me) as string
   
   -- Do it!
   do shell script quoted form of myPath & "Contents/Resources/backup.sh"
end clicked

As you type this in, all text will be set in a purple mono-spaced font (by default, anyway - you may have changed this preference). Once you save, the parser comes alive to check the validity of the script. Valid strings and recognized keywords get color-coded and set in a different font. What did we just tell our application to do? Actions performed on the button will be sent here since we used Interface Builder to tie an action to this particular script. In this case, we're interested to know when someone clicks on the button.

The first line (set myPath...) sets the "myPath" variable to the path of the application. This lets the user place this app wherever they want on their file system, and we can deal with it at runtime. Next, we call our shell script. AppleScript gained the ability to call scripts with the "do shell script" command. Currently, we know where our app lives and have stored that in a variable, myPath. Earlier, we verified where our script lives inside our application bundle. Now we know where to go relative to the app. We can launch our script from the "Contents/Resources" folder below "myPath".

Is it really this simple? Let's find out. First: go load up your /Files directory with some files and folders. Then, back in XCode, click on the "Build and Go" icon in the toolbar. A build window will appear and give you build status. Once complete, you'll see the window that we created earlier in Interface Builder with its one lonely button. As you can see, it is the default button, and has the Aqua default pulsing glow. Go ahead and click the "Backup" button. Our app will run our shell script buried in the application bundle. Depending on how much stuff you loaded into the /Files directory, this may take a minute. Do notice, though, that while the underlying script is running, the button stops pulsing. Once the script finishes up, the button will pulse again. Press Apple-Q or select "Quit NewApplication" from the "Backup" menu.

The answer, then, is "yes! It is that simple." Of course, not only did we not write a very friendly application, there are some other things we need to take into consideration. However, if all you ever want is a one-button method of running a shell-script, now you have the framework to do so. This isn't anything I'd hand a client, of course.

Version 1.1

Before I continue to spill letters onto the page, there's a much more important source before we continue. "do shell script" is addressed in detail in Apple's Technote TN2065. This is a must read. URL in the references at the end of this article.

Moving along, we need to create better feedback for the client when they run our application. Double-click on the MainMenu.nib file once again (in XCode). You should see our application's window displayed by default. If not, double-click the "Window" icon in the "MainMenu.nib (English)" window. Drag a progress indicator from the Cocoa-Controls window onto our main window - place it just above the backup button, and stretch it horizontally to the width of the window. Then, with it still selected, change the drop-down menu in the inspector to "AppleScript". Give this control a name...like, "pMainProgress". (I used to code in VB and RB and, yes, Hungarian notation is driven pretty deep into my brain). We need this name so we can refer to the control in code. Save and quit Interface Builder.

Once again, we're in the position of writing code that will actually make that progress bar do something. Fortunately, AppleScript makes it pretty trivial. You'll see why we need to name objects so AppleScript can reference them. Here's one of the lines we'll need to add:

set uses threaded animation of progress indicator "pMainProgress" of window "wMain" to true

(While this may wrap in print, you should type it as all one single line with no line break).

Since we can have multiple windows, each with multiple progress bars and other objects, we need to be specific. We need to set the "uses threaded animation" property of the progress bar. Ah, which progress bar? The one we called "pMainProgress". Well, on which window? "wMain"! AppleScript's goal of being English-like works in its favor most of the time. Other times, you can get some pretty bizarre sentences. We'll place all of our code right in the on clicked section, because we only want the progress bar to animate while the backup is running. The fully updated code follows (and look for the start and stop of the progress bar):

on clicked theObject
   -- setup
   set myPath to POSIX path of (path to me) as string
   -- Start progress bar
   set uses threaded animation of progress indicator "pMainProgress" of window "wMain" to true
   tell progress indicator "pMainProgress" of window "wMain" to start
   
   -- Do it!
   do shell script quoted form of myPath & "Contents/Resources/backup.sh"
   -- Stop progress bar
   tell progress indicator "pMainProgress" of window "wMain" to stop
   set uses threaded animation of progress indicator "pMainProgress" of window "wMain" to false
   
end clicked

(Again, these lines wrap in print, but they should not be artificially broken when you type them).

Our progress bar commands "wrap" the do shell script. Time for the test: Apple-S (save) and Apple-R (build and Run). Make sure that your source folder is populated, and click on "Backup". Progress bar moves while it's working, and stops once it's done. Fantastic.

What if there's a problem? We really want to trap for errors. Change the "Do it" section to read thusly:

   -- Do it!
   try
      do shell script quoted form of myPath & "Contents/Resources/backup.sh"
   on error number 255
      display dialog "Sorry, an error occurred.  I can't make the copy."
   end try

As you can surmise, this allows us to try a command that may fail, without bombing out - we get to control the process. Here, I show a basic try block. We try to run the script. If it runs properly, returning a zero, all's good and we continue on. If there's a problem, we show a dialog box that explains that there has been a problem. Try blocks can certainly get much more elaborate.

What might be a reason that we'd have an error in our script? Perhaps we're asking it to backup areas of the file system that we don't have access to? In that case, you can have your script run with administrator privileges. You do this with the....wait for it..."with administrator privileges" parameter. Alter the do shell script line to read like this:

do shell script quoted form of myPath & "Contents/Resources/backup.sh" 
with administrator privileges

By itself, with no additional parameters, this will present the user with the familiar dialog box asking for an admin password when the app is run.



Figure 6: Our app asking for authentication

You can preload your script with a username and password. However, I DO NOT RECOMMEND THIS. Clear? To tie this back into last month's column, it would be trivial for someone to run strings across the resulting binary and gather the admin level id and password you provided. If you're daring enough to risk it, find the instructions in the Apple 'do shell script' technote referenced earlier (but seriously: don't).

One little thing that TN2065 does not mention: there is a default timeout on all AppleScript commands, including do shell script, of two minutes. If you believe your script may run for longer - for whatever reason - use a with timeout block:

with timeout of 300 do
   do shell script ...
end timeout

Unfortunately, there is no setting that will just let it do its thing indefinitely (OK, perhaps not a terrible thing). If a command does timeout, a timeout error is thrown (-1712). So do make sure you use a value large enough to let your script run to completion. Even if that's "99999".

One for the road

We'll add one more object to our window: A text field with the current status. Double-click on MainMenu.nib, and once Interface Builder is running, click on the Cocoa-Text icon in the object palette:



Figure 7: Cocoa-Text icon

Drag two "System Font Text" fields to the main window. Place one in the upper left (use the guides), and the second right next to it. Double-click on the first, and type "Status:" into the text field. Double-click on the second and type "Idle" into its text field. With the second still selected, Apple-8 your way to the AppleScript attributes, and name this field "efStatus". We should also clean this window up a bit while we're here, no? Drag the progress bar straight up until the guides appear under the text fields we just created. Do the same for the single button, and stop when the guides appear under the progress bar. Size the window itself appropriately, again using the guides. Save and quit Interface Builder.

Again, we need to make that text field perform an appropriate action. Here's how we can do so. In the "setup" section, add this line:

set the contents of text field "efStatus" of window "wMain" to "Copying files..."
...and just after the try block, add this line:
set the contents of text field "efStatus" of window "wMain" to "Backup Complete."

Save (Apple-S), build and run (Apple-R) the project with the changes. Nice.

Finally

Last thing I'll mention: If you really want to make this professional, you'll probably want to fix up the app menus to show the app's real name (not "New Application") and add a custom icon. Let's tackle the icon first. For this, you'll need Icon Composer. You'll find that with the developer tools in /Developer/Applications/Utilities. You'll need to have your artwork complete before using this utility - Icon Composer is not a drawing program. It will, though, read in Photoshop files directly. Drag your artwork to the 128x128 pane, scale it if needed. From there, drag the 128x128 to the 48x48, scale it and let the program extract the mask. Rinse and repeat for the last two sizes. Apple-S to save. Make sure "Save into bundles" is checked, and save the file. You can then take this file and drag it into the "Resources" section of the XCode project. Choose the "Project" menu and click on the "Properties" tab. Type in the name of your icon file (I left mine "icons.icns" in the example below), and as soon as you press return, you'll see a thumbnail representation of your application icon.



Figure 8: Project properties and setting an application icon.

To update the menus, we need to double-click on the MainMenu.nib once again and launch Interface Builder. You should notice a small menubar floating just underneath the window we've been editing. If not, simply double-click on the "Main Menu" icon in the main window of Interface Builder. Editing the menu is as simple as double-clicking on each item you want to rename. You can alternatively accomplish this with the inspector pane, but this method will update the inspector as well.



Figure 9: Menu editing in action.

Quit and save. Let's build this thing into a 'real' app. In XCode, choose the "Project" menu, and then change the "Active Build Configuration" to "Release". Save and build (Apple-B) the app. The last line of the Build Results window will tell you where to pick up your Universal Binary application! Go get it and double-click to run. Exiting, huh? You can now distribute this application, and it contains everything that it needs to run - your shell script (the point of this entire exercise, remember) is bundled inside.



Figure 10: Our final application, running as a universal binary.

Keep it simple

The goal of this article was to introduce the oft-overlooked capability to easily create a GUI for a shell script using tools that Apple provides for free. While many are aware of this capability, I find it "oft-overlooked" by shell scripters, anyway. As mentioned earlier in the article, this is certainly not an exhaustive look at everything you can do, nor does it even begin to approach "best practices" (such as exhaustive error checking in a try-block, creating a proper info.plist, or even dealing with script output). If this introduction intrigues you, there are many, many places to increase your knowledge and further this path.

While I realize that this will run very much after the fact, this publication will appear during WWDC, which will be less lively without Michael Bartosh. Friend, fellow tech, fellow author and more, he will be sorely missed. Let's all remember to raise a glass - even a virtual one - in remembrance. Speaking of WWDC, I'm present to raise a real glass with anyone interested. See you at Dave's.

Media of the month: I've been too tied up in Citrix tech docs and Microsoft Group Policy to recommend anything appropriate here from a technical perspective. Actually...that may provide the perfect segue: OS X provides Windows interoperability by using the open source Samba project. By itself, Samba is an ambitious and deep project. Cleverly, Apple provides O'Reilly's entire "Using Samba, Second Edition" preloaded onto your Mac! Launch Safari and point your browser to <file:///usr/share/swat/using_samba/toc.html>. This tends to be another 'oft-overlooked' resource.

I was fortunate to meet many MacTech readers at MacWorld in January, and I hope to meet more at WWDC 2006. If you're unable to attend, look for our reports from the show. In any case, I'll see you in print next month!

References

Just about everything at http://developer.apple.com

Especially Tech Note 2065: http://developer.apple.com/technotes/tn2002/tn2065.html

The Tao of AppleScript, Derrick Schneider (yes, this came out in 1994 and shipped with a floppy of examples. AppleScript basics just haven't changed that much).

Resources

Mac Scripter: http://macscripter.net/


Ed Marczak owns and operates Radiotope, a technology consulting company. Radiotope helps separate technology issues from policy issues, cool-tech from needed-tech. Guide your decision at http://www.radiotope.com

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Notability 4.2.2 - Note-taking and annot...
Notability is a powerful note-taker to annotate documents, sketch ideas, record lectures, take notes and more. It combines, typing, handwriting, audio recording, and photos so you can create notes... Read more
Adobe Acrobat Reader 20.006.20034 - View...
Adobe Acrobat Reader allows users to view PDF documents. You may not know what a PDF file is, but you've probably come across one at some point. PDF files are used by companies and even the IRS to... Read more
Adobe Acrobat DC 20.006.20034 - Powerful...
Acrobat DC is available only as a part of Adobe Creative Cloud, and can only be installed and/or updated through Adobe's Creative Cloud app. Adobe Acrobat DC with Adobe Document Cloud services is... Read more
Day One 4.8 - Maintain a daily journal.
Day One is an easy, great-looking way to use a journal / diary / text-logging application. Day One is well designed and extremely focused to encourage you to write more through quick Menu Bar entry,... Read more
OmniPlan 3.14 - Professional-grade proje...
With OmniPlan, you can create logical, manageable project plans with Gantt charts, schedules, summaries, milestones, and critical paths. Break down the tasks needed to make your project a success,... Read more
calibre 4.11.0 - Complete e-book library...
Calibre is a complete e-book library manager. Organize your collection, convert your books to multiple formats, and sync with all of your devices. Let Calibre be your multi-tasking digital librarian... Read more
Tinderbox 8.5.0 - Store and organize you...
Tinderbox is a personal content management assistant. It stores your notes, ideas, and plans. It can help you organize and understand them. And Tinderbox helps you share ideas through Web journals... Read more
OmniPlan Pro 3.14 - Professional-grade p...
With OmniPlan Pro, you can create logical, manageable project plans with Gantt charts, schedules, summaries, milestones, and critical paths. Break down the tasks needed to make your project a success... Read more
Amazon Chime 4.30.7368 - Communications...
Amazon Chime is a communications service that transforms online meetings with a secure, easy-to-use application that you can trust. Amazon Chime works seamlessly across your devices so that you can... Read more
Adobe Premiere Pro CC 2020 14.0.2 - Digi...
Premiere Pro CC 2020 is available as part of Adobe Creative Cloud for as little as $52.99/month. The price on display is a price for annual by-monthly plan for Adobe Premiere Pro only Adobe Premiere... Read more

Latest Forum Discussions

See All

Marvel Strike Force introduces new brawl...
FoxNext's squad-based RPG Marvel Strike Force is set to receive some fresh characters from the X-Men and Iron Man series. They'll arrive as part of the game's latest update, which follows a sizable spending boycott on the title due to complaints... | Read more »
Speed Dating for Ghosts is a narrative a...
Speed Dating for Ghosts originally released on Steam back 2018, since then it has received honourable mentions for narrative during the Independent Games Festival. Now it's made its way over to iOS devices where it's available as a premium title... | Read more »
Fast-paced multiplayer title Tennis Star...
Tennis Stars: Ultimate Clash is the latest free-to-play tennis title to hit iOS and Android. It's said to be a fairly casual experience, offering easy-to-learn controls and fast-paced, mobile-friendly matches. [Read more] | Read more »
Super Mecha Champions' latest updat...
Super Mecha Champions' latest update sees the addition of a brand new character called R.E.D. Alongside that, there's news about the current season and a series of Emojis that have been added to the game. [Read more] | Read more »
Isle Escape: The House is an upcoming pu...
Isle Escape: The House is an upcoming puzzle game from Simeon Angelov that's intended to serve as an introduction to a saga they're planning on releasing in an episodic fashion. The first chapter is set to release for both iOS and Android on 29th... | Read more »
Company of Heroes, the classic RTS, is n...
Feral Interactive has finally released their highly anticipated iOS version of the strategy classic Company of Heroes. It's available now for iPad as a premium title and has had various tweaks to ensure that it's optimised for touch controls. [... | Read more »
Mario Kart Tour's Vancouver Tour ha...
With Mario Kart Tour's Valentine's Tour now at an end (suspiciously before Valentine's Day has even arrived), it's now time to move on to the all-new and exciting Vancouver Tour. This time around, the featured drivers are Hiker Wario and Aurora... | Read more »
A new PictoQuest update makes it a much...
PictoQuest is a charming little puzzle game, but it left us a little disappointed. The game just didn’t seem to use screen space effectively, to the point that using the touch controls (as opposed to the default virtual d-pad) could lead to errant... | Read more »
Alley is an atmospheric adventure game a...
Alley is an atmospheric adventure game that sees you playing as a young girl trapped in an inescapable nightmare. Surrounded by her worst fears, every step forward for her is a huge challenge that you'll help guide her through using some simple... | Read more »
Fight monsters and collect heroes in Cry...
From Final Fantasy to Chaos Rings, Japanese roleplaying games have found a large and loyal fanbase on mobile devices. If you’re seeking a more under-the-radar JRPG to escape into, Lionsfilm’s Cryptract could be the one. The game has been around... | Read more »

Price Scanner via MacPrices.net

$749 MacBook Airs continue to be available on...
Amazon has the 2017 13″ 1.8GHz/128GB MacBook Air on sale today for only $749 shipped. That’s $250 off Apple’s original MSRP for this model and the cheapest new MacBook available from any Apple... Read more
HomePods on sale for $204 at Other World Comp...
Other World Computing has discounted, new, Apple HomePods on sale for up to $95 off Apple’s MSRP: – HomePod Space Gray: $207.99 $92 off MSRP – HomePod White: $204.99 $95 off MSRP These are the same... Read more
Get a Certified Refurbished iMac at Apple for...
Apple has Certified Refurbished 2019 21″ & 27″ iMacs available starting at $929 and up to $350 off the cost of new models. Apple’s one-year warranty is standard, shipping is free, and each iMac... Read more
A Look Back At The Top 5 Most Read Stories Of...
FEATURE: 02.21.20 The best of the best are now history and we’re not talking about Super Bowl LIV from earlier this month but rather, coverage from the past year (its second and first full one at... Read more
Apple offers wide range of discounted custom...
Save up to $610 on a custom-configured 21″ or 27″ iMac with these Certified Refurbished models available at Apple. Each iMac features a new outer case, free shipping, and includes Apple’s standard 1-... Read more
Find the best prices and sales on Macs, iPads...
Our Apple award-winning price trackers are the best place to look for the best New Year’s deals and lowest prices on Apple gear. Scan our price trackers for the latest information on sales, bundles,... Read more
Apple’s 27″ 8-Core iMac Pro on sale today for...
B&H Photo has the base 8-Core 3.2GHz 32GB/1TB iMac Pro on sale today for $4599 — $400 off Apple’s MSRP. Overnight shipping is free to many addresses in the US: – 8-Core 3.2GHz 32GB/1TB iMac Pro... Read more
In stock! Apple’s new Mac Pro for $5995 with...
Apple reseller DataVision has the new 2019 Apple Mac Pro in stock today for $5995 ($5 off MSRP) including free shipping. DataVision charges sales tax for NY, NJ, PA, and CA residents only. If you don... Read more
Apple offers 2019 13″ MacBook Pros for up to...
Apple has a full line of Certified Refurbished 2019 13″ 2.4GHz 4-Core Touch Bar MacBook Pros available starting at $1529 and up to $300 off MSRP. Apple’s one-year warranty is included, shipping is... Read more
Save up to $200 on a 13″ MacBook Air at Apple...
Apple has a full line of Certified Refurbished 2019 13″ MacBook Airs available starting at only $929 and up to $200 off the cost of new Airs. Each MacBook features a new outer case, comes with a... Read more

Jobs Board

Best Buy *Apple* Computing Master - Best Bu...
**745058BR** **Job Title:** Best Buy Apple Computing Master **Job Category:** Store Associates **Store NUmber or Department:** 001080-Lake Charles-Store **Job Read more
Sales Supervisor - *Apple* Blossom Mall - J...
Sales Supervisor - Apple Blossom Mall Location:Winchester, VA, United States- Apple Blossom Mall 1850 Apple Blossom Dr Job ID:1083621Store Hourly Positions Read more
Geek Squad Advanced Repair *Apple* Professi...
**763700BR** **Job Title:** Geek Squad Advanced Repair Apple Professional **Job Category:** Store Associates **Store NUmber or Department:** 000660-Natomas-Store Read more
Medical Assistant - *Apple* Valley Clinic -...
…professional, quality care to patients in the ambulatory setting at the M Health Fairview Apple Valley Clinic, located in Apple Valley, MN. Join the **M Health Read more
*Apple* Mobility Sales Professional - Best B...
**763669BR** **Job Title:** Apple Mobility Sales Professional **Job Category:** Store Associates **Store NUmber or Department:** 000851-Santana Row-Store **Job Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.