Trigger policy when login window is up?

rseide
Contributor

Is there a way to have a policy triggered when a computer is at the login screen?

This is not to be confused by the login/logout trigger.

Basically I would like to have a policy check to see if the computer is at the Login screen and if so, to run a policy.

In Apple Remote Desktop, there is a column for "Current Application". If the Mac is at the login screen, it will be displayed as "Login Window" under that column.

Is there any way to create a policy do be triggered this way?

Thanks in advance.

16 REPLIES 16

mm2270
Legendary Contributor III

Not exactly, but you can of course have a policy that uses the normal every 15 trigger and runs a script as a first step to see who the owner of console is. If its root, then you're at the login screen and it can activate a second policy, or perhaps just move no to the rest of the policy instead of exiting.

Other than that, you can have a LaunchDaemon do this with a set interval time so it can actually run more frequently than the every 15 or every 5 cycle or whatever yours is set to.

That said, might I ask what the use case is here? Why not just have a logout policy run instead if you need it to run while someone isn't logged in? Maybe if you explain the end goal there may be another way to approach this.

dpertschi
Valued Contributor

See Scott's script in this post. Worked for me.

https://jamfnation.jamfsoftware.com/discussion.html?id=5597

Create a custom trigger for your policy and call it from there in the else

Matt
Valued Contributor

Looks like it specifically is looking for a Root user. What if a Root user is logged in?

How does ARD report "Current Application" status? I see LoginWindow a lot, must be a way to extract that.

mm2270
Legendary Contributor III

You could also test to see if a process like the Dock or Finder is in the process list, as just one example. If the actual account "root" is logged in, Finder and Dock would be active processes. If at the login window they wouldn't be.

#!/bin/sh

currUser=$( ls -l /dev/console | awk '{print $3}' )

if [[ "$currUser" == "root" ]] && [[ $( ps axc | grep [F]inder ) == "" ]]; then
     ## Do something, like kick off a policy
else
     exit 0
fi

Matt
Valued Contributor

mm2270, that is similar to how I am doing it right now. If the Finder isn't running it must be off or at LoginWindow. Works but I would love to know how ARD does it :D

justinworkman
Contributor

Towards the end there's an applescript dictionary break down.

http://images.apple.com/ca/fr/remotedesktop/pdf/ARD3_AdminGuide.pdf

justinworkman
Contributor

There might be some promise in this as far as determining the foreground application.
http://alvinalexander.com/mac-os-x/applescript-unix-mac-osx-foreground-application-result

rseide
Contributor

Sorry for my late response. I really appreciate everyone's responses. I have a better insight on how I could accomplish this.

To answer the question about what I am trying to do: I would like to have patching done if the user is logged out, not WHEN the user logs out. Sometimes the software updates take a long time if there are a lot, and the user will only see a blank grey screen when logging out. We don't want the user to interrupt the updates while they're in progress. This has happened in the past where the user gets impatient while they're waiting for the login window to come up after they log out. We've suppressed the Casper notifications (a request from management) so they don't know what's going on even though we send out email notifications to the staff that patching will be done.

mm2270
Legendary Contributor III

So wait, let me understand the 'Management doesn't want notifications from Casper' Does that include the jamfHelper message that you can have come up during policy checks/runs when logging out? If so, it sounds like management is their own worst enemy, or at least yours. If they don't want Casper giving any indication as to what's happening, that's why people are getting impatient and force shutting down their Macs during logout. Seems silly to me.

If you can convince them that it would be acceptable to have an indication of policies running/installs happening at logout. you can take advantage of that function.
If they or you don't like the generic "Checking for policies..." message that Casper displays, I've worked up another process using cocoaDialog that works nicely at logout to really give feedback on installation.

rseide
Contributor

without giving away too much information about my job here, let's just say i work for the gov't, so hopefully that will give you some insight as to their seemingly unreasonable desire to suppress the Casper notifications. :-P

