module Jamf::Client::JamfHelper::ClassMethods

class Methods

Public Instance Methods

jamf_helper(window_type = :hud, **opts) click to toggle source

A wrapper for the jamfHelper command, which can display a window on the client machine.

The first parameter must be a symbol defining what kind of window to display. The options are

  • :hud - creates an Apple “Heads Up Display” style window

  • :utility or :util - creates an Apple “Utility” style window

  • :fs or :full_screen or :fullscreen - creates a full screen window that restricts all user input WARNING: Remote access must be used to unlock machines in this mode

The remaining options Hash can contain any of the options listed. See below for descriptions.

The value returned is the Integer exitstatus/stdout (both are the same) of the jamfHelper command. The meanings of those integers are:

  • 0 - Button 1 was clicked

  • 1 - The Jamf Helper was unable to launch

  • 2 - Button 2 was clicked

  • 3 - Process was started as a launchd task

  • XX1 - Button 1 was clicked with a value of XX seconds selected in the drop-down

  • XX2 - Button 2 was clicked with a value of XX seconds selected in the drop-down

  • 239 - The exit button was clicked

  • 240 - The “ProductVersion” in sw_vers did not return 10.5.X, 10.6.X or 10.7.X

  • 243 - The window timed-out with no buttons on the screen

  • 250 - Bad “-windowType”

  • 254 - Cancel button was select with delay option present

  • 255 - No “-windowType”

If the :abandon_process option is given, the integer returned is the Process ID of the abondoned process running jamfHelper.

See also /Library/Application\ Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper -help

@note the -startlaunchd and -kill options are not available in this implementation, since

they don't work at the moment (casper 9.4).
-startlaunchd seems to be required to NOT use launchd, and when it's ommited, an error is generated
about the launchd plist permissions being incorrect.

@param window_type The type of window to display

@param opts the options for the window

@option opts :window_position [Symbol,nil] one of [ nil, :ul, :ll. :ur, :lr ]

Positions window in the upper right, upper left, lower right or lower left of the user's screen
If no input is given, the window defaults to the center of the screen

@option opts :title [String]

Sets the window's title to the specified string

@option opts :heading [String]

Sets the heading of the window to the specified string

@option opts :align_heading [Symbol] one of [:right, :left, :center, :justified, :natural]

Aligns the heading to the specified alignment

@option opts :description [String]

Sets the main contents of the window to the specified string

@option opts :align_description [Symbol] one of [:right, :left, :center, :justified, :natural]

Aligns the description to the specified alignment

@option opts :icon [String,Pathname]

Sets the windows image field to the image located at the specified path

@option opts :icon_size [Integer]

Changes the image frame to the specified pixel size

@option opts :full_screen_icon [any value]

Scales the "icon" to the full size of the window.
Note: Only available in full screen mode

@option opts :button1 [String]

Creates a button with the specified label

@option opts :button2 [String]

Creates a second button with the specified label

@option opts :default_button [Integer] either 1 or 2

Sets the default button of the window to the specified button. The Default Button will respond to "return"

@option opts :cancel_button [Integer] either 1 or 2

Sets the cancel button of the window to the specified button. The Cancel Button will respond to "escape"

@option opts :timeout [Integer]

Causes the window to timeout after the specified amount of seconds
Note: The timeout will cause the default button, button 1 or button 2 to be selected (in that order)

@option opts :show_delay_options [String,Array<Integer>] A String of comma-separated Integers, or an Array of Integers.

Enables the "Delay Options Mode". The window will display a dropdown with the values passed through the string

@option opts :countdown [any value]

Displays a string notifying the user when the window will time out

@option opts :align_countdown [Symbol] one of [:right, :left, :center, :justified, :natural]

Aligns the countdown to the specified alignment

@option opts :lock_hud [Boolean]

Removes the ability to exit the HUD by selecting the close button

@option opts :abandon_process [Boolean] Abandon the jamfHelper process so that your code can exit.

This is mostly used so that a policy can finish while a dialog is waiting
(possibly forever) for user response. When true, the returned value is the
process id of the abandoned jamfHelper process.

@option opts :output_file [String, Pathname] Save the output of jamfHelper

(the exit code) into this file. This is useful when using abandon_process.
The output file can be examined later to see what happened. If this option
is not provided, no output is saved.

@option opts :arg_string [String] The jamfHelper commandline args as a single

String, the way you'd specify them in a shell. This is appended to any
Ruby options provided when calling the method. So calling:
   Jamf::Client.jamf_helper :hud, title: 'This is a title', arg_string: '-heading "this is a heading"'
will run
   jamfHelper -windowType hud -title 'this is a title' -heading "this is a heading"
