Tutorial

New updates and improvements to Roundfleet.

Important notice

The code examples and scripts provided in these tutorials are for educational purposes only. Roundfleet is not responsible for any issues, damages, or security vulnerabilities that may arise from the use, modification, or implementation of these examples. Always review and test code in a secure environment before using it in production systems.

Application Uninstall Management for macOS

Implement enterprise-grade application uninstall management across your Roundfleet deployment with automated lifecycle management, security validation, residual file cleanup, and comprehensive fleet-wide application removal. This tutorial provides solutions for maintaining clean system environments while ensuring secure and efficient application lifecycle management.

Understanding macOS Application Uninstall Management

macOS provides several methods for application removal:

  • Manual Drag-to-Trash - Standard user method via Finder
  • rm command - Command-line removal of application bundles
  • Third-party Uninstallers - Specialized tools for complete removal
  • MDM Uninstall Actions - Remote uninstall capabilities
  • Package Manager Tools - Homebrew, MacPorts uninstall commands

Basic Application Uninstall

Simple Application Removal

#!/bin/bash

# Basic app uninstall
sudo rm -rf /Applications/Opera.app

Core Uninstall Command Structure

#!/bin/bash

# Generic app uninstall template
sudo rm -rf /path/to/app/files

The rm command options:

  • -r - Removes the file hierarchy (recursive)
  • -f - Removes files without prompting for confirmation (force)

Enterprise Application Uninstall Management System

Comprehensive Application Lifecycle Tool

#!/bin/bash

# Roundfleet Enterprise Application Uninstall Management Tool
# Advanced application removal and lifecycle management

# Configuration
CONFIG_FILE="/etc/roundfleet/app_uninstall_policy.conf"
LOG_FILE="/var/log/roundfleet_app_uninstall.log"
QUARANTINE_DIR="/Library/Roundfleet/QuarantinedApps"
AUDIT_LOG="/var/log/roundfleet_app_audit.log"

# Create directories
mkdir -p "$(dirname "$CONFIG_FILE")" "$(dirname "$LOG_FILE")" "$QUARANTINE_DIR" "$(dirname "$AUDIT_LOG")"

# Default application uninstall policy
cat > "$CONFIG_FILE" 2>/dev/null << 'EOF' || true
# Roundfleet Enterprise Application Uninstall Management Policy
# Version: 2.0

# Uninstall Policy Enforcement
ENFORCE_UNINSTALL_POLICIES=true
SAFE_UNINSTALL_MODE=true
BACKUP_BEFORE_UNINSTALL=true
VERIFY_APP_SIGNATURES=true
PREVENT_SYSTEM_APP_REMOVAL=true

# Security and Safety
REQUIRE_ADMIN_APPROVAL=false
VALIDATE_APP_DEPENDENCIES=true
CHECK_RUNNING_PROCESSES=true
QUARANTINE_SUSPICIOUS_APPS=true
MALWARE_SCAN_ENABLED=true

# Cleanup and Maintenance
COMPLETE_CLEANUP_ENABLED=true
REMOVE_PREFERENCES=true
REMOVE_SUPPORT_FILES=true
REMOVE_CACHES=true
REMOVE_LOGS=true
CLEAN_LAUNCH_SERVICES=true

# Business Rules
BUSINESS_HOURS_RESTRICTION=true
BUSINESS_HOURS_START="09:00"
BUSINESS_HOURS_END="18:00"
CRITICAL_APP_PROTECTION=true
LICENSED_APP_TRACKING=true

# Notification and Communication
USER_NOTIFICATION_ENABLED=true
ADMIN_NOTIFICATION_ENABLED=true
SLACK_WEBHOOK_URL=""
EMAIL_NOTIFICATION_ENABLED=false

# Compliance and Audit
AUDIT_ALL_UNINSTALLS=true
COMPLIANCE_REPORTING=true
SOFTWARE_INVENTORY_UPDATE=true
LICENSE_TRACKING=true
SECURITY_INCIDENT_REPORTING=true