that being said, i am now very intrigued if there is a way to customize the notifications as you seem to have done. it would be great to have a real-time notification similar to Windows when it's applying policy updates to the PC. Our Windows team has a GPO feature enable to display the status of the policy being applied at the login window. I think it's called "Display highly detailed status messages".

please tell me how you have your notifications set up. :D

thank you!

stevewood
Honored Contributor II
Honored Contributor II

I utilize a few different methods for notifications, using the jamfHelper app and cocoaDialog. It just depends on when the policy is running and what my intentions are.

I've recently started using a method that Mike (@mm2270) posted in this link:

https://jamfnation.jamfsoftware.com/featureRequest.html?id=1148

I gather any updates I need to push (namely Flash, Acrobat, Silverlight or other small updates) into a hidden folder structure (in /private/var/) and then utilize his progress bar script, along with a jamfHelper dialog, to alert users that I am installing updates. I typically do this during login. After packaging up the different installers, I upload that to Casper, then set the policy with a before script and an after script. The Before script calls a script to enable jamfHelper:

#!/bin/bash
# JamfHelper Screen Lock
# Customized by yours truly... ABenedict :)
# Varibles
lastreboot=`uptime | awk '{print "Your last reboot was: " $3 " " $4  }' | sed -e 's/.$//g'`
heading="$4"      # This shows up above the image in a bigger bolder font than the description field
image="$5"            # Options are as follows [ maintenance | new | update | hello ] each give you a diffrerent image to give the user better feedback of what is happening on their system
description="$lastreboot ago. $6" # This shows up below the image in a smaller lighter font than the heading field
iconpath="$7"

# Default description if none is passed through the variable
if [ "$4" == "" ]; then
    heading="Installing Updates"
fi

if [ "$5" == "" ]; then
    image="update"
fi

if [ "$6" == "" ]; then
    description="$lastreboot ago. Please do not close your laptop or unplug anything until this screen disappears. Feel free to call the help desk if this screen does not go away after 30 minutes."
fi

if [ "$7" == "" ]; then
    iconpath="/private/var/inte/helperimages/"
fi

# Case statement to assign specific graphic.
case $image in
            maintenance )
                icon="maint.png"
                ;;
            new )
                icon="new.png"
                ;;
            update )
                icon="updt.png"
                ;;
            hello ) #just for kicks and giggles ;)
                icon="hello.png"
                ;;  
esac


# Script contents
#/Library/Application Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper -windowType fs -icon "$iconpath$icon" -heading "$heading" -description "$description" &
/Library/Application Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper -windowType hud -lockHUD -icon "$iconpath$icon" -heading "$heading" -description "$description" &

#Debugging Code
#echo "Heading = $4"
#echo "Description = $6"
#echo "Image = $5"
#echo "Icon Path = $iconpath"
#echo "Icon Path + Icon = $iconpath$icon"


exit 0

This calls jamfHelper in a HUD screen so that the user can see the next script run, which is the After script:

#!/bin/sh

## Progress bar script thanks to Mike (mm270) on the JAMFNation list:  https://jamfnation.jamfsoftware.com/featureRequest.html?id=1148


## Path to cocoaDialog (3.0.0 beta 7) Customize to your environment
cdPath="/private/var/inte/bin/cocoaDialog.app/Contents/MacOS/cocoaDialog"

## Define path to packages & done folder for use in initial check and for installations. Customize to your environment
PathtoPKG="/private/var/inte/installs/"
DoneF="$PathtoPKG/done/"

## Determine OS version
OSvers=$( sw_vers -productVersion )

## (Optional) Set appropriate installer flag based on OS version. Handles packages that may have an old cert
if [[ $OSvers =~ "10.6" ]]; then
    allowFlag="-allow"
elif [[ $OSvers =~ "10.7" ]] || [[ $OSVERS =~ "10.8" ]]; then
    allowFlag="-allowUntrusted"
fi

## Checks for existence of 'done' folder
if [[ ! -e "$DoneF" ]]; then
    echo "'done' directory not found. Creating it."
    mkdir "$DoneF"
fi

