Packaging M365 (Office) plugins for either or both x86 and x64 versions

Packaging M365 (Office) plugins for either or both x86 and x64 versions

Following up on my post about Office architecture freedom, this time I would like to look at the way IT could (should?) offer plugins for the users.

While it is possible, Microsoft doesn't officially support having both the 64 bit and the 32 bit Office suite on the same device at the same time. Why install both versions of the plugins then?

Some vendors create installers that would deploy both versions just to be on the safe side - or perhaps out of convenience not to have to determine the architecture of the installed Office on the device. One would only need to have a slight inclination towards OCD ( I mean be security savvy enough) to not want to install plugin versions that will serve no purpose. Of course it's up to you.

There are a couple of choices:

  • Install both versions of the plugin - this could eliminate the need for the user to reinstall the plugin after an architecture change.
  • Install only the version that matches the installed Office architecture

In the latter scenario some housekeeping comes into play. Should the user change the Office architecture and then reinstall the plugin, it is desirable to uninstall the old version of the plugin too.

Housekeeping is important. Bear in mind that users could choose not to install any of the plugins again. For this scenario you could mark all apps with a tag (e.g. tattooing the registry during the installation), and modify the Office uninstaller to also remove all your apps tagged as plugins when the office architecture is being replaced.

For now, let's package a plugin!

Oracle SmartView

I deliberately chose this one.

This is a universal plugin, but it has some challenges. I will show below how to install only the one that matches the Office architecture.

As always, if there are changes coming to the device, it's a good idea to inform the user. As this is an office plugin, we also ask to close all Office apps to be on the safe side.

 [String]$installPhase = 'Pre-Installation'
  Show-InstallationPrompt -Message "Please close all Office Apps as this package installs an Office Add-on!" -ButtonMiddleText 'Ok'
  Show-InstallationWelcome -CloseApps 'winword,excel,powerpnt,msaccess,onenote' -CloseAppsCountdown 3600 -DeferTimes 0 -MinimizeWindows $false
  Show-InstallationProgress -WindowLocation 'BottomRight' 

  $registryPath = "HKLM:\SOFTWARE\Microsoft\Office\ClickToRun\Configuration"
  $officeArch = Get-ItemPropertyValue -Path $registryPath -Name "Platform"

Once we know the architecture we can choose to install the accompanying version of the plugin. It is also generally a good idea to instruct all installers to target either of the Program Files folders. Especially if you use AppLocker in your environment. One other particularity for this plugin is that it by default installs itself to C:\Oracle.

SmartView comes in its custom executable that actually has two MSIs embedded, one for each arch. I tried to extract them and just use the MSIs, but had less luck with that, so I stayed with the executable:

 [String]$installPhase = 'Installation'
 if ($officeArch = 'x64'){
  Execute-Process -Path 'SmartView.exe' -Parameters ' /Office=64 /s /v " INSTALLDIR='%ProgramW6432%\Oracle\SmartView'"  ' -CreateNoWindow -WindowStyle 'Hidden'
  Execute-Process -Path 'SmartView.exe' -Parameters ' /Office=32 /s /v " INSTALLDIR='%ProgramW6432%\Oracle\SmartView'"  ' -CreateNoWindow -WindowStyle 'Hidden'

Cool! We now have the matching version installed! I might be mistaken here, but to my experience the %ProgramW6432% expands to either Program Files or Program Files (x86) based on which flavor of the plugin gets installed. It's been awhile since, please correct me in a comment if I am wrong.


Let!s take a look at the uninstallation steps.

As mentioned earlier, there are two MSIs inside, so there are two product codes. For the version pf the plugin they are here in the code below. We still check here for the office architecture, cos if we used the installer from above, we only will have the matching product code.

 [String]$installPhase = 'Uninstallation'
 if ($officeArch = 'x64'){
  Execute-MSI -Action 'Uninstall' -Path '{60C17BF6-C777-4F2E-8BF3-D46AE1392005}'
  Execute-MSI -Action 'Uninstall' -Path '{2367719C-BDE9-4FCD-93CB-1CF97FD17716}'

The uninstall step is quite tricky for this one as it notoriously leaves behind a registry entry that causes excel start with an annoying popup post-uninstall.

This is a case for the PowerShell App Deployment Toolkit (PSADT) to shine. All you need to do is to make sure that this registry entry is deleted for every user as a post-uninstallation task. The cmdlet is here:

 [String]$installPhase = 'Post-Uninstallation'
 [ScriptBlock]$HKCURegistrySettings = {
 Remove-RegistryKey -Key 'HKCU\Software\Microsoft\Office\16.0\excel\options' -Name 'OPEN' -SID $UserProfile.SID
 Invoke-HKCURegistrySettingsForAllUsers -RegistrySettings $HKCURegistrySettings

A Few More Things...

It could be desirable to check for anything that even remotely resembles this plugin being installed even before we actually try installing it. Perhaps we want to remove all previous versions.

PSADT gives a really good cmdlet for that. The Remove-MSIApplications cmdlet lets you uninstall anything matching the name regardless of the version. This is particularly helpful if you have multiple old versions to upgrade and you no longer have all the lingering versions' MSI codes:

Remove-MSIApplications -Name 'Adobe Flash'

This will remove ALL apps matching 'Adobe Flash'

Thinking along these lines you could add this to the Pre-Installation section of your PSADT script. Otherwise, you merely rely on the package maintainer's good will of actually taking care of upgrades for you...

Detection Script

In SCCM you would need to add either product codes being installed. Same applies for Intune, but I just used a custom script.

NOTE: you MUST have something on the output, this I learned from Andrew Taylor's post, otherwise Intune won't detect the app!

# Custom Intune detection script for two MSI codes
# If either one is installed, the product should be detected

# Define the MSI product codes
$MSICode1 = "{2367719C-BDE9-4FCD-93CB-1CF97FD17716}"
$MSICode2 = "{60C17BF6-C777-4F2E-8BF3-D46AE1392005}"

# Check if either MSI code is installed
$Installed1 = Get-WmiObject -Query "SELECT * FROM Win32_Product WHERE IdentifyingNumber = '$MSICode1'" -ErrorAction SilentlyContinue
$Installed2 = Get-WmiObject -Query "SELECT * FROM Win32_Product WHERE IdentifyingNumber = '$MSICode2'" -ErrorAction SilentlyContinue

if ($Installed1 -or $Installed2) {
    Write-Output "Product detected (32-bit or 64-bit)"
    exit 0
} else {
	Write-Output "Product is not detected"
    exit 1 

With the above any plugins can be wither matched to your office architecture and be replaced by the other one after the users switch Office versions.

Comments are very welcome!