# Recovery and Rollback
BACKUP_RETENTION_DAYS=30
ROLLBACK_CAPABILITY=true
EMERGENCY_RECOVERY=true
EOF

# Source configuration
source "$CONFIG_FILE" 2>/dev/null || true

# Logging function
log_action() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
}

# Audit logging function
audit_log() {
    local action="$1"
    local app_name="$2"
    local result="$3"
    local details="$4"
    echo "$(date '+%Y-%m-%d %H:%M:%S') - ACTION:$action APP:$app_name RESULT:$result DETAILS:$details USER:$(whoami)" >> "$AUDIT_LOG"
}

# Get application information
get_app_info() {
    local app_path="$1"
    
    if [[ ! -d "$app_path" ]]; then
        echo "App not found: $app_path"
        return 1
    fi
    
    local app_name
    app_name=$(basename "$app_path")
    
    local bundle_id=""
    local version=""
    local signature_status=""
    
    # Get bundle identifier
    if [[ -f "$app_path/Contents/Info.plist" ]]; then
        bundle_id=$(defaults read "$app_path/Contents/Info.plist" CFBundleIdentifier 2>/dev/null || echo "unknown")
        version=$(defaults read "$app_path/Contents/Info.plist" CFBundleShortVersionString 2>/dev/null || echo "unknown")
    fi
    
    # Check code signature
    if command -v codesign >/dev/null 2>&1; then
        if codesign -v "$app_path" >/dev/null 2>&1; then
            signature_status="valid"
        else
            signature_status="invalid"
        fi
    else
        signature_status="unknown"
    fi
    
    echo "Name: $app_name"
    echo "Bundle ID: $bundle_id"
    echo "Version: $version"
    echo "Signature: $signature_status"
    echo "Path: $app_path"
}

# Check if application can be safely uninstalled
check_uninstall_safety() {
    local app_path="$1"
    local force="${2:-false}"
    
    echo "=== Validating Application Uninstall Safety ==="
    
    local app_name
    app_name=$(basename "$app_path")
    
    # Check if app exists
    if [[ ! -d "$app_path" ]]; then
        echo "✅ App not found (already uninstalled): $app_name"
        return 0
    fi
    
    # Prevent system app removal
    if [[ "$PREVENT_SYSTEM_APP_REMOVAL" == "true" ]]; then
        local system_apps=(
            "Activity Monitor.app"
            "Console.app"
            "Disk Utility.app"
            "Finder.app"
            "System Preferences.app"
            "Terminal.app"
            "Utilities"
        )
        
        for system_app in "${system_apps[@]}"; do
            if [[ "$app_name" == "$system_app" ]]; then
                echo "❌ Cannot uninstall system application: $app_name"
                audit_log "UNINSTALL_BLOCKED" "$app_name" "SYSTEM_APP" "System app protection active"
                return 1
            fi
        done
    fi
    
    # Check if app is currently running
    if [[ "$CHECK_RUNNING_PROCESSES" == "true" ]]; then
        local app_executable
        app_executable=$(basename "$app_name" .app)
        
        if pgrep -f "$app_executable" >/dev/null 2>&1; then
            echo "⚠️  Application is currently running: $app_name"
            
            if [[ "$force" != "true" ]]; then
                echo "❌ Uninstall blocked: Application is running. Use force option to terminate and uninstall."
                audit_log "UNINSTALL_BLOCKED" "$app_name" "RUNNING" "Application is currently running"
                return 1
            else
                echo "🚨 Force uninstall: Will terminate running application"
                pkill -f "$app_executable" 2>/dev/null || true
                sleep 2
            fi
        fi
    fi
    
    # Business hours check
    if [[ "$BUSINESS_HOURS_RESTRICTION" == "true" && "$force" != "true" ]]; then
        local current_hour
        current_hour=$(date +%H)
        local start_hour
        start_hour=$(echo "$BUSINESS_HOURS_START" | cut -d':' -f1)
        local end_hour
        end_hour=$(echo "$BUSINESS_HOURS_END" | cut -d':' -f1)
        
        if [[ $current_hour -ge $start_hour && $current_hour -lt $end_hour ]]; then
            echo "⚠️  Business hours restriction active ($BUSINESS_HOURS_START - $BUSINESS_HOURS_END)"
            
            # Check if it's a critical app
            if [[ "$CRITICAL_APP_PROTECTION" == "true" ]]; then
                echo "❌ Uninstall blocked during business hours for safety"
                audit_log "UNINSTALL_BLOCKED" "$app_name" "BUSINESS_HOURS" "Business hours protection active"
                return 1
            fi
        fi
    fi
    
    # Signature verification
    if [[ "$VERIFY_APP_SIGNATURES" == "true" ]]; then
        if ! codesign -v "$app_path" >/dev/null 2>&1; then
            echo "⚠️  Warning: Application has invalid or missing signature"
            
            if [[ "$QUARANTINE_SUSPICIOUS_APPS" == "true" ]]; then
                echo "🔒 Quarantining suspicious application before removal"
                quarantine_application "$app_path"
            fi
        fi
    fi
    
    echo "✅ Application uninstall safety validated"
    audit_log "SAFETY_CHECK" "$app_name" "PASSED" "All safety checks passed"
    return 0
}