## Remove any old pkgs that may be left behind in 'done' folder
if [[ $( ls "$DoneF" ) != "" ]]; then
    echo "Located pkgs in 'done' directory. Deleting them."
    rm -rf "$DoneF"*
fi


## Get a count of waiting package installs
pkgCount=$( echo $( find "$PathtoPKG" -maxdepth 1 -name *.mpkg -or -name *.pkg | wc -l ) )
echo "$pkgCount package(s) found in packages directory"

## Set starting package count
pkgNo=1


## Create the name pipe input for the progressbar & set brief pause
rm -f /tmp/hpipe
mkfifo /tmp/hpipe
#sleep 0.2

## Display progress bar with initial text settings
echo "Displaying progress bar window."
"$cdPath" progressbar --title "Installing Software" --text "Preparing to install software..." 
--posX "right" --posY "top" --float --icon installer < /tmp/hpipe &

## Change the icon above to '--icon-file /path/to/icon.icns' (or .png .tif .jpg etc.) if desired

## Send progress through the named pipe
exec 3<> /tmp/hpipe

## Now, loop through each pkg in the packages folder and install it
find "$PathtoPKG" -maxdepth 1 -name *.mpkg -or -name *.pkg | while read file; do
    ## Get just the name of the package
    shortPKG=$( echo "${file%.*}" | awk -F"/" '{ print $NF }' )
    echo "Beginning installation of $shortPKG."
    ## Perform the installation on the package
   /usr/sbin/installer -pkg "$file" $allowFlag -target / -verboseR 2>&1 | while read line; do
        ## Get updated percentage from current installation and send to progressbar
        thePct=$( echo $line | awk -F"%" '/%/{ print $2 }' | cut -d. -f1 | sed '/^$/d' )
        echo "$thePct Installing $pkgNo of $pkgCount: "$shortPKG" - ($thePct %)" >&3
        if [[ $( echo "$line" | grep "successfully installed." ) ]]; then
            echo "$shortPKG successfully installed. Moving to done folder."
            sleep 0.5
            mv "$file" "$DoneF"
        fi
    done
    ## Increment the package number by 1
    let pkgNo=$pkgNo+1
done

## All installations done. Wait 1/2 second before shutting off progressbar
sleep 0.5

# Turn off progress bar by closing file descriptor 3 and removing the named pipe
echo "Closing progress bar."
exec 3>&-
rm -f /tmp/hpipe

## (Optional) Delete contents of the 'done' folder as a cleanup step
echo "Cleaning up contents of 'done' directory"
rm -rf "$DoneF"*

exit 0

That after script simply cycles through the hidden folder where the installers are to provide a progress bar using cocoaDialog.

The other method I may use is to utilize just the jamfHelper script above to lock the screen at logout while installing a bigger package. I tend to send out emails before hand if I am doing this method so that my users know the logout may take an extended period of time. I had the same problem you have with users closing their laptops or forcing the power off on their machines. I haven't had that problem since implementing the jamfHelper method over 2 years ago.

The third method I use to notify users is again with cocoaDialog using its bubble method. I use this for nagging users to reboot their machines. I have a script that runs to check the uptime of a machine. If the machine has been up for 5 days, the end user gets nagged only with a cocoaDialog window. If up more than 10 days, they get the cocoaDialog and an email.

#!/bin/sh

# Name: uptoolong.sh
# Date:  3 March 2010 (revised 17 March 2010)
# Author: Steve Wood (swood@integer.com)
# Purpose: this script will check how long a machine has been up and display a notification
# using Growl and Growl Notify.
# updated:  22 March 2010 - moved email address grab inside of if then loop
#
# updated:  20 March 2013 - removed Growl bits and added cocoaDialog instead

# set some variables and grab the time
days=`uptime | awk '{ print $4 }' | sed 's/,//g'`
num=`uptime | awk '{ print $3 }'`

# path to cocoaDialog
CD="/private/var/inte/bin/cocoaDialog.app/Contents/MacOS/cocoaDialog"
cdTitle="Machine Needs A Restart"
cdIcon="/private/var/inte/icons/ToolUtilities.icns"

