Friday, October 16, 2015

Empower your Users with Simple Xcode apps

At one point, I worked in a large, distributed environment. Sadly, I didn't have authority over any computer in our management system.  The only way I could take action was if the end user specifically authorized me.  And with 10,000 machines all over the city, that was not trivial to do.  

Actually, it turned out to be surprisingly closer to trivial that I expected.  If you are familiar with the defaults command, I was able to save a setting on a user's computer, to read in with an extension attribute in JAMF Casper and create a smart group.  But how to get the end users to run that Defaults command was the challenge.  

The command I needed was  defaults write /Library/Preferences/com.toddCo.manage.plist AllowUpdates -bool YES.

AllowUpdates means that I'm allowed to push out software updates, such as Office, Java, Flash, and more.  And the end user needed to submit that command on their computer to approve me updating their machines.  

I ended up writing a simple application in Xcode which ran that command for them.  I'll walk you through that process in the remainder of this guide.

Open Xcode and create a new project.  Select Other and choose Cocoa AppleScript.
Give your project a name and enter your Organization Identifier (a reverse domain name is best) and click Next.  Then save the project somewhere appropriate and get ready to do the fun part.

When building an application, it's often best (and most fun) to start with the GUI (Graphic User Interface).  So lets layout our application.  Click on MainMenu.xib on the left, then click the icon for The Window (See circled below) to make sure the main program window appears. 
To start adding elements to our window, click the third icon on the bottom right.  There, you can see buttons, progress bars, check boxes, labels, text fields and more.  Find a Multi-Line Label and put in some text such as "Checking this checkbox will allow the IT Department to update applications such as Java, Flash, or Firefox on your computer".  Then, of course, drag in a check box and set the text to 'I Agree'.

Now to make the 'I Agree' check box do something in code.  Select the check box in your window, then select the Binding Inspector.  That's the 7th icon along the top right section of the screen that looks like a spiral.  See the image below.  If necessary, use the disclosure triangle to expand the 'Value' area.  Check the box to Bind To and choose 'Application'.  And enter a variable name in the Model Key Path field.  I choose to use the variable name 'iAgreeBox'. 


Before we leave this screen, also drag in a Push Button and call it 'Save'.  We'll make that work later. 

Now it's time to write some code to make stuff happen.  Towards the top left of the screen, click on AppDelegate.applescript to bring up the code window.   If we want to get or edit any data in the GUI, we need to reference it with a property.  Since we want to be able to see what that check box is set to, lets create a property for it.  At the top of AppDelegate.applescript, you'll see a 'Property theWindow' line.  Below that, add the text 'property iAgreeBox : false'    The name iAgreeBox needs to match exactly the name you put in that Model Key Path on the previous step.  I often copy/paste just to avoid spelling errors.  Spelling errors don't count if you make the same mistake in both places.  Now we can use iAgreeBox to determine the state of that checkbox in our script. 

Lets add some code for the Save button.  Below the property lines, enter this text:
     on saveTime_(sender)
        do shell script "defaults write /Library/Preferences/com.toddCo.manage.plist AllowUpdates -bool " & iAgreeBox with administrator privileges

         display dialog "Setting Saved!" buttons "OK"


    end saveTime_

Note that there is an underscore after 'saveTime' and the word 'sender' in parens.  That is all required.  Why it's required will be discussed elsewhere.

Lets see what that means in parts.  The first line, on saveTime_(sender) means that this chunk of code should run when the program issues a call to run the task named saveTime.   We'll make that 'Save' button from the GUI do that later.  And at the end, end saveTime_, is the footer, or end, for the steps of the saveTime task.

The  do shell script line is the big one.   Since this is an AppleScript program, we tell Applescript to run some terminal/command line code.  The defaults write command is the one from the beginning of the article.  That's where the Yes or No is saved into that plist file.  With Administrator Privileges means that if needed, the program will prompt for an admin name and password.  Only someone with admin writes will be able to run this program. 

Now we need to link the save button from the GUI to run this chunk of code.  To do that, switch back to MainMenu.xib on the left to see the GUI.  Hold down the Control key on the keyboard and drag from your button to the icon for Delegate.  See the screen image below.  

Once you drag to delegate, a small dark window will appear with a list of those different tasks in it.  One should be called 'saveTime'.   Select it to link the button to that task.  Now when someone clicks the button, the steps in the 'saveTime' block of code will run! 

You now have a fully functional program! How do you know if it works?  Since we're writing some data to a plist, we can just look there and see what it says.

defaults read /Library/Preferences/com.toddco.manage.plist AllowUpdates

Now try running your new program and change the checkbox and click Save.  Each time you open the application, it does default to an 'off' checkbox instead of what is saved there.  We'll fix that next.

Find the section that has applicationWillFinishLaunching.  This is the chunk of code that runs when the program is opened.  Add this line in between so it runs when you start your program.

    on applicationWillFinishLaunching_(aNotification)
         set my iAgreeBox to (do shell script "defaults read /Library/Preferences/com.toddCo.manage.plist AllowUpdates")
    end applicationWillFinishLaunching_


Now when you open the program, the checkbox should match what it was set to last time it was closed.  

 
Next:
In the next post, we will read that setting into our JAMF JSS as an Extension Attribute and create a Smart Group to target those machines. 
http://tmhoule.blogspot.com/2016/05/xcode-applescript-part-ii.html
 

No comments:

Post a Comment