# Create backup before uninstall
create_app_backup() {
    local app_path="$1"
    local app_name
    app_name=$(basename "$app_path")
    
    if [[ "$BACKUP_BEFORE_UNINSTALL" != "true" ]]; then
        return 0
    fi
    
    echo "=== Creating Application Backup ==="
    
    local backup_dir="/Library/Roundfleet/AppBackups"
    local backup_file="$backup_dir/${app_name%.*}_backup_$(date +%Y%m%d_%H%M%S).tar.gz"
    
    mkdir -p "$backup_dir"
    
    echo "Creating backup of $app_name..."
    if tar -czf "$backup_file" -C "$(dirname "$app_path")" "$(basename "$app_path")" 2>/dev/null; then
        echo "✅ Application backup created: $backup_file"
        log_action "Application backup created: $backup_file"
        
        # Set retention policy
        find "$backup_dir" -name "*_backup_*.tar.gz" -mtime +$BACKUP_RETENTION_DAYS -delete 2>/dev/null || true
        
        return 0
    else
        echo "⚠️  Application backup failed"
        log_action "WARNING: Application backup failed for $app_name"
        return 1
    fi
}

# Quarantine suspicious application
quarantine_application() {
    local app_path="$1"
    local app_name
    app_name=$(basename "$app_path")
    
    echo "=== Quarantining Suspicious Application ==="
    
    local quarantine_path="$QUARANTINE_DIR/$(date +%Y%m%d_%H%M%S)_$app_name"
    
    if mv "$app_path" "$quarantine_path" 2>/dev/null; then
        echo "🔒 Application quarantined: $quarantine_path"
        log_action "Application quarantined: $app_name -> $quarantine_path"
        audit_log "QUARANTINE" "$app_name" "SUCCESS" "Suspicious app quarantined"
        
        # Create quarantine record
        cat > "$quarantine_path.info" << EOF
{
  "original_path": "$app_path",
  "quarantine_time": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
  "reason": "suspicious_signature",
  "quarantined_by": "$(whoami)"
}
EOF
        
        return 0
    else
        echo "❌ Failed to quarantine application"
        return 1
    fi
}

