Upgrade workflow from Office 2016 to Office 2019

pandrum
New Contributor III

We are a Volume Licensing Service Center customer and use the Volume Licensing Serializer for Office 2016.

Whats the preferred workflow to upgrade to Office 2019 from Office 2016? Do I need to uninstall the Office 2016 suite first and then redeploy with Office 2019 and the 2019 VL serializer? Or can I deploy Office 2019 on top of Office 2016 together with the 2019 VL serializer?

1 ACCEPTED SOLUTION

talkingmoose
Moderator
Moderator

For consistent and reliable results, pushing both the VL 2019 Serializer and the current Office 2019 packages together the first time is a good idea. Don't worry about uninstalling what you have. This is simply an update to what you've got. You'll only need to push the serializer this one time.

If you're using a configuration profile to manage registered apps with Microsoft AutoUpdate, be sure you update that too.

https://github.com/pbowden-msft/Payloads/blob/master/MAU_AppArray.plist

View solution in original post

15 REPLIES 15

talkingmoose
Moderator
Moderator

For consistent and reliable results, pushing both the VL 2019 Serializer and the current Office 2019 packages together the first time is a good idea. Don't worry about uninstalling what you have. This is simply an update to what you've got. You'll only need to push the serializer this one time.

If you're using a configuration profile to manage registered apps with Microsoft AutoUpdate, be sure you update that too.

https://github.com/pbowden-msft/Payloads/blob/master/MAU_AppArray.plist

ryan_ball
Valued Contributor

Because I use Jamf Pro, I've decided to try to work with their patch management feature to patch MS Office.

