Posted on 11-06-2020 10:45 AM
Are you running the NT-ware uniFLOW SmartClient for macOS?
As you probably know, NT-ware's older versions (v1.1.0 and lower) were not as robust as their Windows versions.
In order to upgrade/update to newer versions, you need to uninstall the older versions first.
NT-ware places their default uninstall script here...
/etc/smartclient/uninstall-smartclient.bash
Unfortunately, this script is extremely rudimentary and lacks any support for running in an automated environment that uses an MDM/UDM solution such as Jamf Pro.
With that, I give you my highly augmented version of an NT-ware uniFLOW SmartClient uninstaller that works both locally and/or with Jamf Pro.
A brief HOWTO is posted down below... after the script.
THE SCRIPT
#!/bin/sh
##############################################################################
#
# SCRIPT FILENAME:
# uninstall_nt-ware_uniflow_smartclient.sh
#
# DESCRIPTION:
# The core functionality of this script was written by NT-ware to uninstall
# the uniFLOW SmartClient for macOS.
#
# This version of the uniFLOW SmartClient "uninstall-smartclient.sh" is a
# complete overhaul that provides additional error checking, better local
# user identification, multi-shell compatibility, robust support for unique
# user environments, better output/logging, and a local (terminal) mode
# and an automated UDM/MDM (Jamf Pro) mode.
#
# DISCLAIMER:
# Jamf Pro is not required to run this script. This script can be used as
# a replacement for the default "uninstall-smartclient.sh" that comes
# bundled with the uniFLOW SmartClient.
#
# CHANGE LOG:
# v1.0 - 2020-11-05
# Written by Caine Hörr
# https://github.com/cainehorr
# * Initial Script Creation
# * Replaced vendor assigned shebang for bash and zsh compatibility
# * Replaced vendor code that checks for sudo/root permissions to
# properly identify the currently logged in user
# * Replaced vendor code with an array to process sub-folder deletion
# within home folders
# * Replaced vendor code with AppleScript to gracefully quit the
# uniFLOW SmartClient
# * Removed vendor code that unnecessarily utilizes ls commands in
# favor of echoing path data already held within variables
# * Added functions for multi-use code blocks
# * Added comments to properly "document/explain" the script
# * Added absolute path statements to all called binaries (because
# you never know what users have done to their system environment)
# * Added error checking for existence of files and directories
# * Added echo statements for running script both locally and for
# logging to Jamf Pro policy logs
# * Added JamfHelper pop-ups to guide the user appropriately when
# being run from Jamf Pro
#
##############################################################################
##############################################################################
#
# MIT License
#
# Copyright (c) 2020 Caine Hörr
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
#
##############################################################################
# Set the name and location of the uniFLOW SmartClient application
appName="/Applications/uniFLOW SmartClient.app"
# Acquire the currently installed version of uniFLOW SmartClient.app
currentAppVersion="$(defaults read "${appName}/Contents/Info" CFBundleShortVersionString | awk '{ print $1 }')"
##############################################################################
#
# EDIT THESE VALUES AS MUCH AS YOU WANT!
#
# These values configure the jamfHelper pop-up window look and feel
#
window_Type="utility"
text_Title="mac@Your_Company_Name"
text_Header="uniFLOW SmartClient Uninstall"
align_Header="left"
text_Message_One="IT is uninstalling version ${currentAppVersion} of the following application from your device in preparation for an updated version\n \n${appName}\n \nClicking "OK" will begin the process. \n \nOn the next pop-up window, please click the "Yes" button."
text_Message_Two="The removal of version ${currentAppVersion} of the following application from your device has failed\n \nn${appName}\n \nPlease contact IT for immediate remediation."
text_Message_Three="The removal of version ${currentAppVersion} of the following application from your device has completed\n \n${appName}\n \nIT will now proceed with installing an updated version."
align_Description="left"
icon_path="/path/to/your/corporate/logo.png"
button_Continue="OK"
button_Default=1
#
##############################################################################
##############################################################################
#
# THERE ARE NO USER SERVICABLE PARTS DOWN HERE...
# DO NOT EDIT BELOW THIS LINE!
#
##############################################################################
# Check for sudo/root permissions
# This is only need when running the script locally
# When running in an automated UDM/MDM environment, sudo/root is implied
if [[ "$(/usr/bin/id -u)" != "0" ]]; then
echo "[ERROR] $0 requires sudo/root privileges"
exit 1
fi
function_jamfHelperPopUpWindow(){
# Call jamfHelper and display the pop-up window
jamfHelper -windowType "${window_Type}" -lockHUD -title "${text_Title}" -heading "${text_Header}" -alignHeading "${align_Header}" -description "${text_Description}" -alignDescription "${align_Description}" -icon "${icon_path}" -button1 "${button_Continue}" -defaultButton "${button_Default}"
}
function_quit_uniFLOW_SmartClient(){
if [[ ${jamfHelperInstalled} = "True" ]]; then
# Set the jamfHelper Message
text_Description=$( echo ${text_Message_One} )
function_jamfHelperPopUpWindow
fi
# Attempt to quit the uniFLOW SmartClient gracefully
/usr/bin/osascript <<'END'
tell application "SmartClient"
quit
end tell
END
}
echo "Preparing to uninstall ${appName} v${currentAppVersion}"
# Set path to the jamfHelper.app
jamfHelperPath=/Library/Application Support/JAMF/bin/jamfHelper.app
if [[ -d "${jamfHelperPath}" ]]; then
jamfHelperInstalled="True"
echo "jamfHelper is installed - Running in Jamf Pro mode"
# Set path to the jamfHelper.app/Contents/MacOS
PATH=$PATH:/Library/Application Support/JAMF/bin/jamfHelper.app/Contents/MacOS
else
jamfHelperInstalled="False"
echo "jamfHelper is not installed - Running in terminal mode"
fi
# Identify if the uniFLOW SmartClient is running - First Pass
runningInstance=$(/bin/ps -a -x -o comm | /usr/bin/grep 'SmartClient$' )
# Validate that $runningInstance contains information
if [[ -n "$runningInstance" ]]; then
echo "[WARNING] uniFLOW SmartClient is running on this device - Attempting to quit"
function_quit_uniFLOW_SmartClient
until function_quit_uniFLOW_SmartClient; do
if [[ $? -eq 0 ]]; then
echo "User agreed to the uniFLOW SmartClient uninstallation"
fi
done
else
echo "[WARNING] uniFLOW SmartClient is not running on this device"
fi
# Identify if the uniFLOW SmartClient is running - Second Pass
runningInstance=$(/bin/ps -a -x -o comm | /usr/bin/grep 'SmartClient$' )
# Validate that $runningInstance does not contains information
if [[ ! -z "$runningInstance" ]]; then
echo "[ERROR] uniFLOW SmartClient is running on this device - Attempting to quit has failed"
if [[ ${jamfHelperInstalled} = "True" ]]; then
# Set the jamfHelper Message
text_Description=$( echo ${text_Message_Two} )
function_jamfHelperPopUpWindow
fi
exit 1
fi
# Remove UniFlow SmartCient Domains and Services
plistPath=/Library/LaunchAgents/com.ntware.SmartClient.plist
if [[ -f ${plistPath} ]]; then
echo "Removing UniFlow SmartCient Domains and Services"
/bin/launchctl bootout system /Library/LaunchAgents/com.ntware.SmartClient.plist
fi
# Delete existing uniFLOW SmartClient printer queues
if [[ -f /Users/shared/.smartclient/queue_created_at_installation ]]; then
QUEUE_NAME_NO_SPACES=$(/bin/cat /Users/shared/.smartclient/queue_created_at_installation)
# Validate that $QUEUE_NAME_NO_SPACES is not null
if [[ -n "$QUEUE_NAME_NO_SPACES" ]]; then
echo "Deleting printer queue $QUEUE_NAME_NO_SPACES"
# Delete the printer or class destination
/usr/sbin/lpadmin -x "$QUEUE_NAME_NO_SPACES"
fi
fi
# Identify the uniFLOW SmartClient printers and what devices they are attached to
list=$(/usr/bin/lpstat -v | /usr/bin/grep 'mom:S*$')
# Determine the number of uniFLOW SmartClient printers present
count=$(echo "$list" | /usr/bin/wc -l)
for queueNumber in $(seq $count); do
name=$(echo "$list" | /usr/bin/sed -n "$queueNumber p" | /usr/bin/awk '{print $(NF-1)}' 2>/dev/null | /usr/bin/sed 's?:$??')
newPath=$(echo "$list" | /usr/bin/sed -n "$queueNumber p" | /usr/bin/awk '{print $(NF)}' 2>/dev/null | /usr/bin/sed 's?mom:??g')
# If $name OR $newPath value is null then continue to the next queueNumber
# in the loop without running any further commands below this if/then statement
if [ -z "$name" -o -z "$newPath" ]; then
continue
fi
# The following statements will not execute if $name OR $newPath are null
echo "Changing path for $name to $newPath"
/usr/sbin/lpadmin -p "$name" -E -v "$newPath"
done
# If the script can't uninstall all uniFLOW SmartClient printers, throw this error
remaining=$(/usr/bin/lpstat -v | /usr/bin/grep 'mom:S*$')
if [[ -n "$remaining" ]]; then
echo "[ERROR] Unable to remove 'mom:' backend from all printers. \n \nPlease do so manually before attempting to uninstall again."
exit 1
fi
# Set input field separator to a comma ","
IFS=','
files='/Library/LaunchAgents/com.ntware.SmartClient.plist,/private/etc/paths.d/momadmin-path,/private/etc/sudoers.d/momadmin-sudoers,/usr/libexec/cups/backend/mom,/usr/local/sbin/momadmin.sh'
directories='/Applications/uniFLOW SmartClient.app,/private/etc/smartclient,/Users/Shared/.smartclient'
# Check for the existence of files as declared in $files
for file in ${files}; do
# If file is not found, break out of loop
if [[ ! -f ${file} ]]; then
# If content of $file is not found then continue to the next itteration of $file
# in the loop without running any further commands below this if/then statement
echo "[WARNING] File not found: ${file}"
continue
fi
# The following statements will not execute if $file is not found
# Delete ${file}
/bin/rm -f ${file}
echo "Deleting the following file: ${file}"
done
# Check for the existence of directories as declared in $directories
for directory in ${directories}; do
if [[ ! -d ${directory} ]]; then
# If content of $directories is not found then continue to the next itteration of $directories
# in the loop without running any further commands below this if/then statement
echo "[WARNING] Directory not found: ${directory}"
continue
fi
# The following statements will not execute if $directories is not found
# Delete ${directory}
/bin/rm -r ${directory}
echo "Deleting the following directory: ${directory}"
done
# Delete all .smartclient sub-directories from all User home folders
array=(/Users/*)
for i in "${!array[@]}"; do
userDirectory=${array[i]}
smartClientUserConfig="${userDirectory}/.smartclient"
if [[ -d "${smartClientUserConfig}" ]]; then
echo "Deleting ${smartClientUserConfig}"
/bin/rm -rf "${smartClientUserConfig}"
else
echo "[WARNING] Directory not found: ${smartClientUserConfig}"
fi
done
if [[ ${jamfHelperInstalled} = "True" ]]; then
# Set the jamfHelper Message
text_Description=$( echo ${text_Message_Three} )
function_jamfHelperPopUpWindow
fi
exit
HOWTO USE uninstall_nt-ware_uniflow_smartclient.sh
It's pretty straight forward really.
ENJOY!
Caine Hörr
A reboot a day keeps the admin away!
Posted on 12-10-2021 03:01 PM
We are having issues installing SmartClient. Do you have any ideas for how we might do that?
Posted on 09-29-2022 06:41 AM
We just switched from PaperCut to uniFLOW and we discovered exactly what you described in terms of requiring an uninstall. Thanks for doing the work and making life easier. Cheers!