# Find and remove application support files
cleanup_app_support_files() {
    local app_name="$1"
    local bundle_id="$2"
    
    if [[ "$COMPLETE_CLEANUP_ENABLED" != "true" ]]; then
        return 0
    fi
    
    echo "=== Cleaning Application Support Files ==="
    
    local cleanup_paths=()
    local app_base_name
    app_base_name=$(basename "$app_name" .app)
    
    # Common cleanup locations
    local common_locations=(
        "/Library/Application Support"
        "/Library/Caches"
        "/Library/Preferences"
        "/Library/Logs"
        "~/Library/Application Support"
        "~/Library/Caches"
        "~/Library/Preferences"
        "~/Library/Logs"
        "~/Library/Saved Application State"
    )
    
    for location in "${common_locations[@]}"; do
        # Expand tilde
        location="${location/#\~/$HOME}"
        
        if [[ -d "$location" ]]; then
            # Search by app name
            find "$location" -maxdepth 2 -name "*$app_base_name*" -type d 2>/dev/null | while read -r path; do
                if [[ -n "$path" ]]; then
                    cleanup_paths+=("$path")
                fi
            done
            
            # Search by bundle ID if available
            if [[ -n "$bundle_id" && "$bundle_id" != "unknown" ]]; then
                find "$location" -maxdepth 2 -name "*$bundle_id*" -type d 2>/dev/null | while read -r path; do
                    if [[ -n "$path" ]]; then
                        cleanup_paths+=("$path")
                    fi
                done
            fi
        fi
    done
    
    # Remove preference files
    if [[ "$REMOVE_PREFERENCES" == "true" && -n "$bundle_id" && "$bundle_id" != "unknown" ]]; then
        local pref_files=(
            "/Library/Preferences/$bundle_id.plist"
            "$HOME/Library/Preferences/$bundle_id.plist"
            "$HOME/Library/Preferences/ByHost/$bundle_id.*"
        )
        
        for pref_file in "${pref_files[@]}"; do
            if [[ -f "$pref_file" ]]; then
                rm -f "$pref_file" 2>/dev/null || true
                echo "🗑️  Removed preference file: $pref_file"
            fi
        done
    fi
    
    # Clean up found support files
    local cleaned_count=0
    for path in "${cleanup_paths[@]}"; do
        if [[ -d "$path" ]]; then
            rm -rf "$path" 2>/dev/null || true
            echo "🗑️  Removed support files: $path"
            ((cleaned_count++))
        fi
    done
    
    # Update Launch Services database
    if [[ "$CLEAN_LAUNCH_SERVICES" == "true" ]]; then
        echo "🔄 Updating Launch Services database..."
        /System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister -kill -r -domain local -domain system -domain user 2>/dev/null || true
    fi
    
    echo "✅ Cleanup completed: $cleaned_count support file locations removed"
    log_action "Application support files cleanup completed for $app_name ($cleaned_count locations)"
}

# Send uninstall notification
send_uninstall_notification() {
    local app_name="$1"
    local operation="$2"
    local result="$3"
    
    if [[ "$USER_NOTIFICATION_ENABLED" != "true" ]]; then
        return 0
    fi
    
    echo "=== Sending Uninstall Notifications ==="
    
    local notification_title="Roundfleet Application Management"
    local notification_message="Application $operation: $app_name ($result)"
    
    # Display notification to logged-in users
    local logged_users
    logged_users=$(who | awk '{print $1}' | sort -u)
    
    for user in $logged_users; do
        if [[ -n "$user" ]]; then
            sudo -u "$user" osascript -e "display notification \"$notification_message\" with title \"$notification_title\"" 2>/dev/null || true
            echo "📱 Notification sent to user: $user"
        fi
    done
    
    # Slack notification
    if [[ -n "$SLACK_WEBHOOK_URL" ]]; then
        local slack_payload="{\"text\":\"🖥️ *$(hostname)*: $notification_title\\n$notification_message\"}"
        curl -s -X POST -H 'Content-type: application/json' --data "$slack_payload" "$SLACK_WEBHOOK_URL" >/dev/null 2>&1 || true
        echo "📢 Slack notification sent"
    fi
    
    log_action "Uninstall notifications sent for $app_name ($operation - $result)"
}

