Menu Close

Microsoft Office: User Configuration Capture & Upload

Help your users easily provide Microsoft Support their Office configuration files while maintaining user privacy

Background

After implementing Microsoft’s recommended macro security in Office for Mac settings via a Configuration Profile, then having affected users run Paul’s Office-Reset packages via Jamf Pro’s Self Service, some users are still observing the dreaded Run-time error 32815 triple-prompts for Visual Basic for Applications when opening blank documents in Word, Excel or PowerPoint.

Run-time error ‘32815’

While again re-running — or re-re-running — the Office-Reset policies suppress the error, we started working with Microsoft Support to determine root-cause as the issue seems to reemerge immediately after each Office update.

TL;DR: We’re currently convinced it’s Adobe Acrobat DC’s fault

Capture User’s Office Configuration

We started by focusing on Word and the request from Microsoft Support was to capture the content of the following folders both before and after the next Office upgrade:

  • ~/Library/Containers/com.microsoft.Word
  • ~/Library/Group Containers/UBF8T346G9.Office/User Content.localized/*
  • /Library/Application Support/Microsoft/Office365/User Content.localized/*

~/Library/Containers

Since a sandboxed app can only write to its own directories, the ~/Library/Containers/com.microsoft.Word/Data folder contains aliases to several user folders, including ~/Desktop, ~/Downloads and the highly personal ~/Pictures directory:

❯ ls -lah ~/Library/Containers/com.microsoft.Word/Data
total 16
drwx------  13 dan  staff   416B Sep  2 01:15 .
drwx------@  5 dan  staff   160B Sep  2 01:15 ..
lrwxr-xr-x   1 dan  staff    19B Jul 19 08:37 Desktop -> ../../../../Desktop
drwx------   2 dan  staff    64B Jul 19 08:37 Documents
lrwxr-xr-x   1 dan  staff    21B Jul 19 08:37 Downloads -> ../../../../Downloads
drwx------  33 dan  staff   1.0K Jul 28 14:52 Library
lrwxr-xr-x   1 dan  staff    18B Jul 19 08:37 Movies -> ../../../../Movies
lrwxr-xr-x   1 dan  staff    17B Jul 19 08:37 Music -> ../../../../Music
lrwxr-xr-x   1 dan  staff    20B Jul 19 08:37 Pictures -> ../../../../Pictures
drwx------   2 dan  staff    64B Jul 19 08:37 SystemData
drwx------   2 dan  staff    64B Jul 19 08:37 tmp

--symlinks

As entertaining as this Personally Identifiable Information (PII) may be to a Microsoft Support engineer, we elected to exclude the contents of aliased directories by adding the --symlinks option to the zip command.

--exclude

After a review by our internal Security team, we choose to also exclude the Cookies and WebKit directories:

The Cookies folder may contain authentication cookies

The Webkit folder could include authentication data from our IdP

Note: While the user’s shortname is plainly visible in the output, this is most likleyl already known to Microsoft.

Script

Add the following script to Jamf Pro, adjusting the workspace URL as provided by Microsoft Support. (Latest version available on GitHub.)

#!/bin/bash
####################################################################################################
#
# ABOUT
#
#   Microsoft Office User Configuration Capture
#
####################################################################################################
#
# HISTORY
#
# Version 1.0.0, 02-Sep-2022, Dan K. Snelson
#   Original version
#
# Version 1.0.1, 02-Sep-2022, Dan K. Snelson
#   Exclude "Webkit" and "Cookies" (per Obi-Bryson)
#
####################################################################################################



####################################################################################################
#
# Variables
#
####################################################################################################

scriptVersion="1.0.1"
scriptResult=""
export PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin
loggedInUser=$( echo "show State:/Users/ConsoleUser" | scutil | awk '/Name :/ { print $3 }' )
loggedInUserHome=$( dscl . -read /Users/$loggedInUser | grep NFSHomeDirectory: | cut -c 19- | head -n 1 )
serialNumber=$( system_profiler SPHardwareDataType | grep "Serial Number" | awk -F ": " '{ print $2 }' )
timestamp=$( date '+%Y-%m-%d-%H%M%S' )
filename="microsoft_case_86753099_${serialNumber}-${timestamp}"



####################################################################################################
#
# Functions
#
####################################################################################################

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Check for / install swiftDialog (thanks, @acodega!)
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

function dialogCheck(){

    # Get the URL of the latest PKG From the Dialog GitHub repo
    dialogURL=$( curl --silent --fail "https://api.github.com/repos/bartreardon/swiftDialog/releases/latest" | awk -F '"' "/browser_download_url/ && /pkg\"/ { print \$4; exit }" )

    # Expected Team ID of the downloaded PKG
    expectedDialogTeamID="PWA5E9TQ59"

    # Check for Dialog and install if not found
    if [[ ! -e "/Library/Application Support/Dialog/Dialog.app" ]]; then

        scriptResult+="Installing Dialog; "

        # Create temporary working directory
        workDirectory=$( basename "$0" )
        tempDirectory=$( mktemp -d "/private/tmp/$workDirectory.XXXXXX" )

        # Download the installer package
        curl --location --silent "$dialogURL" -o "$tempDirectory/Dialog.pkg"

        # Verify the download
        teamID=$( spctl -a -vv -t install "$tempDirectory/Dialog.pkg" 2>&1 | awk '/origin=/ {print $NF }' | tr -d '()' )

        # Install the package if Team ID validates
        if [[ "$expectedDialogTeamID" = "$teamID" ]] || [[ "$expectedDialogTeamID" = "" ]]; then
            installer -pkg "$tempDirectory/Dialog.pkg" -target /
        else
            jamfDisplayMessage "Dialog Team ID verification failed."
            exit 1
        fi

        # Remove the temporary working directory when done
        rm -Rf "$tempDirectory"  

    else

        scriptResult+="Dialog version $(dialog --version) found; proceeding..."

    fi

}



# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Display Message: Dialog
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

function displayMessageDialog() {

    rm /var/tmp/dialog.log

    title="${1}"
    message="${2}"
    icon=$( defaults read /Library/Preferences/com.jamfsoftware.jamf.plist self_service_app_path )

    scriptResult+="Display \"${title}\" message to ${loggedInUser}; "

    dialog --title "${title}" --message "${message}" --icon "${icon}" --ontop --moveable

    echo "quit:" >> /var/tmp/dialog.log

}



# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# JAMF Display Message (for fallback in case swiftDialog fails to install)
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

function jamfDisplayMessage() {
    scriptResult+="${1}"
    jamf displayMessage -message "${1}" &
}



# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Reveal File in Finder
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

function revealMe() {
    /usr/bin/su - "${loggedInUser}" -c '/usr/bin/open -R "'"${1}"'" '
}



####################################################################################################
#
# Program
#
####################################################################################################

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Logging preamble
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

scriptResult+="Microsoft Office User Configuration Capture (${scriptVersion}); "



# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Confirm script is running as root
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

if [[ $(id -u) -ne 0 ]]; then
    scriptResult+="This script should be run as root; exiting."
    echo "${scriptResult}"
    exit 1
fi



# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Validate logged-in user
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

if [[ -z "${loggedInUser}" || "${loggedInUser}" == "loginwindow" ]]; then
    scriptResult+="No user logged-in; exiting."
    echo "${scriptResult}"
    exit 0
fi



# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Validate swiftDialog is installed
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

dialogCheck



# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Compress Microsoft Word-related directories
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

scriptResult+="Compress Microsoft Word-related directories; "

zip --quiet --recurse-paths --symlinks "${loggedInUserHome}/Desktop/${filename}.zip" "/Library/Application Support/Microsoft/Office365/User Content.localized" "${loggedInUserHome}/Library/Group Containers/UBF8T346G9.Office/User Content.localized" "${loggedInUserHome}/Library/Containers/com.microsoft.Word" --exclude "${loggedInUserHome}/Library/Containers/com.microsoft.Word/Data/Library/Cookies/*" --exclude "${loggedInUserHome}/Library/Containers/com.microsoft.Word/Data/Library/WebKit/*"

scriptResult+="Microsoft Word-related directories saved to: ${loggedInUserHome}/Desktop/${filename}.zip; "



# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Display End-user Message
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

displayMessageDialog "Microsoft Case No. 86753099 (${scriptVersion})" "## Log Gathering Complete  \n\nYour computer logs have been saved
to your Desktop as:  \n\n\`${filename}.zip\`  \n\nPlease [upload](https://support.microsoft.com/files?workspace=ridiculously-long-URL-goes-here) the file to Microsoft."



# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Reveal Compressed File
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

scriptResult+="Reveal Compressed File; "

revealMe "${loggedInUserHome}/Desktop/${filename}.zip"



# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Exit
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

scriptResult+="Complete!"

echo "${scriptResult}"

exit 0

Policy

Create a new Jamf Pro policy, add the script and make the policy available in Self Service.

Self Service Description

Adjust the workspace URL as provided by Microsoft Support.

## Office for Mac: Default templates' macros re-enabled with each upgrade

Please click the **Capture** button to save the following directories to your Mac's Desktop:  
  
- `/Library/Application Support/Microsoft/Office365/User Content`
- `~/Library/Containers/Microsoft Word`
- `~/Library/Group Containers/UBF8T346G9.Office/User Content`

Once complete, a compressed file with a name similar to `microsoft_case_86753099 … .zip` will be saved to your Mac's Desktop.

Please [upload](https://support.microsoft.com/files?workspace=ridiculously-long-URL-goes-here) the `microsoft_case_86753099 … .zip` file to Microsoft.

User Message

The script will gather the directories and leverage swiftDialog (installing, if necessary) to display a Self Service-branded message to the users which includes a link to upload the output directly to Microsoft:

Posted in Microsoft Office, Scripts, Tips & Tricks

Related Posts