Add-in Express™ for Microsoft® Office and .netAdd-in Express Home > Add-in Express for Office and .NET > Online Guide > Deploying Office solutions Deploying Office solutions
As it is frequently stated throughout this manual, an Office solution must be registered so that the corresponding Office
application is able to locate and load it. Add-in Express creates registry keys itself but... Because some keys are created
in HKEY_CURRENT_USER (HKCU) and some in HKEY_LOCAL_MACHINE (HKLM), the user running the installer must have permissions
for the corresponding registry hive. So, you should always consider the permissions or privileges when
choosing the way to deploy your solution. Combined with permissions to the files deployed with the Office extension,
this allows defining the basic rules below:
- The Office solution must be installed to a location for which all users of the extension have appropriate permissions.
- Registering a per-machine extension (= for all users on the PC) normally requires administrative permissions; deploying
such an extension doesn't allow you to use ClickOnce, which is a per-user deployment technology.
- Installer of a per-user extension should not install anything requiring administrative permissions because it may fail
to install for any user account other than administrator.
How your Office extension is registered
A setup project created as described in Creating MSI Installers uses adxregistrator.exe as a custom action.
When you run the installer and adxregistrator.exe is invoked, it performs the following steps:
- loads .NET Framework
- creates an instance of the add-in module
- invokes the registration code provided by the Add-in Express module; there is a special module for each Office extension type
When doing all the things above, adxregistrator.exe writes them into a log file, its default location is {user profile}\Documents\Add-in Express\adxregistrator.log.
What follows below is a description of the process and how you can customize it.
Loading the assembly
adxregistrator.exe supports /install and /uninstall switches. They accept a string parameter containing the file name of the assembly that is to be registered/unregistered.
adxregistrator.exe /install="MyAddin1.dll"
Note.All add-in files including dependencies and the Add-in Express assemblies must be located in the folder where adxregistrator.exe is run.
Determining privileges
A COM add-in has two sides: it is a COM library and an Office add-in at the same time. Both sides of the COM add-in require proper registration in the Windows Registry.
The add-in side of a COM add-in relates only to Office: a per-user COM add-in is denoted by False in the RegisterForAllUsers property of its add-in module and it is
registered in HKCU. A per-machine add-in has True in the RegisterForAllUsers property of its add-in module and it is filed down in HKLM. The exact registry paths
are given in Registry Keys.
But the COM library side of a COM add-in, the COM object implemented by the add-in module and corresponding to the add-in as a whole, must be registered, too.
It can be registered either in HKCU or in HKLM (the same as the add-in side). This is controlled by the /privileges switch supported by adxregistrator.exe.
The switch accepts two values: admin and user. Misspelling the value or omitting the switch results in registering the COM object of the COM add-in in HKLM
which requires administrative permissions.
The need to register both, the COM library and the add-in itself, creates four possible combinations of settings you can specify in RegisterForAllUsers
and in the /privileges switch of adxregistrator.exe. The two combinations below are recommended:
- per-user add-ins:
add-in module: RegisterForAllUsers = False
adxregistrator.exe: /privileges=user
- per-machine add-ins:
add-in module: RegisterForAllUsers = True
adxregistrator.exe: /privileges=admin
Please note that for a per-machine add-in, all users of the add-in must have appropriate permissions for the folder the add-in is installed to.
The Add-in Express team recommends installing such an add-in to Program Files.
Loading CLR
By default, adxregistrator.exe loads the latest version of the .NET Framework installed on the PC. This can be a problem if your assembly uses
version-sensitive components. To bypass this, you can use the /CLRVersion switch that accepts a string value in the format below:
major[[.minor].build]
The value you assign to a switch is processed as described below:
- \CLRVersion="2.0.50727" refers to the specified build of the .NET Framework. If the build with the exact build number is not
installed on the PC, the newest of all .NET Framework versions installed on the PC will be loaded. This will also occur
if any other build of .NET Framework 2.0 is installed on the PC.
- \CLRVersion="2.0" refers to any build of .NET Framework 2.0. In a hypothetical scenario with the now non-existing .NET Framework 2.1 installed, using \CLRVersion="2.0" will result in loading the latest version of the .NET Framework installed on the PC (after the registrator does not find .NET Framework 2.0).
- \CLRVersion="2" refers to any build of .NET Framework 2.0.
If the specified version of the .NET Framework is not installed on the PC, the newest version of all .NET Framework versions installed on the PC is loaded instead.
Creating an instance of the add-in module
After the CLR is loaded, the registrator creates an AppDomain, loads the assembly specified by you (see Loading the Assembly),
creates an instance of the Add-in Express module defined in the assembly and run the registration code provided by every module of Add-in Express.
If the assembly includes several Add-in Express modules (=several Office extensions), the registrator processes all of them in turn.
An important note
Creating an instance of the module invokes the module's constructor. It means that you should foresee the situation in which the module is created
outside of the Office application. If you don't, a run-time exception may prevent your Office solution from being registered or unregistered.
The simplest way to bypass this is not to write custom code in the constructor of the module. Instead, you can use the events the module provides.
Note. Do not write custom code in the constructor of the module.
If a variable in the module is declared on the class level, the initializer of the variable is called even before the constructor of the module.
That is why all the reasoning for not using custom code in the module's constructor does apply to initializers.
Note. Do not use initializers of complex-type variables declared on the class level in the module.
Running the registration code
Every Add-in Express module provides a static (Shared in VB.NET) method with the ComRegisterFunction attribute applied. That method invokes
the registration code defined in the base class of the module. Note that if you create a custom static (Shared in VB.NET) method and apply
ComRegisterFunction to it, the method will be executed during registration. The ComUnregisterFunction attribute is processed in a similar fashion;
if this attribute is applied to a method, the method will be called while unregistering the extension. There's no way to predict or change the
order in which amethods having such attributes are called.
Documenting the process
The process of registration/unregistration is documented in a log file, the default location of which is
{user profile}\Documents\Add-in Express\adxregistrator.log. The registrator supports the /LogFileLocation switch that allows you to specify the
path and file name of the log file. Also, the log file will not be generated if you use /GenerateLogFile=false; omitting that switch means the file will be generated.
When specifying the path to the log file, you can refer to a system folder using a wide-spread notation, a sample of which is %UserProfileFolder%.
Below is the list of supported folder IDs (please find their definitions here ):
- ProgramFilesX64Folder
- RoamingAppDataFolder
- DesktopFolder
- PersonalFolder
- InternetCacheFolder
- LocalAppDataFolder
- AppDataFolder
- DocumentsFolder
- MyDocumentsFolder
- UserProfileFolder
- ProgramFilesFolder
- CommonProgramDataFolder
- PublicDocumentsFolder
- PublicDesktopFolder
- ProgramFilesX64CommonFolder
- ProgramFilesCommonFolder
The supported macro characters are as follows: <>, &&, [], $$, %%.
Exit code
If a custom action returns a non-zero exit code, the .MSI installer produces nasty dialogs that may scare the end-user and produce extra problems
for the developer. That is why, the default value of the /ReturnExitCode switch supported by the registrator is false. Nevertheless, in custom
scenarios you may want to be notified about problems as soon as possible. Set the switch to true and get a value that you can decipher using the information supplied here.
How your Office extension loads into an Office application
Registry keys
Any Office solution - a COM add-in, Excel add-in, RTD server, or smart tag - must be installed and registered because Office looks
for extensions in the registry. In other words, to get your add-in to work, 1) add-in files must be installed to a location accessible
by the add-in users and 2) registry keys must be created that specify which Office application will load the add-in and which PC users
may use the add-in. The necessity to create registry keys is the reason why you cannot use XCOPY deployment for a COM
add-in, Excel XLL add-in, RTD server, or Smart tag.
Although Add-in Express creates all registry keys for you, you might need to find the keys when debugging your add-ins. The main
intention of this section is to provide you with information on this.
Locating COM add-ins in the registry
Depending on the value of the RegisterForAllUsers property of the add-in module, the main registry entry of a COM add-in is located at:
{HKLM or HKCU}\Software\Microsoft\Office\{host}\AddIns\{your add-in ProgID}
If the RegisterForAllUsers property of the add-in module is true, the add-in is registered in HKEY_LOCAL_MACHINE, otherwise the key
is located in HKEY_CURRENT_USER.
Pay attention to the LoadBehavior value defined in this key; typically, it is 3. If LoadBehavior is 2 when your run your add-in,
this may be an indication of an unhandled exception at add-in startup.
The registry key above notifies the corresponding Office application that there's an add-in to load. FYI, the COM add-in is a COM
object registered in
HKEY_CLASSES_ROOT\CLSID\{Add-in Express Project GUID}
Locating Excel UDF add-ins in the registry
Registering a UDF adds a value to the following key:
HKEY_CURRENT_USER\Software\Microsoft\Office\{Office version}.0\Excel\Options
The value name is OPEN or OPEN{n} where n is 1, if another UDF is registered, 2 - if there are two other XLLs registered, etc.
The value contains a string, which is constructed in the following way:
str = "/R " + "" + pathToTheDll + ""
Add-in Express Loader
All Office applications are unmanaged while all Add-in Express based add-ins are managed class libraries. Therefore,
there must be some software located between Office applications and your add-ins. Otherwise, Office applications will not
know of your .NET add-ins and other Office extensions. That software is called a shim. Shims are unmanaged DLLs that isolate your
add-ins in a separate application domain.
When you install your add-in, the registry settings for the add-in will point to the shim. And the shim will be the first DLL
examined by the host application when it starts loading your add-in or smart tag.
Add-in Express provides the shim of its own, called Add-in Express loader. The loader (adxloader.dll, adxloader64.dll) is a
compiled shim not bound to any certain Add-in Express project. Instead, the loader uses the adxloader.dll.manifest file containing a
list of .NET assemblies that must be registered. The loader's files (adxloader.dll, adxloader64.dll and adxloader.dll.manifest) must
always be located in the Loader subdirectory of the Add-in Express project folder. When a project is being rebuilt or registered, the
loader files are copied to the project's output directory. You can sign the loader with a digital signature and, in this way, create
trusted COM extensions for Office.
Add-in Express loader manifest
The manifest (adxloader.dll.manifest) is the source of configuration information for the loader. Below, you see the content of a sample
manifest file.
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<assemblyIdentity name="MyAddin14, PublicKeyToken=f9f39773da5c568a" />
<loaderSettings generateLogFile="true" shadowCopyEnabled="true"
privileges="user"> configFileName="app.config"
<logFileLocation>C:\MyLog.txt</logFileLocation>
</loaderSettings>
</configuration>
The manifest file allows generating the log file containing useful information about errors on the add-in loading stage.
The default location of the log file is {user profile}\Documents\Add-in Express\adxloader.log. You can change the location using
the logFileLocation node; relative paths are also acceptable. The manifest file allows you to disable the Shadow Copy feature of
the Add-in Express loader, which is enabled by default (see
Deploying - shadow copy). The privileges attribute accepts the "user" string indicating that the Add-in Express based setup
projects can be run with non-administrator privileges. Please, note, any other value will require administrator privileges to
install your project. You should be aware that the value of this attribute is controlled by the RegisterForAllUsers property
value of add-in and RTD modules. If RegisterForAllUsers
is True and privileges="user", a standard user running the installer will be unable to install your Office extension.
If RegisterForAllUsers is False and privileges="administrator", your Office extension will be installed for
the administrator only.
In addition, you can run regsvr32 against the adxloader.dll. If a correct manifest file is located in the same folder,
this will register all Add-in Express projects listed in the loader manifest.
How the loader works
Consider an ideal case, when all required files are supplied, registry keys are created and permissions are correct.
If so, when the Office application discovers an appropriate registry key (see Locating COM add-ins in
the registry),
it finds the loader's DLL, loads it and calls a method implemented by the loader in accordance with COM rules.
The loader initializes CLR (Common Language Runtime), reads the manifest, creates an AppDomain, loads your assembly
into the domain, and creates an instance of your add-in module (this runs the constructor of the module). Then the loader
generates the AddinInitialize and AddinStartupComplete events of the module, connects the module to events of the host
application and waits for the event that specifies the end of the job. When such an event occurs, the loader disconnects
the module from the host application events, and generates the AddinBeginShutdown and AddinFinalize events of the module
(see also Custom actions when your COM add-in is uninstalled).
You can find some background info in Insight of Add-in Express Loader.
Loader's log
If the manifest requires creating a log file (see the generateLogFile attribute at Add-in Express
Loader manifest), the log file is created in the location specified by the manifest or in {Documents}\Add-in Express\adxloader.log
(default). Note that the log is re-created when you install/uninstall the add-in and when the Office application loads it.
Back to Add-in Express for Office and .NET homepage |