When using this, be careful not to specify the windowType, since it's generated
by the first, required, parameter of this method.

@return [Integer] the exit status of the jamfHelper command. See above.

    # File lib/jamf/client/jamf_helper.rb
186 def jamf_helper(window_type = :hud, **opts)
187   raise Jamf::UnmanagedError, 'The jamfHelper app is not installed properly on this computer.' unless JAMF_HELPER.executable?
188 
189   unless JAMF_HELPER_WINDOW_TYPES.include? window_type
190     raise Jamf::InvalidDataError, "The first parameter must be a window type, one of :#{JAMF_HELPER_WINDOW_TYPES.keys.join(', :')}."
191   end
192 
193   # start building the arg array
194 
195   args = ['-startlaunchd', '-windowType', JAMF_HELPER_WINDOW_TYPES[window_type]]
196 
197   opts.keys.each do |opt|
198     case opt
199     when :window_position
200       raise Jamf::InvalidDataError, ":window_position must be one of :#{JAMF_HELPER_WINDOW_POSITIONS.join(', :')}." unless \
201         JAMF_HELPER_WINDOW_POSITIONS.include? opts[opt].to_sym
202 
203       args << '-windowPosition'
204       args << opts[opt].to_s
205 
206     when :title
207       args << '-title'
208       args << opts[opt].to_s
209 
210     when :heading
211       args << '-heading'
212       args << opts[opt].to_s
213 
214     when :align_heading
215       raise Jamf::InvalidDataError, ":align_heading must be one of :#{JAMF_HELPER_ALIGNMENTS.join(', :')}." unless \
216         JAMF_HELPER_ALIGNMENTS.include? opts[opt].to_sym
217 
218       args << '-alignHeading'
219       args << opts[opt].to_s
220 
221     when :description
222       args << '-description'
223       args << opts[opt].to_s
224 
225     when :align_description
226       raise Jamf::InvalidDataError, ":align_description must be one of :#{JAMF_HELPER_ALIGNMENTS.join(', :')}." unless \
227         JAMF_HELPER_ALIGNMENTS.include? opts[opt].to_sym
228 
229       args << '-alignDescription'
230       args << opts[opt].to_s
231 
232     when :icon
233       args << '-icon'
234       args << opts[opt].to_s
235 
236     when :icon_size
237       args << '-iconSize'
238       args << opts[opt].to_s
239 
240     when :full_screen_icon
241       args << '-fullScreenIcon'
242 
243     when :button1
244       args << '-button1'
245       args << opts[opt].to_s
246 
247     when :button2
248       args << '-button2'
249       args << opts[opt].to_s
250 
251     when :default_button
252       raise Jamf::InvalidDataError, ":default_button must be one of #{JAMF_HELPER_BUTTONS.join(', ')}." unless \
253         JAMF_HELPER_BUTTONS.include? opts[opt]
254 
255       args << '-defaultButton'
256       args << opts[opt].to_s
257 
258     when :cancel_button
259       raise Jamf::InvalidDataError, ":cancel_button must be one of #{JAMF_HELPER_BUTTONS.join(', ')}." unless \
260         JAMF_HELPER_BUTTONS.include? opts[opt]
261 
262       args << '-cancelButton'
263       args << opts[opt].to_s
264 
265     when :timeout
266       args << '-timeout'
267       args << opts[opt].to_s
268 
269     when :show_delay_options
270       args << '-showDelayOptions'
271       args << JSS.to_s_and_a(opts[opt])[:arrayform].join(', ')
272 
273     when :countdown
274       args << '-countdown' if opts[opt]
275 
276     when :align_countdown
277       raise Jamf::InvalidDataError, ":align_countdown must be one of :#{JAMF_HELPER_ALIGNMENTS.join(', :')}." unless \
278         JAMF_HELPER_ALIGNMENTS.include? opts[opt].to_sym
279 
280       args << '-alignCountdown'
281       args << opts[opt].to_s
282 
283     when :lock_hud
284       args << '-lockHUD' if opts[opt]
285 
286     end # case opt
287   end # each do opt
288 
289   cmd = Shellwords.escape JAMF_HELPER.to_s
290   args.each { |arg| cmd << " #{Shellwords.escape arg}" }
291   cmd << " #{opts[:arg_string]}" if opts[:arg_string]
292   cmd << " > #{Shellwords.escape opts[:output_file]}" if opts[:output_file]
293 
294   if opts[:abandon_process]
295     pid = Process.fork
296     if pid.nil?
297       # In child
298       exec cmd
299     else
300       # In parent
301       Process.detach(pid)
302       pid
303     end
304   else
305     system cmd
306     $CHILD_STATUS.exitstatus
307   end
308 end