# Enterprise application uninstall
enterprise_uninstall() {
    local app_path="$1"
    local force="${2:-false}"
    local skip_backup="${3:-false}"
    
    echo "=== Enterprise Application Uninstall ==="
    
    if [[ -z "$app_path" ]]; then
        echo "❌ Application path required"
        return 1
    fi
    
    local app_name
    app_name=$(basename "$app_path")
    
    # Get application information
    echo "Analyzing application: $app_name"
    local app_info
    app_info=$(get_app_info "$app_path")
    echo "$app_info"
    
    local bundle_id
    bundle_id=$(echo "$app_info" | grep "Bundle ID:" | cut -d':' -f2 | xargs)
    
    # Safety checks
    if ! check_uninstall_safety "$app_path" "$force"; then
        return 1
    fi
    
    # Create backup if enabled
    if [[ "$skip_backup" != "true" ]]; then
        create_app_backup "$app_path"
    fi
    
    log_action "ENTERPRISE UNINSTALL: Starting uninstall of $app_name"
    audit_log "UNINSTALL" "$app_name" "INITIATED" "Path: $app_path Bundle: $bundle_id Force: $force"
    
    # Perform the uninstall
    echo "🗑️  Removing application bundle..."
    if sudo rm -rf "$app_path"; then
        echo "✅ Application bundle removed successfully"
        
        # Complete cleanup
        cleanup_app_support_files "$app_name" "$bundle_id"
        
        # Send notifications
        send_uninstall_notification "$app_name" "uninstall" "success"
        
        log_action "Application uninstalled successfully: $app_name"
        audit_log "UNINSTALL" "$app_name" "SUCCESS" "Complete removal including support files"
        
        return 0
    else
        echo "❌ Failed to remove application bundle"
        send_uninstall_notification "$app_name" "uninstall" "failed"
        log_action "FAILED: Could not remove application: $app_name"
        audit_log "UNINSTALL" "$app_name" "FAILED" "Bundle removal failed"
        return 1
    fi
}

