Sometimes it is necessary to restrict which of the add-in functions in an XLL are made available to users. The XLL+ toolkit contains a set of classes - in header file xlpfunctionfilter.h - which offer various policies for applying such restrictions.
There are two very different strategies for filtering the functions made available to the user:
The use of a run-time configuration file is less secure, since this method of control can be altered by users; if you want to keep the function filter under the control of the developer, then you should apply the restriction to the source code at development time, by using the FunctionFilterOptIn or FunctionFilterOptOut function extensions.
To use the development-time approach you will need to load the extension file
FunctionFilter.xpe
which is located in the extensions directory of your XLL+ installation.
See Loading an extension file
for instructions.
Two different filtering policies are offered, opt-in and opt-out.
To apply filtering at development time, ensure that the extension file FunctionFilter.xpe is loaded (see above). This will add two new boolean properties to the "Miscellaneous" section of the add-in's proprties in the Properties window: FunctionFilterOptIn and FunctionFilterOptOut.
An opt-in policy looks at the FunctionFilterOptIn property and ignores FunctionFilterOptOut. An opt-out policy looks at the FunctionFilterOptOut property and ignores FunctionFilterOptIn.
In an opt-in policy, to ensure that a function is published, set its FunctionFilterOptIn property to True. Only these functions will be included.
In an opt-out policy, to ensure that a function is suppressed, set its FunctionFilterOptOut property to True. These functions will be included and all other functions will be included.
You need to apply the filter just before function registration takes place, and two helper classes are available to achieve this. Each is a specialized event handler for the XlRegisterFunctions event.
To apply an opt-in policy, declare a global instance of CXllFunctionFilterEventHandlerOptIn:
CXllFunctionFilterEventHandlerOptIn theFunctionFilter;
During the XlRegisterFunctions event, the object's Update method will be called. As a result, an opt-in policy will be appied to the global instance of the function filter (CXllFunctionFilter), using the following code:
CXllFunctionFilter::Apply(*CXllApp::Instance(), true);
You can find a full example of this policy in the PubDevIn sample application.
To apply an opt-out policy, declare a global instance of CXllFunctionFilterEventHandlerOptOut:
CXllFunctionFilterEventHandlerOptOut theFunctionFilter;
During the XlRegisterFunctions event, the object's Update method will be called. As a result, an opt-in policy will be appied to the global instance of the function filter (CXllFunctionFilter), using the following code:
CXllFunctionFilter::Apply(*CXllApp::Instance(), false);
You can find a full example of this policy in the PubDevOut sample application.
The event handler class CXllFunctionFilterEventHandlerFromFile can be used to implement a run-time filter.
This event observer should be declared at global scope as a static instance, as below:
CXllFunctionFilterEventHandlerFromFile theFunctionFilter(CXllFunctionFilterLoader::EXPLICIT);
During the XlRegisterFunctions event, the object's Update method will be called. As a result, the specified configuration file will be located, loaded and parsed and then applied to the function filter registry, CXllFunctionFilter. The actual work of loading and parsing the file is performed by CXllFunctionFilterLoader.
The configuration file will be parsed in one of two ways.
If the loadType specified in the constructor is CXllFunctionFilterLoader::OPT_IN or CXllFunctionFilterLoader::OPT_OUT then the file should contain a list of function names, each on a single line. Blank lines are ignored.
If the loadType is CXllFunctionFilterLoader::EXPLICIT then the file should contain a list of function names and actions, each on a single line. Each line should contain a pair of items, separated by white space: first a function name, and second a boolean value, which can be 1, 0, true or false. If the boolean value is 1 or true, then the function in that line is published. If the boolean value is 0 or false, then the function in that line is suppressed. Blank lines are ignored.
You can find a full example of this approach in the PublishRT sample application.
The developer will almost certainly need to carry on testing and developing the add-in functions which are not being delivered to the user. To facilitate this, it is usual to wrap the filtering code in an #ifdef directive, e.g.:
#ifndef _DEBUG CXllFunctionFilterEventHandlerOptOut theFunctionFilter; #endif