# we want the computer name
computername=$2

# set the nasty message we are going to send
message1="Your computer has now been up for $num days.  It is important for you to restart"
message2="your machine regularly to help it run efficiently and to apply any updates or changes"
message3="that have been pushed in the background.  Please restart your machine ASAP.  Thank you."
echo $days
echo $num

# now check how long they've been awake
if [ $days = "days" ];

then
    if [ $num -gt 5 ];
        # we have a narcaleptic Machine
        then
            # this is serious
            if [ $num -gt 9 ];

                then

                    # grab the current user and use that to query OD for the email address
                    CurrentUser=`ls -l /dev/console | awk '{ print $3 }'`

                    #disabling email for right now.
                    #email=`dscl /LDAPv3/master.integerdallas.com -read /Users/$CurrentUser | grep EMailAddress | awk '{ print $2 }'`

                    # old way of using a dummy package
                    #touch /Library/Application Support/JAMF/Receipts/UpTooLong.pkg

                    # new method of an extension attribute


                    cdText="Your computer has not been restarted in more than 10 days.  Please restart ASAP.  Thank you."
                    #/usr/sbin/jamf displayMessage -message "Your computer has now been up for $num days.  Please restart ASAP.  Thank you"

                    $CD bubble --title "$cdTitle" --no-timeout --text "$cdText" --icon-file $cdIcon

                    # disabling mail for right now
                    echo -e "$message1
$message2
$message3" | mail -s "Machine Up Too Long" $email
                    echo "<result>$num $days</result>"
                else

                    # old way of using a dummy package
                    #touch /Library/Application Support/JAMF/Receipts/UpTooLong.pkg

                    # new method of an extension attribute

                    #/usr/local/bin/growlnotify -a "Finder" -t "Restart Required" -m "Your computer has been up for $num days.  Please restart as soon as possible." -s
                    cdText="Your computer has not been restarted in $num days.  Please restart ASAP.  Thank you."
                    $CD bubble --title "$cdTitle" --no-timeout --text "$cdText" --icon-file $cdIcon
                    #echo "<result>$num $days</result>"

            fi  

    fi
fi

#now run a recon to make sure we add to the smart groups and clear if need been
#/usr/sbin/jamf recon

exit 0

Hope that helps you out. You really should try to get your management to ease up on the no notification rule. It can save you a lot of headaches.

mm2270
Legendary Contributor III

Well, in truth, I don't have anything actually set up to do what I've described, mostly because we rarely if ever use login or logout policies. Political thing mostly, not to mention the fact that most of our user base seems to avoid logging out or rebooting, as if they'll get cooties or something. (you wouldn't believe some of the griping and moaning when we tell some users they need to logout or reboot)

But, as an experiment, in case we ever did decide to start using logout policies, I worked up a script that can show more detailed information as a policy or policies run utilizing cocoaDialog. Its not a "fill in as it goes" progress bar, but the barber pole"something is happening, please stand by" variety. Although I've tested this with some simple installs and it works really nicely, I'll admit that I've not tested it with really long installs, nor with multiple policies being executed at logout. The way the script works is, you need to have one policy call another using either a policy ID or a manual trigger. Either works fine, but I'm not sure how well it would work if you wanted several policies all to run at logout.

Anyway, here is the script. A couple of notes on it:
1) You of course need to have cocoaDialog installed (preferably the latest beta version which you can find here: http://mstratman.github.io/cocoadialog/) and in my case we have it placed in /Library/Application Support/JAMF/bin/ Same place as jamfHelper.app. It can be run from anywhere though as long as you change that part of the script.

2) You only need one parameter ($4) set up for the script, which is either a policy ID number or a manual trigger. The script can handle either one intelligently. Everything else gets pulled from the policy running itself and the /var/log/jamf.log

3) You can customize the icon that shows up in the progress bar by replacing the SSIcon variable with the path to another icon file or image.