# Bulk application uninstall
bulk_uninstall() {
    local app_list_file="$1"
    local force="${2:-false}"
    
    echo "=== Bulk Application Uninstall ==="
    
    if [[ ! -f "$app_list_file" ]]; then
        echo "❌ Application list file not found: $app_list_file"
        return 1
    fi
    
    local success_count=0
    local failure_count=0
    local total_count=0
    
    while IFS= read -r app_path; do
        # Skip empty lines and comments
        if [[ -z "$app_path" || "$app_path" == \#* ]]; then
            continue
        fi
        
        ((total_count++))
        echo "Processing ($total_count): $app_path"
        
        if enterprise_uninstall "$app_path" "$force" "false"; then
            ((success_count++))
        else
            ((failure_count++))
        fi
        
        echo "---"
    done < "$app_list_file"
    
    echo "=== Bulk Uninstall Summary ==="
    echo "Total applications: $total_count"
    echo "Successful uninstalls: $success_count"
    echo "Failed uninstalls: $failure_count"
    
    log_action "Bulk uninstall completed: $success_count/$total_count successful"
    audit_log "BULK_UNINSTALL" "MULTIPLE" "COMPLETED" "Success: $success_count Failed: $failure_count Total: $total_count"
}

# Malware application removal
remove_malware_app() {
    local app_path="$1"
    local threat_level="${2:-medium}"
    
    echo "🚨 MALWARE APPLICATION REMOVAL 🚨"
    
    local app_name
    app_name=$(basename "$app_path")
    
    log_action "MALWARE REMOVAL: Removing malicious application: $app_name (Threat: $threat_level)"
    audit_log "MALWARE_REMOVAL" "$app_name" "INITIATED" "Threat level: $threat_level"
    
    # Quarantine first for analysis
    if [[ "$threat_level" == "high" ]]; then
        echo "🔒 High threat level - quarantining for security analysis"
        quarantine_application "$app_path"
    else
        # Force removal without backup for malware
        echo "🗑️  Performing emergency malware removal..."
        enterprise_uninstall "$app_path" "true" "true"
    fi
    
    # Security incident reporting
    if [[ "$SECURITY_INCIDENT_REPORTING" == "true" ]]; then
        local incident_file="/var/log/roundfleet_security_incidents.log"
        echo "$(date '+%Y-%m-%d %H:%M:%S') - MALWARE_REMOVAL: $app_name (Threat: $threat_level) User: $(whoami) Device: $(hostname)" >> "$incident_file"
    fi
    
    send_uninstall_notification "$app_name" "malware removal" "completed"
    audit_log "MALWARE_REMOVAL" "$app_name" "COMPLETED" "Emergency removal completed"
}

# List installed applications
list_applications() {
    local filter="$1"
    
    echo "=== Installed Applications ==="
    
    local app_list=()
    
    # Find all .app bundles
    while IFS= read -r -d '' app_path; do
        local app_name
        app_name=$(basename "$app_path")
        
        if [[ -n "$filter" ]]; then
            if [[ "$app_name" == *"$filter"* ]]; then
                app_list+=("$app_path")
            fi
        else
            app_list+=("$app_path")
        fi
    done < <(find /Applications -name "*.app" -type d -print0 2>/dev/null)
    
    # Sort and display
    printf '%s\n' "${app_list[@]}" | sort
    
    echo "Total applications found: ${#app_list[@]}"
}

# Generate uninstall report
generate_uninstall_report() {
    local report_file="/Library/Roundfleet/Reports/app_uninstall_report_$(date +%Y%m%d_%H%M%S).json"
    
    echo "=== Generating Application Uninstall Report ==="
    
    mkdir -p "$(dirname "$report_file")"
    
    # Count recent operations from audit log
    local recent_uninstalls=0
    local recent_quarantines=0
    local recent_malware_removals=0
    
    if [[ -f "$AUDIT_LOG" ]]; then
        recent_uninstalls=$(grep -c "ACTION:UNINSTALL.*RESULT:SUCCESS" "$AUDIT_LOG" 2>/dev/null || echo 0)
        recent_quarantines=$(grep -c "ACTION:QUARANTINE" "$AUDIT_LOG" 2>/dev/null || echo 0)
        recent_malware_removals=$(grep -c "ACTION:MALWARE_REMOVAL" "$AUDIT_LOG" 2>/dev/null || echo 0)
    fi
    
    # Get current application count
    local total_apps
    total_apps=$(find /Applications -name "*.app" -type d 2>/dev/null | wc -l)
    
    # Create JSON report
    cat > "$report_file" << EOF
{
  "report_type": "application_uninstall_management",
  "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
  "device_info": {
    "hostname": "$(hostname)",
    "os_version": "$(sw_vers -productVersion)",
    "serial_number": "$(system_profiler SPHardwareDataType | grep "Serial Number" | awk -F: '{print $2}' | xargs)"
  },
  "application_statistics": {
    "total_installed_applications": $total_apps,
    "recent_uninstalls": $recent_uninstalls,
    "quarantined_applications": $recent_quarantines,
    "malware_removals": $recent_malware_removals
  },
  "policy_configuration": {
    "safe_uninstall_mode": $SAFE_UNINSTALL_MODE,
    "backup_before_uninstall": $BACKUP_BEFORE_UNINSTALL,
    "complete_cleanup_enabled": $COMPLETE_CLEANUP_ENABLED,
    "business_hours_restriction": $BUSINESS_HOURS_RESTRICTION
  },
  "security_status": {
    "signature_verification": $VERIFY_APP_SIGNATURES,
    "quarantine_enabled": $QUARANTINE_SUSPICIOUS_APPS,
    "malware_scan_enabled": $MALWARE_SCAN_ENABLED,
    "security_incident_reporting": $SECURITY_INCIDENT_REPORTING
  }
}
EOF
    
    echo "Application uninstall report saved to: $report_file"
    log_action "Application uninstall management report generated: $report_file"
}

# Main function with argument handling
main() {
    log_action "=== Roundfleet Application Uninstall Management Tool Started ==="
    
    case "${1:-help}" in
        "uninstall")
            enterprise_uninstall "$2" "$3" "$4"
            ;;
        "bulk")
            bulk_uninstall "$2" "$3"
            ;;
        "malware")
            remove_malware_app "$2" "$3"
            ;;
        "list")
            list_applications "$2"
            ;;
        "info")
            get_app_info "$2"
            ;;
        "report")
            generate_uninstall_report
            ;;
        *)
            echo "Roundfleet Enterprise Application Uninstall Management Tool"
            echo "Usage: $0 [command] [options]"
            echo ""
            echo "Commands:"
            echo "  uninstall [app_path] [force] [skip_backup]  - Uninstall application with safety checks"
            echo "  bulk [list_file] [force]                    - Bulk uninstall from file list"
            echo "  malware [app_path] [threat_level]           - Remove malicious application"
            echo "  list [filter]                               - List installed applications"
            echo "  info [app_path]                             - Get application information"
            echo "  report                                      - Generate uninstall management report"
            echo ""
            echo "Examples:"
            echo "  $0 uninstall /Applications/Opera.app       - Safe uninstall with backup"
            echo "  $0 uninstall /Applications/App.app true    - Force uninstall (skip safety checks)"
            echo "  $0 bulk apps_to_remove.txt                 - Bulk uninstall from list"
            echo "  $0 malware /Applications/Malware.app high  - Emergency malware removal"
            echo "  $0 list Safari                             - List apps containing 'Safari'"
            ;;
    esac
    
    log_action "=== Application uninstall management operation completed ==="
}

