Forum Discussion

Simon42's avatar
Simon42
Copper Contributor
Sep 14, 2022

MacOS Intune PKG Enrollment - LOB APP

Hello,
I am currently having a problmen with rolling out the global protect client over intune. I have testet it with different versions(5.21 and 6.1.0) but without success. The pgk file has a current signature.
 
Over Troubleshootings + support options I can only see the Error code: 0x87D13BA7 Unknown.
 
Do you have any ideas? And actually its also not possible to upload a wrapped app in the .intunemac format
 

3 Replies

  • Michelle_ash's avatar
    Michelle_ash
    Copper Contributor

    Simon42 You are not alone, this is a long standing issue with PA Global Protect due to the way it handles the installation in the package.  This was happening with wrapped packages as well.

     

    There is a way to get it to install with a .sh script.  At the bottom of my post is a sample script that will require some editing and testing.

     

    What the script does:

     

    It creates a plist file and then populates vpn portal info from the information provided in the script, and then downloads or gets the package from a location (hopefully you have access to define a URL where you can store the base package), and installs it.

     

    You will need to whitelist system extensions in a device profile by whitelisting the teamID , but aside from that it should work with some tweaking of the script, provided you can get the package to retrieve from a specific location you have chosen for it to reside:

     

    #!/bin/sh
    
    plistBuddy='/usr/libexec/PlistBuddy'
    GPplistFile='/Library/Preferences/com.paloaltonetworks.GlobalProtect.settings.plist'
    
    if [ -f ${GPplistFile} ]
    then
    	echo "Plist already exists..."
    else
    	echo "Creating Plist"
    	${plistBuddy} -c "print : 'Palo Alto Networks':'GlobalProtect':'PanSetup':'Portal'" ${GPplistFile}
    	${plistBuddy} -c "add :'Palo Alto Networks' dict" ${GPplistFile}
    	${plistBuddy} -c "add :'Palo Alto Networks':'GlobalProtect' dict" ${GPplistFile}
    	${plistBuddy} -c "add :'Palo Alto Networks':'GlobalProtect':'PanSetup' dict" ${GPplistFile}
    	${plistBuddy} -c "add :'Palo Alto Networks':'GlobalProtect':'PanSetup':'Portal' string 'vpn.company.com'" ${GPplistFile}
    	${plistBuddy} -c "add :'Palo Alto Networks':'GlobalProtect':'PanSetup':'Prelogon' integer 0" ${GPplistFile}
    fi
    	
    if [ -d "/Applications/GlobalProtect.app" ]
    then
    	echo "Already installed..."
    	exit 0
    else
    	echo "Preparing..."
    	curl "http://files.company.com/GlobalProtect.pkg" > "/tmp/GlobalProtect.pkg"
    	echo "Installing..."	
    	sudo installer -pkg "/tmp/GlobalProtect.pkg" -target /
    	echo "Cleaning..."
    	rm "/tmp/GlobalProtect.pkg"
    	exit 0
    fi
    • Simon42's avatar
      Simon42
      Copper Contributor

      Hello Michelle_ash

      thanks for the reply. 

      Then I will try to open a ticket for this at palo alto. 

       

      I know the script and it works with it. But it would be nicer if the user could load the app via the company portal when needed. 

      If I hear anything from Palo Alto, I will report here. 

       

       

      • scsteady's avatar
        scsteady
        Copper Contributor

        Simon42  I haven't see anyone post but here is the shell script I used and it worked light out. We  used  azure blob with public www 

         

        also used plist option to set the url 

        #!/bin/bash
        #set -x
        
        ############################################################################################
        ##
        ## Script to install the latest GlobalProtect Blob Servers
        ##
        ############################################################################################
        
        
        # Define variables
        weburl="https://xxxx.z13.web.core.windows.net/GlobalProtect.pkg"                                        # What is the Azure Blob Storage URL?
        appname="GlobalProtect"                                                                        # The name of our App deployment script
        app="GlobalProtect.app"                                                                        # The actual name of our App once installed
        logandmetadir="/Library/Logs/Microsoft/IntuneScripts/GlobalProtect"                               # The location of our logs and last updated data
        processpath="/Applications/GlobalProtect.app/Contents/MacOS/GlobalProtect"                    # The process name of the App we are installing
        terminateprocess="false"                                                                        # Do we want to terminate the running process? If false we'll wait until its not running
        autoUpdate="false"   
        
        # Generated variables
        tempdir=$(mktemp -d)
        log="$logandmetadir/$appname.log"                                               # The location of the script log file
        metafile="$logandmetadir/$appname.meta"                                         # The location of our meta file (for updates)
        
        plistBuddy='/usr/libexec/PlistBuddy'
        GPplistFile='/Library/Preferences/com.paloaltonetworks.GlobalProtect.settings.plist'
        
        if [ -f ${GPplistFile} ]
        then
        	echo "Plist already exists..."
        else
        	echo "Creating Plist"
        	${plistBuddy} -c "print : 'Palo Alto Networks':'GlobalProtect':'PanSetup':'Portal'" ${GPplistFile}
        	${plistBuddy} -c "add :'Palo Alto Networks' dict" ${GPplistFile}
        	${plistBuddy} -c "add :'Palo Alto Networks':'GlobalProtect' dict" ${GPplistFile}
        	${plistBuddy} -c "add :'Palo Alto Networks':'GlobalProtect':'PanSetup' dict" ${GPplistFile}
        	${plistBuddy} -c "add :'Palo Alto Networks':'GlobalProtect':'PanSetup':'Portal' string 'vpn.something.com'" ${GPplistFile}
        	${plistBuddy} -c "add :'Palo Alto Networks':'GlobalProtect':'PanSetup':'Prelogon' integer 0" ${GPplistFile}
        fi
        
        
        
        # function to delay script if the specified process is running
        waitForProcess () {
        
            #################################################################################################################
            #################################################################################################################
            ##
            ##  Function to pause while a specified process is running
            ##
            ##  Functions used
            ##
            ##      None
            ##
            ##  Variables used
            ##
            ##      $1 = name of process to check for
            ##      $2 = length of delay (if missing, function to generate random delay between 10 and 60s)
            ##      $3 = true/false if = "true" terminate process, if "false" wait for it to close
            ##
            ###############################################################
            ###############################################################
        
            processName=$1
            fixedDelay=$2
            terminate=$3
        
            echo "$(date) | Waiting for other [$processName] processes to end"
            while ps aux | grep "$processName" | grep -v grep &>/dev/null; do
        
                if [[ $terminate == "true" ]]; then
                    echo "$(date) | + [$appname] running, terminating [$processpath]..."
                    pkill -f "$processName"
                    return
                fi
        
                # If we've been passed a delay we should use it, otherwise we'll create a random delay each run
                if [[ ! $fixedDelay ]]; then
                    delay=$(( $RANDOM % 50 + 10 ))
                else
                    delay=$fixedDelay
                fi
        
                echo "$(date) |  + Another instance of $processName is running, waiting [$delay] seconds"
                sleep $delay
            done
            
            echo "$(date) | No instances of [$processName] found, safe to proceed"
        
        }
        
        # function to check if we need Rosetta 2
        checkForRosetta2 () {
        
            #################################################################################################################
            #################################################################################################################
            ##
            ##  Simple function to install Rosetta 2 if needed.
            ##
            ##  Functions
            ##
            ##      waitForProcess (used to pause script if another instance of softwareupdate is running)
            ##
            ##  Variables
            ##
            ##      None
            ##
            ###############################################################
            ###############################################################
        
            
        
            echo "$(date) | Checking if we need Rosetta 2 or not"
        
            # if Software update is already running, we need to wait...
            waitForProcess "/usr/sbin/softwareupdate"
        
        
            ## Note, Rosetta detection code from https://derflounder.wordpress.com/2020/11/17/installing-rosetta-2-on-apple-silicon-macs/
            OLDIFS=$IFS
            IFS='.' read osvers_major osvers_minor osvers_dot_version <<< "$(/usr/bin/sw_vers -productVersion)"
            IFS=$OLDIFS
        
            if [[ ${osvers_major} -ge 11 ]]; then
        
                # Check to see if the Mac needs Rosetta installed by testing the processor
        
                processor=$(/usr/sbin/sysctl -n machdep.cpu.brand_string | grep -o "Intel")
                
                if [[ -n "$processor" ]]; then
                    echo "$(date) | $processor processor installed. No need to install Rosetta."
                else
        
                    # Check for Rosetta "oahd" process. If not found,
                    # perform a non-interactive install of Rosetta.
                    
                    if /usr/bin/pgrep oahd >/dev/null 2>&1; then
                        echo "$(date) | Rosetta is already installed and running. Nothing to do."
                    else
                        /usr/sbin/softwareupdate --install-rosetta --agree-to-license
                    
                        if [[ $? -eq 0 ]]; then
                            echo "$(date) | Rosetta has been successfully installed."
                        else
                            echo "$(date) | Rosetta installation failed!"
                            exitcode=1
                        fi
                    fi
                fi
                else
                    echo "$(date) | Mac is running macOS $osvers_major.$osvers_minor.$osvers_dot_version."
                    echo "$(date) | No need to install Rosetta on this version of macOS."
            fi
        
        }
        
        # Function to update the last modified date for this app
        fetchLastModifiedDate() {
        
            #################################################################################################################
            #################################################################################################################
            ##
            ##  This function takes the following global variables and downloads the URL provided to a temporary location
            ##
            ##  Functions
            ##
            ##      none
            ##
            ##  Variables
            ##
            ##      $logandmetadir = Directory to read nand write meta data to
            ##      $metafile = Location of meta file (used to store last update time)
            ##      $weburl = URL of download location
            ##      $tempfile = location of temporary DMG file downloaded
            ##      $lastmodified = Generated by the function as the last-modified http header from the curl request
            ##
            ##  Notes
            ##
            ##      If called with "fetchLastModifiedDate update" the function will overwrite the current lastmodified date into metafile
            ##
            ###############################################################
            ###############################################################
        
            ## Check if the log directory has been created
            if [[ ! -d "$logandmetadir" ]]; then
                ## Creating Metadirectory
                echo "$(date) | Creating [$logandmetadir] to store metadata"
                mkdir -p "$logandmetadir"
            fi
        
            # generate the last modified date of the file we need to download
            lastmodified=$(curl -sIL "$weburl" | grep -i "last-modified" | awk '{$1=""; print $0}' | awk '{ sub(/^[ \t]+/, ""); print }' | tr -d '\r')
        
            if [[ $1 == "update" ]]; then
                echo "$(date) | Writing last modifieddate [$lastmodified] to [$metafile]"
                echo "$lastmodified" > "$metafile"
            fi
        
        }
        
        function downloadApp () {
        
            #################################################################################################################
            #################################################################################################################
            ##
            ##  This function takes the following global variables and downloads the URL provided to a temporary location
            ##
            ##  Functions
            ##
            ##      waitForCurl (Pauses download until all other instances of Curl have finished)
            ##      downloadSize (Generates human readable size of the download for the logs)
            ##
            ##  Variables
            ##
            ##      $appname = Description of the App we are installing
            ##      $weburl = URL of download location
            ##      $tempfile = location of temporary DMG file downloaded
            ##
            ###############################################################
            ###############################################################
        
            echo "$(date) | Starting downlading of [$appname]"
        
            # wait for other downloads to complete
            waitForProcess "curl -f"
        
            #download the file
            updateOctory installing
            echo "$(date) | Downloading $appname"
        
            cd "$tempdir"
            curl -f -s --connect-timeout 30 --retry 5 --retry-delay 60 -L -J -O "$weburl"
            if [ $? == 0 ]; then
        
                    # We have downloaded a file, we need to know what the file is called and what type of file it is
                    tempSearchPath="$tempdir/*"
                    for f in $tempSearchPath; do
                        tempfile=$f
                    done
        
                    case $tempfile in
        
                    *.pkg|*.PKG)
                        packageType="PKG"
                        ;;
        
                    *.zip|*.ZIP)
                        packageType="ZIP"
                        ;;
        
                    *.dmg|*.DMG)
                        packageType="DMG"
                        ;;
        
                    *)
                        # We can't tell what this is by the file name, lets look at the metadata
                        echo "$(date) | Unknown file type [$f], analysing metadata"
                        metadata=$(file "$tempfile")
                        if [[ "$metadata" == *"Zip archive data"* ]]; then
                            packageType="ZIP"
                            mv "$tempfile" "$tempdir/install.zip"
                            tempfile="$tempdir/install.zip"
                        fi
        
                        if [[ "$metadata" == *"xar archive"* ]]; then
                            packageType="PKG"
                            mv "$tempfile" "$tempdir/install.pkg"
                            tempfile="$tempdir/install.pkg"
                        fi
        
                        if [[ "$metadata" == *"bzip2 compressed data"* ]] || [[ "$metadata" == *"zlib compressed data"* ]] ; then
                            packageType="DMG"
                            mv "$tempfile" "$tempdir/install.dmg"
                            tempfile="$tempdir/install.dmg"
                        fi
                        ;;
                    esac
        
                    if [[ ! $packageType ]]; then
                        echo "Failed to determine temp file type [$metadata]"
                        rm -rf "$tempdir"
                    else
                        echo "$(date) | Downloaded [$app] to [$tempfile]"
                        echo "$(date) | Detected install type as [$packageType]"
                    fi
                 
            else
            
                echo "$(date) | Failure to download [$weburl] to [$tempfile]"
                 updateOctory failed
                 exit 1
            fi
        
        }
        
        # Function to check if we need to update or not
        function updateCheck() {
        
            #################################################################################################################
            #################################################################################################################
            ##
            ##  This function takes the following dependencies and variables and exits if no update is required
            ##
            ##  Functions
            ##
            ##      fetchLastModifiedDate
            ##
            ##  Variables
            ##
            ##      $appname = Description of the App we are installing
            ##      $tempfile = location of temporary DMG file downloaded
            ##      $volume = name of volume mount point
            ##      $app = name of Application directory under /Applications
            ##
            ###############################################################
            ###############################################################
        
        
            echo "$(date) | Checking if we need to install or update [$appname]"
        
            ## Is the app already installed?
            if [ -d "/Applications/$app" ]; then
        
            # App is installed, if it's updates are handled by MAU we should quietly exit
            if [[ $autoUpdate == "true" ]]; then
                echo "$(date) | [$appname] is already installed and handles updates itself, exiting"
                exit 0;
            fi
        
            # App is already installed, we need to determine if it requires updating or not
                echo "$(date) | [$appname] already installed, let's see if we need to update"
                fetchLastModifiedDate
        
                ## Did we store the last modified date last time we installed/updated?
                if [[ -d "$logandmetadir" ]]; then
        
                    if [ -f "$metafile" ]; then
                        previouslastmodifieddate=$(cat "$metafile")
                        if [[ "$previouslastmodifieddate" != "$lastmodified" ]]; then
                            echo "$(date) | Update found, previous [$previouslastmodifieddate] and current [$lastmodified]"
                            update="update"
                        else
                            echo "$(date) | No update between previous [$previouslastmodifieddate] and current [$lastmodified]"
                            echo "$(date) | Exiting, nothing to do"
                            exit 0
                        fi
                    else
                        echo "$(date) | Meta file [$metafile] not found"
                        echo "$(date) | Unable to determine if update required, updating [$appname] anyway"
        
                    fi
                    
                fi
        
            else
                echo "$(date) | [$appname] not installed, need to download and install"
            fi
        
        }
        
        ## Install PKG Function
        function installPKG () {
        
            #################################################################################################################
            #################################################################################################################
            ##
            ##  This function takes the following global variables and installs the PKG file
            ##
            ##  Functions
            ##
            ##      isAppRunning (Pauses installation if the process defined in global variable $processpath is running )
            ##      fetchLastModifiedDate (Called with update flag which causes the function to write the new lastmodified date to the metadata file)
            ##
            ##  Variables
            ##
            ##      $appname = Description of the App we are installing
            ##      $tempfile = location of temporary DMG file downloaded
            ##      $volume = name of volume mount point
            ##      $app = name of Application directory under /Applications
            ##
            ###############################################################
            ###############################################################
        
        
            # Check if app is running, if it is we need to wait.
            waitForProcess "$processpath" "300" "$terminateprocess"
        
            echo "$(date) | Installing $appname"
        
        
            # Update Octory monitor
            updateOctory installing
        
            # Remove existing files if present
            if [[ -d "/Applications/$app" ]]; then
                rm -rf "/Applications/$app"
            fi
        
            installer -pkg "$tempfile" -target /Applications
        
            # Checking if the app was installed successfully
            if [ "$?" = "0" ]; then
        
                echo "$(date) | $appname Installed"
                echo "$(date) | Cleaning Up"
                rm -rf "$tempdir"
        
                echo "$(date) | Application [$appname] succesfully installed"
                fetchLastModifiedDate update
                updateOctory installed
                exit 0
        
            else
        
                echo "$(date) | Failed to install $appname"
                rm -rf "$tempdir"
                updateOctory failed
                exit 1
            fi
        
        }
        
        ## Install DMG Function
        function installDMG () {
        
            #################################################################################################################
            #################################################################################################################
            ##
            ##  This function takes the following global variables and installs the DMG file into /Applications
            ##
            ##  Functions
            ##
            ##      isAppRunning (Pauses installation if the process defined in global variable $processpath is running )
            ##      fetchLastModifiedDate (Called with update flag which causes the function to write the new lastmodified date to the metadata file)
            ##
            ##  Variables
            ##
            ##      $appname = Description of the App we are installing
            ##      $tempfile = location of temporary DMG file downloaded
            ##      $volume = name of volume mount point
            ##      $app = name of Application directory under /Applications
            ##
            ###############################################################
            ###############################################################
        
        
            # Check if app is running, if it is we need to wait.
            waitForProcess "$processpath" "300" "$terminateprocess"
        
        
        
            echo "$(date) | Installing [$appname]"
            updateOctory installing
        
            # Mount the dmg file...
            volume="$tempdir/$appname"
            echo "$(date) | Mounting Image"
            hdiutil attach -quiet -nobrowse -mountpoint "$volume" "$tempfile"
        
            # Remove existing files if present
            if [[ -d "/Applications/$app" ]]; then
                echo "$(date) | Removing existing files"
                rm -rf "/Applications/$app"
            fi
        
            # Sync the application and unmount once complete
            echo "$(date) | Copying app files to /Applications/$app"
            rsync -a "$volume"/*.app/ "/Applications/$app"
        
            # Unmount the dmg
            echo "$(date) | Un-mounting [$volume]"
            hdiutil detach -quiet "$volume"
        
            # Checking if the app was installed successfully
        
            if [[ -a "/Applications/$app" ]]; then
        
                echo "$(date) | [$appname] Installed"
                echo "$(date) | Cleaning Up"
                rm -rf "$tempfile"
        
                echo "$(date) | Fixing up permissions"
                sudo chown -R root:wheel "/Applications/$app"
                echo "$(date) | Application [$appname] succesfully installed"
                fetchLastModifiedDate update
                updateOctory installed
                exit 0
            else
                echo "$(date) | Failed to install [$appname]"
                rm -rf "$tempdir"
                updateOctory failed
                exit 1
            fi
        
        }
        
        ## Install ZIP Function
        function installZIP () {
        
            #################################################################################################################
            #################################################################################################################
            ##
            ##  This function takes the following global variables and installs the DMG file into /Applications
            ##
            ##  Functions
            ##
            ##      isAppRunning (Pauses installation if the process defined in global variable $processpath is running )
            ##      fetchLastModifiedDate (Called with update flag which causes the function to write the new lastmodified date to the metadata file)
            ##
            ##  Variables
            ##
            ##      $appname = Description of the App we are installing
            ##      $tempfile = location of temporary DMG file downloaded
            ##      $volume = name of volume mount point
            ##      $app = name of Application directory under /Applications
            ##
            ###############################################################
            ###############################################################
        
        
            # Check if app is running, if it is we need to wait.
            waitForProcess "$processpath" "300" "$terminateprocess"
        
            echo "$(date) | Installing $appname"
            updateOctory installing
        
            # Change into temp dir
            cd "$tempdir"
            if [ "$?" = "0" ]; then
              echo "$(date) | Changed current directory to $tempdir"
            else
              echo "$(date) | failed to change to $tempfile"
              if [ -d "$tempdir" ]; then rm -rf $tempdir; fi
              updateOctory failed
              exit 1
            fi
        
            # Unzip files in temp dir
            unzip -qq -o "$tempfile"
            if [ "$?" = "0" ]; then
              echo "$(date) | $tempfile unzipped"
            else
              echo "$(date) | failed to unzip $tempfile"
              if [ -d "$tempdir" ]; then rm -rf $tempdir; fi
              updateOctory failed
              exit 1
            fi
        
            # If app is already installed, remove all old files
            if [[ -a "/Applications/$app" ]]; then
            
              echo "$(date) | Removing old installation at /Applications/$app"
              rm -rf "/Applications/$app"
            
            fi
        
            # Copy over new files
            rsync -a "$app/" "/Applications/$app"
            if [ "$?" = "0" ]; then
              echo "$(date) | $appname moved into /Applications"
            else
              echo "$(date) | failed to move $appname to /Applications"
              if [ -d "$tempdir" ]; then rm -rf $tempdir; fi
              updateOctory failed
              exit 1
            fi
        
            # Make sure permissions are correct
            echo "$(date) | Fix up permissions"
            sudo chown -R root:wheel "/Applications/$app"
            if [ "$?" = "0" ]; then
              echo "$(date) | correctly applied permissions to $appname"
            else
              echo "$(date) | failed to apply permissions to $appname"
              if [ -d "$tempdir" ]; then rm -rf $tempdir; fi
              updateOctory failed
              exit 1
            fi
        
            # Checking if the app was installed successfully
            if [ "$?" = "0" ]; then
                if [[ -a "/Applications/$app" ]]; then
        
                    echo "$(date) | $appname Installed"
                    updateOctory installed
                    echo "$(date) | Cleaning Up"
                    rm -rf "$tempfile"
        
                    # Update metadata
                    fetchLastModifiedDate update
        
                    echo "$(date) | Fixing up permissions"
                    sudo chown -R root:wheel "/Applications/$app"
                    echo "$(date) | Application [$appname] succesfully installed"
                    exit 0
                else
                    echo "$(date) | Failed to install $appname"
                    exit 1
                fi
            else
        
                # Something went wrong here, either the download failed or the install Failed
                # intune will pick up the exit status and the IT Pro can use that to determine what went wrong.
                # Intune can also return the log file if requested by the admin
                
                echo "$(date) | Failed to install $appname"
                if [ -d "$tempdir" ]; then rm -rf $tempdir; fi
                exit 1
            fi
        }
        
        function updateOctory () {
        
            #################################################################################################################
            #################################################################################################################
            ##
            ##  This function is designed to update Octory status (if required)
            ##
            ##
            ##  Parameters (updateOctory parameter)
            ##
            ##      notInstalled
            ##      installing
            ##      installed
            ##
            ###############################################################
            ###############################################################
        
            # Is Octory present
            if [[ -a "/Library/Application Support/Octory" ]]; then
        
                # Octory is installed, but is it running?
                if [[ $(ps aux | grep -i "Octory" | grep -v grep) ]]; then
                    echo "$(date) | Updating Octory monitor for [$appname] to [$1]"
                    /usr/local/bin/octo-notifier monitor "$appname" --state $1 >/dev/null
                fi
            fi
        
        }
        
        function startLog() {
        
            ###################################################
            ###################################################
            ##
            ##  start logging - Output to log file and STDOUT
            ##
            ####################
            ####################
        
            if [[ ! -d "$logandmetadir" ]]; then
                ## Creating Metadirectory
                echo "$(date) | Creating [$logandmetadir] to store logs"
                mkdir -p "$logandmetadir"
            fi
        
            exec &> >(tee -a "$log")
            
        }
        
        # function to delay until the user has finished setup assistant.
        waitForDesktop () {
          until ps aux | grep /System/Library/CoreServices/Dock.app/Contents/MacOS/Dock | grep -v grep &>/dev/null; do
            delay=$(( $RANDOM % 50 + 10 ))
            echo "$(date) |  + Dock not running, waiting [$delay] seconds"
            sleep $delay
          done
          echo "$(date) | Dock is here, lets carry on"
        }
        
        ###################################################################################
        ###################################################################################
        ##
        ## Begin Script Body
        ##
        #####################################
        #####################################
        
        # Initiate logging
        startLog
        
        echo ""
        echo "##############################################################"
        echo "# $(date) | Logging install of [$appname] to [$log]"
        echo "############################################################"
        echo ""
        
        # Install Rosetta if we need it
        checkForRosetta2
        
        # Test if we need to install or update
        updateCheck
        
        # Wait for Desktop
        waitForDesktop
        
        # Download app
        downloadApp
        
        # Install PKG file
        if [[ $packageType == "PKG" ]]; then
            installPKG
        fi
        
        # Install PKG file
        if [[ $packageType == "ZIP" ]]; then
            installZIP
        fi
        
        # Install PKG file
        if [[ $packageType == "DMG" ]]; then
            installDMG
        fi

         

         

Resources