4) You can also change the --width parameter to something bigger/smaller, but I found the 450 pixel size to be about right for most policies. Keep in mind that longer text strings will simply get lopped off at the end if the progress bar window isn't big enough to display it all, so you don't want it to be too narrow.

5) Lastly, you can actually place the progress bar anywhere you want by changing the --posX and --posY parameters when invoking it to something like top and right or bottom, left, etc. cocoaDialog even accepts exact pixel positioning, which is pretty cool.

#!/bin/sh

## Paths to cocoaDialog and the Self Service icon
cdPath="/Library/Application Support/JAMF/bin/cocoaDialog.app/Contents/MacOS/cocoaDialog"
SSIcon="/Applications/Self Service.app/Contents/Resources/Self Service.icns"

## Parameter 4 holds the assignment for either a policy ID
## or a manual trigger for the actual policy that will be run
pid="$4"

if [ "$pid" == "" ]; then
    echo "No policy ID or manual trigger was assigned to paramater 4. Please assign one to use this script."
    exit 1
fi

if [[ $(echo "$pid / $pid" | bc 2>&1 /dev/null) != "1" ]]; then
    PFlag="-trigger"
else
    PFlag="-id"
fi

## Create the name pipe input for the progressbar
rm -f /tmp/hpipe
mkfifo /tmp/hpipe
sleep 0.2

## Display indeterminate progress bar
echo "Displaying progress bar window."
"$cdPath" progressbar --indeterminate --title "Casper Suite Policy" --text "Preparing policy..." 
--posX "center" --posY "center" --width 450 --float --icon-file "$SSIcon" < /tmp/hpipe &

## Send progress through the named pipe
exec 3<> /tmp/hpipe

/usr/sbin/jamf policy $PFlag "$pid" 2>&1 | while read line; do
    ## Get output from current installation and send to progress bar
    outPut=$( echo "$line" | egrep -i "find|gather|install|executing|policy|download|run|retrieving|locating|submit" | sed 's/^[   ]*//g' )
    current_policy=$( tail -10 /var/log/jamf.log | awk -F"Executing Policy" '/Executing Policy/{ print $NF }' | sed -e 's/^ //;s/...$//' | tail -1 )
    if [ "$outPut" != "" ]; then
        echo "10 $outPut" >&3
    else
        echo "10 Please wait. Running $current_policy..." >&3
    fi
done

## Wait 1 second before shutting off progressbar
sleep 1

# Turn off progress bar by closing file descriptor 3 and removing the named pipe
echo "Closing progress bar."
exec 3>&-
rm -f /tmp/hpipe

exit 0

Let me know if you end up trying this out and what you think. While its not perfect by any stretch and it involves having two polices, one running the script and the other one the actual policy, it could be useful in some cases where the boiler plate "Checking for policies..." jamfHelper screen isn't sufficient.

rseide
Contributor

Thanks stevewood and mm2270! I really appreciate the scripts you posted. I will give this a shot but i do not have the jamfHelper app on the JSS. I tried to look into the JAMF/bin folder but I can't access it, even if I try to "sudo cd" into it.

We're running 8.63.

rseide
Contributor

Thanks stevewood and mm2270! I really appreciate the scripts you posted. I will give this a shot but i do not have the jamfHelper app on the JSS. I tried to look into the JAMF/bin folder but I can't access it, even if I try to "sudo cd" into it.

We're running 8.63.

mm2270
Legendary Contributor III

@rseide, jamfHelper.app exists on every client, or should, as it gets installed as part of the management framework when a Mac is enrolled. Its in a protected folder, but sudo commands can access it.

If you want to "see it" from Terminal, open a root shell first

sudo -s

Enter your admin account password when prompted. The Terminal should change to something like bash-3.2# at the prompt. From there you can cd into any location you want, even ones with protected permissions like /Library/Application Support/JAMF/bin/

rseide
Contributor

Thanks! that did the trick. I will try the scripts out as soon as time permits and let you know how it goes.

Thanks to everyone who contributed to this thread. :)