# Execute main function
main "$@"

Advanced Application Management Features

Application Dependency Analysis

#!/bin/bash

# Check application dependencies before uninstall
check_app_dependencies() {
    local app_path="$1"
    local app_name
    app_name=$(basename "$app_path")
    
    echo "=== Analyzing Application Dependencies ==="
    
    # Check for shared frameworks
    local frameworks_dir="$app_path/Contents/Frameworks"
    if [[ -d "$frameworks_dir" ]]; then
        echo "📦 Found embedded frameworks:"
        ls -la "$frameworks_dir" | grep -v "^total" | awk '{print $9}' | grep -v "^$"
    fi
    
    # Check for plugins and extensions
    local plugins_dir="$app_path/Contents/PlugIns"
    if [[ -d "$plugins_dir" ]]; then
        echo "🔌 Found plugins/extensions:"
        find "$plugins_dir" -name "*.appex" -o -name "*.plugin" | while read -r plugin; do
            echo "  - $(basename "$plugin")"
        done
    fi
    
    # Check for launch agents/daemons
    local plist_locations=(
        "/Library/LaunchAgents"
        "/Library/LaunchDaemons"
        "$HOME/Library/LaunchAgents"
    )
    
    echo "🔄 Checking for launch services:"
    for location in "${plist_locations[@]}"; do
        if [[ -d "$location" ]]; then
            find "$location" -name "*.plist" | while read -r plist; do
                if grep -q "$app_name" "$plist" 2>/dev/null; then
                    echo "  - Found reference in: $(basename "$plist")"
                fi
            done
        fi
    done
}

# Create application removal checklist
create_removal_checklist() {
    local app_path="$1"
    local checklist_file="/tmp/app_removal_checklist_$(date +%Y%m%d_%H%M%S).txt"
    
    cat > "$checklist_file" << EOF
Application Removal Checklist
=============================
Application: $(basename "$app_path")
Date: $(date)
Operator: $(whoami)

Pre-Removal Checks:
[ ] Application is not currently running
[ ] No dependent applications identified
[ ] Backup created (if required)
[ ] User notification sent
[ ] Business hours compliance verified

Removal Steps:
[ ] Main application bundle removed
[ ] Preferences files cleaned
[ ] Support files removed
[ ] Cache files cleared
[ ] Launch services updated
[ ] System integrity verified

Post-Removal Verification:
[ ] Application no longer appears in Applications folder
[ ] No residual files remain
[ ] System stability confirmed
[ ] License tracking updated
[ ] Audit log entry created

Notes:
_________________________________________________
_________________________________________________
_________________________________________________

Operator Signature: ________________________
Date Completed: ____________________________
EOF
    
    echo "Removal checklist created: $checklist_file"
}

