M-Files UI Extensibility Framework
Developer's Guide
Contents
2.10 Module Isolation and Behavior
3. UI Extensibility Application Development
3.1.1 Application Development
Folder
3.1.2 Writing the Application Definition File
3.1.3 Writing and Testing the Application Source Files
3.1.4 Deploying Applications to Vault Users
3.1.5 Application Security and Preapproving Applications
3.1.7 Installing Local Applications
3.2 Getting Started with Events
3.2.2 Common Events and the Object Life Cycle
3.2.3 Starting Modules and Receiving First Events
3.2.4 Registering Event Listeners
The M-Files UI Extensibility Framework is a collection
of features, APIs, program execution environments and libraries that allow external add-ins (M-Files
Applications) to customize the behavior of the M-Files Client. With these applications, the
M-Files experience can be improved to better match specific business areas and
needs.
This document explains various techniques and approaches to customize
the M-Files Client. The reader
is expected to have general knowledge and skills in software
development and programming, preferably with JScript, HTML and ActiveX
technologies.
M-Files Applications are packages that can be installed in
M-Files that contain program logic which can react to actions and
alter or enhance functionality within the M-Files client. The M-Files platform triggers the
application's logic through an event handling mechanism, and once
triggered, may interact with M-Files via provided interfaces.
A single application consists of multiple modules
which contain the actual program code. Different modules run in different
M-Files components, and they have different purposes and behaviors. For
example, code that runs in the M-Files Shell Window (the part of M-Files client
that runs inside Windows Explorer) would be placed in a dedicated ShellUI module, and the application code
that runs in M-Files client service and listens to vault actions would be located in a VaultCore module.
Physically, each application module is implemented as one or more JScript files. The
JScript code has access to interfaces that allow it to interact with the
M-Files platform.
Each type of module receives
access to different
interfaces. Applications
only need
to implement logic in relevant modules, so small applications
may implement logic in only one module.
Application modules that interface with M-Files UI
components can present their own user interface with dashboard windows.
Dashboards are dialogs or integrated windows whose content is defined
within HTML
files. These HTML files may
contain JScript for
extending logic, and can also access M-Files platform interfaces in a
manner similar to application modules.
The picture
below illustrates how the M-Files Application can access different M-Files core
components through UI Extensibility Framework interfaces.
M-Files Application and surrounding infrastructure.
ShellUI
modules are always bound to M-Files Shell component. They are initialized when
a user navigates to the M-Files drive within Windows Explorer, or from a common
dialog inside a Windows Application. Each shell window or common dialog runs
its own instance of a ShellUI module. Their logic is
executed with the rights of the current Windows user.
The
lifetime of a ShellUI module and its main object
follows the lifetime of a single M-Files Shell window (i.e. the Windows
Explorer window, or a common dialog). The lifetime of other objects within the ShellUI module (like the ShellFrame
object that represents the content of ShellUI window)
can be shorter.
Tip:
Refer to
Fast browsing in the User Interface Extensibility Framework for information on
how you can optimize the way the M-Files Desktop client builds and renders the client
interface.
The program
logic of a ShellUI module can access the user
interface of the M-Files Shell, adding custom commands and logic to the Tasks
Pane, or launching custom user interfaces as dashboards inside pop-up dialogs
or integrated windows. Integrated dashboards can be shown in the place of the
shell listing view, the right side previewer pane, or the bottom properties
pane. ShellUI modules are also able to send
synchronous communication messages to VaultUI and VaultCore modules.
User interface customization possibilities with ShellUI module.
VaultUI modules
are run within the MFStatus.exe process. There is one instance of the
MFStatus.exe process per Windows session. The lifetime of a VaultUI
module and its main class follows a Vault connection within a Windows session;
the module is started when the user logs in to a Vault, and is stopped when the
user logs out. The program logic is executed as the current Windows user.
VaultUI
modules can display their own UI by launching a dashboard in a popup window.
They can work in co-operation with VaultCore modules,
and can access the same interfaces. This allows VaultUI
modules to react to various document and vault operations, validate them, and
change their parameters as needed. For example, a VaultCore
module could be used to validate object properties, block check-in requests if
the object metadata is incomplete, and trace vault usage.
VaultCore
modules run within the MFClient.exe service. The workstation shares the same
MFClient.exe process with all logged in user sessions; however each M-Files
user has its own dedicated VaultCore module instance.
The lifetime of the VaultCore module and its main
class follows the M-Files session; the module is started when the user logs in
document vault, and is stopped when the user logs out from the vault. The
program logic is executed as a Windows system user and it has quite
unrestricted access to the system resources.
Note that VaultCore object exists for each logged in M-Files user,
and an associated VaultEntry object exists for each
logged in M-Files user per windows session. It is relatively rare, but entirely
possible, that a Windows user has more than one Windows session, and two or
more VaultEntry objects share a single VaultCore object.
Application
running in VaultCore module may implement connections
or co-operation with other system services, or access system resources that are
not allowed for normal user. For example, the application must use VaultCore module to write a file under Program Files
folder, or to install software components to the computer.
Normally
the VaultCore cannot access user interface, however
it can access the same interfaces as the VaultUI
modules, and can therefore display a dashboard in some or all associated
Windows sessions. These dashboards are executed with the rights of the
currently logged in Windows user.
Application
modules can show custom UIs via dashboards. A dashboard is a popup window or a
window integrated in Windows Shell, with HTML content and ability execute its
own JScript. Dashboards are not independent modules, but are launched by them.
Dashboards are able to access objects from their owner module, and an owner
module can exchange data with their dashboards.
The
lifetime of the dashboard follows the lifetime of the dashboard window, which
in turn is affected by the owner window. All dashboard logic is executed as the
current Windows user.
Dashboards
are run with Internet Explorer browser component integrated in M-Files window.
The hosted browser behavior is altered to work favorably with M-Files applications, therefore the dashboard content should be
designed for M-Files Application use only. Using generic or non-owned content
(from the internet or a non-local source) is discouraged, and not allowed by
default. Developers must keep in mind that dashboard content gets executed on
the local computer, and the code receives access to the document vault with the
rights current M-Files user.
Applications
can access the underlying M-Files core platform through interface objects. The
primary interface, determined by module type, is passed to a module when it's
activated (e.g. when the user logs in or opens a new shell window). The
availability of subsequent objects is announced via event notifications, so
applications can access other relevant objects by tracking events of the main
object. Each interface object is connected to a core M-Files object, and can be
used to control M-Files behavior as long as the interface object stays
connected.
The picture
below illustrates the main objects of each application module. The ShellUI objects offer the main UI customization
functionality, whereas the VaultUI and VaultCore objects offer validation and reaction
capabilities for document and vault actions. Dashboards can be launched from
UI-aware objects, such as ShellUI, ShellFrame, and VaultUI.
Main objects for each M-Files Application module.
Application
logic must be implemented with the JScript scripting language. However,
depending on the context, the environment in which the scripts are run can vary
slightly.
JScript
within application modules is executed in the Windows Scripting Host (WSH)
environment, whereas the JScript contained in dashboards (embedded in HTML
code) is executed within Internet Explorer (web browser). The JScript engine
version and some language details are different between these two environments,
and JScript is actually referred to as JavaScript in Internet Explorer 9
and later.
In general,
JScript executed within WSH has the same access to the system resources as the
executing context, whereas Internet Explorer is more restricted, and may limit
access to resources outside of the browser environment. However, because
Dashboards can access their parent modules, the dashboards can always delegate
restricted actions for them to run on Windows Scripting Host.
Other
language details may vary between Internet Explorer versions, and M-Files
application developers should be aware of the limitations and variations
between Internet Explorer versions; similar to how web developers must be aware
of web browser compatibility issues. M-Files application dashboards require
Internet Explorer 8 or newer.
The M-Files
platform interfaces and the M-Files APIs are implemented as ActiveX objects.
These objects are passed to the JScript/JavaScript environments and can be
accessed from the scripts. However, ActiveX and JScript/JavaScript objects have
different characteristics, and cannot always be treated the same. For example,
ActiveX objects cannot be dynamically extended like JScript/JavaScript, their
properties do not enumerate, and they are missing standard
JScript/JavaScript functions and properties like constructor, and toString().
Applications
consist of a definition file, module files, dashboard files, and supporting
dashboard content files (like JavaScript libraries, CSS, images, etc.). The
application definition file is a project file that links to all the module and dashboard
files, and defines the properties of the application.
The
application definition can include application name, version, description,
copyright, publisher, M-Files version dependency requirement, and other
details. It can also specify whether the application is enabled by default, or
whether the user must deliberately activate the application. The application
definition file can also set the application to be compulsory, so that
if the application is installed, M-Files Vaults cannot be used without it.
M-Files
applications can be installed inside vaults, where they are automatically
distributed to all users who log in. Alternatively, the application can be installed
locally to a user's computer, to be applied in all document vaults, or in a
specific document vault only.
M-Files
applications are run on local computers, in the context of the current Windows
or system user. Moreover, the application gets access to the document vault
acting as a current M-Files user. Approval from the current user or local
computer administrator is required for executing an M-Files Application – just
as it is needed for locally installed programs. Document vault administrators
may not have administrative permissions to local computers, and therefore
vault-installed applications cannot be judged as "safe" by default.
M-Files
applications that are uploaded to a document vault are downloaded to local
computers the next time the user logs in to the vault. At this time, the user
is prompted whether they allow the applications to be run on the local
computer.
Note:
If the user is not a local administrator, they can only accept applications
that do not contain VaultCore modules because VaultCore modules are run as a system user. If the user has
administrative permissions, they can allow any application to be downloaded
from the document vault. Once an application with a VaultCore
module has the permission to run on local computer, the permission is granted
for all users. Therefore, the administrator can allow the application to run on
behalf of non-administrator users.
Note:
In versions older than M-Files 2018, the permission to execute the application
is granted for a single application version only. If an application is changed
in the document vault, the application footprint changes and the permission to
run the application is prompted again. In M-Files 2018 and later, the
permission is granted for the current and all future versions of the
application.
In M-Files
2018 and later, the default behavior is that approval to run all the
vault-specific applications is requested in a single prompt. In versions older
than M-Files 2018, the approval is requested for each application. If you wish
to use the app-by-app approval mode in M-Files 2018 and later, you can do so by
adding the following registry key to the Windows registry of the client
computer:
Key name: HKEY_LOCAL_MACHINE\Software\Motive\<version>\Client\MFClient
Value name: ApproveEachApplicationSeparately
Value type: REG_DWORD
Value data: 0 (setting disabled)
or 1 (setting enabled, default
value)
Disabling the acceptance
prompt
In order to
avoid the acceptance prompt, a preshared application
key can be distributed to workstations. The key must be installed in the system
registry, under HKEY_LOCAL_MACHINE (see chapter 3.1.5). Only administrative users can
modify these settings.
Applications
installed directly on the local computer
M-Files applications that are installed directly on a local computer are executed without any validations or prompts. Applications are installed by placing them within the M-Files installation folder, under the Program Files folder. Administrative permissions are required to modify these files.
If multiple
applications are installed, they live in isolated object models in a sense that
one application cannot access the interface instances that belong to another
application. Therefore a single application cannot interfere with events or
custom commands registered by another application.
However,
applications can race in the use of shared resources, like the UI
customization, dashboard placements and M-Files command state changes. In that
sense a degree of good will and humble behavior is expected from applications.
It is
easiest to develop a new application directly on a local computer. The
applications are placed under the Client\Apps folder of the M-Files
version installation folder. Locally installed vault-specific applications are
stored in <vault guid>\sysapps
subfolder. It is recommended to develop the application with dedicated
development vault, to avoid accidents in the production vault.
Though the sysapps folder can be used as a temporary
development location for applications, it is also the permanent application
storage for locally installed applications.
Start by
creating a folder for your application. The folder name can be chosen freely.
Here we use the 'Sample App' subfolder for an application that is applied in
single document (guid:
CF7DFF87-8CA7-4A8C-971C-3F62C1489B34) vault; so full path is now ' C:\Program
Files\M-Files\9.0.3369.0\Client\Apps\{CF7DFF87-8CA7-4A8C-971C-3F62C1489B34}\sysapps\Sample
App'. The picture below shows a simple M-Files Application that consists of
two files.
Simple M-Files Application consisting of two files, installed for single vault on local computer.
Create the
application definition file, appdef.xml,
and place it to the application folder.
You can
create two different types of applications: client applications and server
applications. The type of the application is specified as a "type"
attribute in the "application" element. For UI Extensibility
applications, the value is "client-application".
A simple
application definition could look like this:
<?xml version="1.0"
encoding="utf-8"?>
<application type="client-application" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.m-files.com/schemas/appdef-client-v3.xsd">
<guid>7BE49057-5EC7-4FC8-9302-32C0BAA3737E</guid>
<name>Sample App</name>
<description>Sample Application</description>
<platforms>
<platform>Desktop</platform>
<platform>Web</platform>
</platforms>
<modules>
<module environment="shellui">
<file>main.js</file>
</module>
</modules>
</application>
Note:
Ensure that the actual encoding of the file matches with the XML-defined
encoding. In other words, save the file in UTF-8 format.
For a
client application, the application definition file must contain information as
follows:
· Application type, specified with the "type" attribute in the "application" element. For a client application, the value is "client-application".
o For a server application, the value is "server-application".
· XML schema location, specified with the "noNamespaceSchemaLocation" attribute in the "application" element. For a client application, the value is "http://www.m-files.com/schemas/appdef-client-v3.xsd".
o Applications with this schema version are only loaded in M-Files Desktop version 2015.2 or newer.
§ With prior M-Files versions, the older schema can be used: "http://www.m-files.com/schemas/appdef.xsd". Client apps that use the older schema are assumed to be for M‑Files Desktop only and will thus not be loaded in M-Files Web.
o For a server application, the value is "http://www.m-files.com/schemas/appdef-server-v1.xsd".
· Application identifier (GUID), which is the globally unique identifier for the application. It should be ensured that no two applications have the same GUID. Generate the GUID with a GUID generator (like guidgen.exe from Microsoft), or use public internet service like http://www.guidgen.com/ or http://createguid.com/.
· Application name. The name is displayed in the user interface, and it should be descriptive enough to allow user to identify the application.
· Platforms, defined with the "platform" elements placed under the "platforms" element. The application is only loaded for the defined platforms. The currently available platforms are "Desktop" and "Web".
o The "platforms" element must contain at least one "platform" element. The names are case-insensitive. Unknown platform names are ignored.
o If the "platforms" element has not been included or if the older schema version is used, M-Files assumes that the application is to be loaded for M-Files Desktop only.
· Application source code for application modules. At least one module with at least one source file must be specified. The environment of the module specifies where the module is executed. The possible values are shellui, vaultui and vaultcore.
o Modules with the vaultui or the vaultcore environment are not loaded in M-Files Web.
Other common
definitions are:
· Application version. This is informative version of the application. It has no functional meaning, but it can be displayed for the M-Files user.
· Application description. This information is displayed for the user. If the application will be installed to the document vault, and the application pre-shared security key is not used, the description is important because users will see the description of the application when they are prompted to allow or disallow the application execution.
· Application publisher. This information is also displayed with the application security prompt, and should describe the legal author of the application. The application publisher is essential if the application is equipped with publisher-specific license key to enable certain platform features.
· Required M-Files version. If your application utilizes features in recent M-Files version, you can ensure that the application is run only if the underlying M-Files is new enough.
· Application optionality. By default applications are optional, so that user may disable (or disallow) the application, and still use the document vault. If the application is not optional, the user cannot disable the application, and the document vault cannot be accessed if the application is disallowed or it cannot be executed for other reasons (too old M-Files version etc.).
· Enabled-by-default setting, which specifies whether the application becomes automatically enabled or disabled. The default value is 'automatically enabled'. One may wish to change this if the application implements a functionality that is used by few users only, so that application does not disturb the majority of the users.
Create and
edit the application source files in your local application folder, and modify
the appdef.xml respectively to include new files. See sample applications in
this documentation for an example of the actual application implementation.
The
application is run automatically when the user logs in to M-Files next time.
When the application is changed and developed further, the user should log out
and re-login to the document vault in order to ensure that the application is
refreshed properly.
After the
application is proven to be functional in the local system, it can be deployed
to other vault users. In order to upload the application to the vault, it must
be packed to a ZIP file first.
Convert the
whole application folder to a ZIP file, as the picture below illustrates.
Note:
If you are using data compression software, such as 7-Zip or WinZip, it is
recommended to use the default settings when creating the archive. For
instance, using the Deflate64
compression method may cause issues during application installation.
Then change
the extension to MFAPPX and use M-Files Admin to install the MFAPPX file to the
document vault: Right-click the document vault and choose 'Applications'. Click
'Install' and choose the appropriate MFAPPX file to install. The application
package is now installed to the document vault and will be distributed for all
users who log in to the vault.
Single application installed to a document vault.
Important: The document vault now contains the same application
you developed locally. The same application must not be loaded twice into
M-Files, so remove the local copy under the sysapps folder before logging in to
the document vault. If you are still developing your application, you can
temporarily disable your local applications by renaming the sysapps folder, or renaming the
appdef.xml.
When the
user logs in to the document vault and a new vault application is ready to be
taken into use, a security dialog prompts the user to allow or disallow the
application to be used. See Security for more information.
The application security dialog.
Note:
In M-Files 2018 and later, the default behavior is
that approval to run all the vault-specific applications is requested in a
single prompt, whereas in versions older than M-Files 2018, the approval is
requested for each application.
The
administrator may wish to preapprove all or selected vault applications in
order to avoid user confusion. This can be achieved by distributing a registry
key that specifies the applications to be preapproved.
In large installations,
administrators may wish to distribute these registry settings via Active
Directory Group Policies or similar registry setting delivery mechanisms.
Preapproving All
Vault Applications
If you are
using M-Files 2018 or later, you can preapprove all vault applications by
making the following registry modification on all the M-Files client computers
on which you want all vault application to be preapproved:
Key |
HKEY_LOCAL_MACHINE\SOFTWARE\Motive\M-Files\<version>\Client\MFClient\ApplicationAccess\<vault
GUID> |
Value name |
allapps |
Value type |
REG_SZ |
Description |
This
setting enables all vault applications to be preapproved on the selected
client computer. |
Value data |
any |
You can copy the vault GUID from the Document Vault Properties dialog in M-Files Admin.
Preapproving Specific
Vault Applications
To preapprove a specific vault application, make the following registry modification on all the M-Files client computers on which you want the vault application to be preapproved:
Key |
HKEY_LOCAL_MACHINE\SOFTWARE\Motive\M-Files\<version>\Client\MFClient\ApplicationAccess\<vault
GUID> |
Value name |
{<application
GUID>} |
Value type |
REG_SZ |
Description |
The
identifier the preapproved application. Note that the GUID must be enclosed
in curly brackets. |
Valid values |
<application
checksum> any |
You can copy the vault GUID from the Document Vault Properties dialog in M-Files Admin, the application GUID appears in the application definition file, and the checksum can be seen on the last line of the application security dialog.
The picture below shows an example how the
configuration would look in Registry Editor:
Pre-shared application approval key as seen in Registry Editor.
Users can
manually enable or disable applications, unless they are defined to be
non-optional (in appdef.xml file). The applications can be enabled or disabled
with Windows Explorer menu command Settings à Applications. If the application is defined to be
disabled by default, the user must manually enable the application with this
functionality. The change takes place after the next login.
The
application files are placed under Client\Apps folder structure, in
similar way that was used to develop the application, see Application
Development Folder. If the application is installed to be common for all
document vaults, it can be placed to sysapps
subfolder (i.e. without the vault guid in the path).
The
application activation mechanism and object model and relations are primarily
event-driven. Objects' internal state changes are also announced with event
notifications. Applications register event listeners and provide callback
functions that are run whenever the corresponding event occurs. All event
listeners are registered via the IEvents
interface. All objects that are able to send events provide access to this
interface.
In the case
of a module's main object's 'New' event, the application does not need
to register a listener, but rather implement a function that is named with the
format OnNew<ModuleType>.
This function will then behave as the initial entry point and main function for
the application. For example, a ShellUI module would
declare a function with the name OnNewShellUI(shellUI) to act as its entry point.
Note: In
this section, the terms object and state refer to the JScript
language features, not to M-Files objects and their properties.
Certain
life cycle related events are common for all objects. When a new object becomes
available a New<ObjectType> event
is sent to listeners of the parent/owner object and the new object is passed as
an event parameter. If the created object is the main object of the module, the
application infrastructure sends the first notification.
Next, the
object sends a 'Started' event, and when the object's lifecycle is close
to terminate, it sends a 'Stop' event. These events are sent by the
object itself. The picture below describes all internal lifecycle states for
the object.
Object life cycle states.
Object
lifecycle events and states explained:
1. A new object is created and it enters the Created state. A New<ObjectType> event (e.g. NewShellFrame) is sent to listeners of the parent/owner object. The new object must not be used yet, but event handlers can be registered for the new object at this point. An attempt to access the object for other purposes causes an error 'Object is not ready'.
2. An object enters the Started state, and the Started event is sent to the event listeners of the object. Note: in order to receive the started event, the application had to register the event listener when the New<ObjectType> event fired. The application may now start to use the object.
3. An object approaches the end of its life, and the Stop event is sent to the event listeners of the object. After the stop is announced, the object must not be accessed. An attempt to access the object after this point causes an error 'Object is not ready'.
4. The object gets decommissioned and it is detached from the underlying model. An attempt to access the object that is in this state leads to an error 'Object is decommissioned'.
5. The object is finally destroyed when nothing refers to it.
The entry
point for each application module is actually an event handler, and the module
is started by triggering the event. In order to receive the first event, a
correctly named method must be implemented in the module code. The method
name is in format OnNew<ModuleType>, and it receives the module main object
as a parameter.
Entry
point of ShellUI module:
function OnNewShellUI( shellUI )
{
// This is the start point of ShellUI module.
}
Entry
point of VaultUI module:
function OnNewVaultUI( vaultUI )
{
// This is the start point of VaultUI module.
}
Entry
point of VaultCore module:
function OnNewVaultCore( vaultCore )
{
// This is the start point of VaultCore module.
}
The
application infrastructure offers three different methods to register event
listeners. The event registration method can be chosen freely, and can be seen
as a matter of preference. Some event registration methods provide a chance to
unregister event handlers as well. Unregistering an event listener is optional,
and is not required for cleaning up resources.
JScript
offers an easy approach to event handling via function closures. The use of
closures makes immediate event handlers simple to implement, however the users
of imperative programming languages may wish to get familiar with the closure
approach first.
Events can
be registered directly with the IEvents interface
registration methods. The example below shows how a new event handler is passed
as a function closure to the registration method. The unnamed function closure
will be called when the event is triggered.
{
// Register new event handler.
// Here the shellUI variable refers to IShellUI object.
var
handle = shellUI.Events.Register(
Event_NewShellFrame,
function( shellFrame ) {
// Event handler code goes here.
}
);
}
More than
one event handler can be registered to listen to the same event on a single
object. Registrations can be removed by unregistering them.
Direct
function closure assignment can be used as shortcut method for registering
listener. Note that the event property name changes slightly when compared with
the corresponding Event enumerator name: the Event_
prefix gets replaced with On prefix. I.e. enumerator value Event_NewShellFrame turns to OnNewShellFrame
property.
{
// Register new event handler.
// Here the shellUI variable refers to IShellUI object.
shellUI.Events.OnNewShellFrame = function( shellFrame ) {
// Event handler code goes here.
}
}
With this
registration method, a single object can have just one listener per event. Any
previously registered handlers are unregistered. All registrations can be
removed by assigning a null value.
For new
objects, event handlers can be registered by providing an object of function
closures as a return value from New<ObjectType>
event handler method. The following code illustrates this approach.
function OnNewShellUI( shellUI )
{
// Return event handlers as a closure.
return {
OnStarted: function() {
// Handle the started event of ShellUI.
},
OnNewShellFrame: function( shellFrame ) {
// Handle the OnNewShellFrame event of ShellUI.
return {
OnStarted: function() {
// Handle the started event of ShellFrame.
}
};
}
};
}
The
function can return multiple handlers at once. Note also that the OnNewShellFrame handler uses same approach to register yet
further events handlers for ShellFrame object.
The event
handlers within the returned closures must be named with same convention as the
function closure assignment; the Event_ prefix gets replaced with On prefix.
Please see User Interface Extensibility Framework Samples in M-Files Developer Portal.