In the past I used @rtrouton's workflow to package the entire suite and include our VL_Serializer which worked great. Unfortunately updating several gigs of apps at once has it's own problems, so I never pushed updates out (plus thousands of Macs downloading Office updates doesn't make sense), I just added new versions to Self Service which sufficed.

However, the new patch management feature is great, but makes it hard to manage Office as you are required to have separate packages for each App, plus you need a VL_Serializer to be used with new installs or upgrades to 2019 apps.

So I've decided to automate @rtrouton's mentioned workflow via a script, (which can be set up with Automator.app to just drag a MS Office PKG into it) and it will create a new package with both the App installer as well as the specific VL_Serializer for either 2016 or 2019 versions. This is a work in progress but seems to function okay.

These versions can be installed right over existing Office installs, can be used in patch management, or can be used as a fresh install.

#!/bin/bash
# written by Ryan Ball

loggedInUser=$(/usr/bin/python -c 'from SystemConfiguration import SCDynamicStoreCopyConsoleUser; import sys; username = (SCDynamicStoreCopyConsoleUser(None, None, None) or [None])[0]; username = [username,""][username in [u"loginwindow", None, u""]]; sys.stdout.write(username + "
");')
userHome=$(/usr/bin/dscl . read "/Users/$loggedInUser" NFSHomeDirectory | cut -c 19-)
filePath="$1"

function finish () {
    if [[ -n "$pkgName" ]] && [[ -d "/tmp/$pkgName" ]]; then
        rm -R "/tmp/$pkgName"
    fi
    exit "$1"
}

# Determine the MS Office PKG we are going to rebuild
[[ -z "$filePath" ]] && filePath=$(osascript -e 'tell app (path to frontmost application as Unicode text) to set new_file to POSIX path of (choose file with prompt "Choose Word|Excel|PowerPoint|Outlook|OneNote .pkg to rebuild." of type {"PKG"})' 2> /dev/null)
[[ -z "$filePath" ]] && echo "User cancelled; exiting." && finish 1
fileName=${filePath##*/}
pkgName=${fileName%.*}

# Expand the package at a temporary location
pkgutil --expand "$filePath" "/tmp/$pkgName"

# Read informatoin about the PKG
if [[ -f "/tmp/$pkgName/Distribution" ]]; then
    pkgInfo=$(grep pkg-ref "/tmp/$pkgName/Distribution" | grep id | grep version | grep -v autoupdate | grep -v licensing)
    # Get the ID of the package
    id=$(echo "$pkgInfo" | tr " " "
" | grep id | grep -o '".*"' | cut -d " -f2)

    # Get the version of the package
    version=$(echo "$pkgInfo" | tr " " "
" | grep version | grep -o '".*"' | cut -d " -f2)
    majorVersion=$(awk -F '.' '{print $1}' <<< "$version")
    minorVersion=$(awk -F '.' '{print $2}' <<< "$version")

    # Make sure we obtain the specifics of the package
    [[ -z "$id" ]] && echo "Error; ID of package is null; exiting." && finish 1
    [[ -z "$version" ]] && echo "Error; Version of package is null; exiting." && finish 1
else
    echo "Error, Distrbution file does not exist; exiting."
    finish 1
fi

if [[ ! "$id" =~ powerpoint|outlook|onenote|excel|word ]]; then
    echo "$id is not a supported MS Office product for this process; exiting."
    finish 1
fi

# Create the PKG source files
rootDir="$userHome/${id}_${version}"
mkdir -p "$rootDir/scripts"
mkdir -p "$rootDir/build"

# Determine the VL Serializer version to use
if [[ "$majorVersion" == "16" ]] && [[ "$minorVersion" -le "16" ]] || [[ "$majorVersion" == "15" ]]; then
    serializer="Microsoft_Office_2016_VL_Serializer_2.0.pkg"
elif [[ "$majorVersion" == "16" ]] && [[ "$minorVersion" -ge "17" ]]; then
    serializer="Microsoft_Office_2019_VL_Serializer.pkg"
else
    echo "Could not determine VL Serializer to use; exiting."
    finish 1
fi

# Save the VL Serializer for later use and copy it to the scripts directory for the PKG
appSupportDir="$userHome/Library/Application Support/Create_Microsoft_Update_PkGs"
if [[ -f "$appSupportDir/$serializer" ]]; then
    echo "Found serializer in $appSupportDir; using that for new package..."
    cp "$appSupportDir/$serializer" "$rootDir/scripts/"
else
    findSerializer=$(osascript -e "tell app (path to frontmost application as Unicode text) to set new_file to POSIX path of (choose file with prompt "Browse to your $serializer package." of type {"PKG"})" 2> /dev/null)
    [[ -z "$findSerializer" ]] && echo "User cancelled; exiting." && finish 1
    mkdir -p "$appSupportDir"
    echo "Saving the Serializer to $appSupportDir for later use..."
    cp "$findSerializer" "$appSupportDir/$serializer"
    cp "$findSerializer" "$rootDir/scripts/$serializer"
fi

# Create the postinstall script for the PKG
cat << EOF > "$rootDir/scripts/postinstall"
#!/bin/bash

# Determine working directory
install_dir=$(dirname "$0")

# Install the MS Office product
/usr/sbin/installer -dumplog -verbose -pkg "$install_dir/${pkgName}_Rebuilt.pkg" -target "$3"

# Install the VL_Serializer
/usr/sbin/installer -dumplog -verbose -pkg "$install_dir/$serializer" -target "$3"

exit 0
EOF

# Move the Office PKG to the scripts directory
cp "${filePath}" "$rootDir/scripts/"
chmod +x "$rootDir/scripts/postinstall"

# Build the PKG
/usr/bin/pkgbuild --nopayload --scripts "/$rootDir/scripts" --identifier "$id" --version "$version" "$rootDir/build/${pkgName}_Rebuilt.pkg"

if [[ -f "$rootDir/build/${pkgName}_Rebuilt.pkg" ]]; then
    echo "Successfully created package."
    open -R "$rootDir/build/${pkgName}_Rebuilt.pkg"
else
    echo "Error, package failed to build; exiting."
    finish 1
fi

finish 0

pandrum
New Contributor III

Thanks @talkingmoose you are a baus.

cboatwright
New Contributor III

Used the new patch management feature and individual packages from https://macadmins.software, working fantastic! One note though... do not push your volume serializer days before the apps because apparently that kills off the use of 2016 apps immediately.

jhalvorson
Valued Contributor

@talkingmoose I have downloaded the MAU_AppArray.plist from https://github.com/pbowden-msft/Payloads/blob/master/MAU_AppArray.plist
What are the steps to add it as a configuration profile? I believe it should be a Custom Setting, but what would the Preference domain be for this plist?

talkingmoose
Moderator
Moderator

@jhalvorson, I just happened to put this one together for Office 2019/365 for a customer last week. The domain you want to use is com.microsoft.autoupdate2. Upload the following plist to a Custom Settings payload in a new Configuration Profile for fully automated (unattended) updates.

com.microsoft.autoupdate2.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Applications</key>
    <dict>
        <key>/Applications/Microsoft Excel.app</key>
        <dict>
            <key>Application ID</key>
            <string>XCEL2019</string>
            <key>LCID</key>
            <integer>1033</integer>
        </dict>
        <key>/Applications/Microsoft OneNote.app</key>
        <dict>
            <key>Application ID</key>
            <string>ONMC2019</string>
            <key>LCID</key>
            <string>1033</string>
        </dict>
        <key>/Applications/Microsoft Outlook.app</key>
        <dict>
            <key>Application ID</key>
            <string>OPIM2019</string>
            <key>LCID</key>
            <integer>1033</integer>
        </dict>
        <key>/Applications/Microsoft PowerPoint.app</key>
        <dict>
            <key>Application ID</key>
            <string>PPT32019</string>
            <key>LCID</key>
            <integer>1033</integer>
        </dict>
        <key>/Applications/Microsoft Word.app</key>
        <dict>
            <key>Application ID</key>
            <string>MSWD2019</string>
            <key>LCID</key>
            <integer>1033</integer>
        </dict>
        <key>/Applications/Skype for Business.app</key>
        <dict>
            <key>Application ID</key>
            <string>MSFB16</string>
            <key>LCID</key>
            <integer>1033</integer>
        </dict>
        <key>/Applications/Microsoft Remote Desktop.app</key>
        <dict>
            <key>Application ID</key>
            <string>MSRD10</string>
            <key>LCID</key>
            <integer>1033</integer>
        </dict>
        <key>/Applications/Company Portal.app</key>
        <dict>
            <key>Application ID</key>
            <string>IMCP01</string>
            <key>LCID</key>
            <integer>1033</integer>
        </dict>
        <key>/Library/Application Support/Microsoft/MAU2.0/Microsoft AutoUpdate.app</key>
        <dict>
            <key>Application ID</key>
            <string>MSau04</string>
            <key>LCID</key>
            <integer>1033</integer>
        </dict>
        <key>/Applications/OneDrive.app</key>
        <dict>
            <key>Application ID</key>
            <string>ONDR18</string>
            <key>LCID</key>
            <integer>1033</integer>
        </dict>
        <key>/Applications/Microsoft Teams.app</key>
        <dict>
            <key>Application ID</key>
            <string>TEAM01</string>
            <key>LCID</key>
            <integer>1033</integer>
        </dict>
        <key>/Applications/Microsoft Defender ATP.app</key>
        <dict>
            <key>Application ID</key>
            <string>WDAV00</string>
            <key>LCID</key>
            <integer>1033</integer>
        </dict>
        <key>/Applications/Microsoft Edge.app</key>
        <dict>
            <key>Application ID</key>
            <string>EDGE01</string>
            <key>LCID</key>
            <integer>1033</integer>
        </dict>
    </dict>
    <key>HowToCheck</key>
    <string>AutomaticDownload</string>
    <key>StartDaemonOnAppLaunch</key>
    <true/>
</dict>
</plist>

mconners
Valued Contributor

Good Afternoon @talkingmoose, looking at your .plist file above, is this all that is needed for Office 2019 to automatically check and keep itself updated? I have been trying to get MAU configured for this and right now, the only working solution for me is when an application is launched, it will attempt to update.

I have been trying to get the automated process to work without the need to open a Microsoft application first.

Thoughts?

talkingmoose
Moderator
Moderator

To have Microsoft AutoUpdate keep apps up-to-date, at least one registered Microsoft app needs to be running. One open app is enough to kick off AutoUpdate's daemon and it will check every 12 hours for updates. This plist registers all the apps on behalf of the end user. Therefore, any one of them running will do the job.

With this plist, those Microsoft apps that are not running will silently update. Any apps that are running will prompt the user to either update now or wait until later. Choosing to wait will update the app the next time it reopens or will prompt to install the update again (if the end user hasn't quit the app).

hdsreid
Contributor III

couple of questions for you guys:
we have users on 2016 VL right now that are eligible to be using O365 with their accounts. If I am not pushing any configuration profiles for Office to these users, is it possible to just drop these eligible users in my o365 patch management group, and have them download/install the latest version of 16.27.x from their current 16.16.x version for 2016? Will it convert it from 2016 to 365 with no issues, only the need to enter credentials for activation when launching the apps for the first time?

The reason I ask is because we have a lot of users deployed on 2016 which was deployed well before I started at my company. The management for Office on Mac was lacking quite a bit, so nothing was ever configured via config profiles. Given the size of our Mac user base (and location), we have mostly been fine allowing users to configure auto update on their own (if they choose to do so/know how), and push the individual update packages out to the rest of the clients via patch management. At the moment, I have no intention of changing this management style (it works for us and our apps are up to date), so I want to find the easiest way to transition from 2016 to 365.

Thanks!

mconners
Valued Contributor

Hello @talkingmoose it was my understanding there was a way for MAU to auto-run even if none of the Microsoft applications weren't running. Is it even possible to have it work this way? If so, what am I missing?

My goal was for MAU to run in the background without any user intervention and without the need to open any of the Microsoft applications.

Thanks again for your responses.

talkingmoose
Moderator
Moderator

@mconners, maybe you're thinking of @pbowden's msupdate script:

https://github.com/pbowden-msft/msupdatehelper

map
New Contributor II

Inconsequential typo in the comments line at ~24 - "informatoin".

kwoodard
Contributor III

I know this is an old thread, but my question seems to fit best here. I hope the original authors are still around and can provide some insight.

With Office 2016 nearing the end of support, I will need to be moving people off of 2016 and onto 2019. When 2011 came to an end, I had a script that removed the old version and a package with all the 2016 apps install, followed by the serializer. I have heard that 2019 can be installed over the top of 2016, with the new serializer run afterwards. Can I not set up a Self Service installer to run the 2019 installer, run the serializer, and be on my way? We have a license for KASE, and with my software update scripts and policies, we get the Office updates weekly. Am I missing something here?

pandrum
New Contributor III

We just installed Office 2019 Suite installer + 2019 VL serializer on top of Office 2016 and it worked fine for us. We pushed it out automatically but Self Service installer should work fine too.

kwoodard
Contributor III

Awesome, thank you @pandrum . I will give that a try on a couple non essential machines.