Important Configuration Notes

macOS Application Structure Understanding

  • Application Bundles - .app directories containing executable and resources
  • Bundle Identifiers - Unique identifiers for application tracking
  • Code Signatures - Security validation for application authenticity
  • Support Files - Preferences, caches, logs in various Library locations

Enterprise Integration Points

  • Software Asset Management - Integration with SAM platforms
  • License Compliance - Tracking of licensed application removals
  • Security Information and Event Management (SIEM) - Security incident reporting
  • Change Management Systems - Documentation and approval workflows

Best Practices for Enterprise Application Management

  1. Safety and Validation

    • Always verify application signatures before removal
    • Check for running processes and dependencies
    • Implement business hours restrictions for critical applications
    • Maintain comprehensive audit trails
  2. Data Protection

    • Create backups before uninstallation when required
    • Preserve user data and preferences when appropriate
    • Implement quarantine procedures for suspicious applications
    • Follow data retention policies
  3. System Cleanliness

    • Remove all associated support files and preferences
    • Clean up caches and temporary files
    • Update Launch Services database after removal
    • Verify complete removal through system scans
  4. Security and Compliance

    • Track license compliance for removed applications
    • Report security incidents for malware removal
    • Maintain detailed audit logs for compliance
    • Implement role-based access controls

Troubleshooting Common Issues

  • Permission errors - Ensure admin privileges for application removal
  • Apps in use - Terminate running processes before uninstallation
  • Incomplete removal - Use comprehensive cleanup procedures
  • System apps - Implement protection against critical system app removal
  • Dependency conflicts - Analyze dependencies before bulk removals

Remember to test uninstallation procedures thoroughly in a controlled environment before implementing across your entire Roundfleet to ensure system stability and operational continuity.

Related Tutorials

Application Launch Management for macOS

Manage macOS application launching across Roundfleet devices with automated app deployment, security validation, remote execution, and comprehensive fleet-wide application lifecycle management for enterprise operations.

Jul 7, 2025

Application Language Management on macOS

Learn how to manage and configure individual application languages on macOS devices using command-line scripts for enterprise language policy enforcement and localization management.

Jul 7, 2025

Application Force Close Management for macOS

Manage macOS application force close operations across Roundfleet devices with automated process termination, security validation, troubleshooting diagnostics, and comprehensive fleet-wide application control for enterprise operations.

Jul 7, 2025

Safari Browser Management on macOS

Learn how to configure Safari homepage, browser settings, security policies, and deploy enterprise browser management across your Roundfleet devices with comprehensive user management and compliance features.

Jul 7, 2025

Rosetta 2 and Apple Silicon Compatibility Management on macOS

Learn how to install, manage, and monitor Rosetta 2 translation layer on Apple Silicon Macs with enterprise-grade compatibility management, application monitoring, and fleet-wide deployment capabilities.

Jul 7, 2025

Package Management with Homebrew on macOS

Deploy, manage, and maintain software packages across macOS devices using Homebrew with enterprise-grade configuration management, compliance tracking, and automated deployment workflows.

Jul 7, 2025

Check App Code Signature on macOS

Verify application code signatures on Mac devices to ensure authenticity and detect tampering using codesign commands.

Jul 7, 2025

View Last Opened Time of Apps and Files on macOS

Learn how to track when applications and files were last accessed on macOS devices using advanced shell scripts for comprehensive fleet monitoring.

Jul 7, 2025