Author Archives: Peter Grew

Calling a REST service from JScript

In this post we will take a look how to consume a REST service from the Smart Office JScript code. Related blog posts that focus on M3 APIs can be found at the following links.
Calling M3 APIs in JScript
Background workers in Smart Office scripts

Setting up the REST Data Service

Let’s start with the script code. It’s necessary to import the following three assemblies to gain access to the necessary classes and interfaces.

import MForms;
import Mango.Core.Services;
import System.ComponentModel;

The first step is to get a handle to the REST data service from the DataServiceManager.

var svc : IDataService = DataServiceManager.Current.Get("REST");

The REST data service is configured with a parameter set put in a DataItemCollection, so we start by setting the service address. I’m going to use a fake online REST service for the example to demonstrate how it’s done.

var params = new DataItemCollection();
params.Add(new DataItem(RestDataService.KeyBaseAddress, ""));

The available parameters can be found in the RestDataService class, the name starting with Key. It’s necessary to set KeyBaseAddress for the REST requests. KeyUri can contain a relative URI that is combined with KeyBaseAddress. Both parameters support variable substitution using names within curly braces {}. For example:

params.Add(new DataItem(RestDataService.KeyUri, "/users/{userId}"));
params.Add(new DataItem("userId", e.Argument));

or like this. Both will will result in the same endpoint URL.

params.Add(new DataItem(RestDataService.KeyUri, "/users/" + e.Argument));

If the userId variable equals to 7 the combined parameters results in the REST URL:

The service request and response type headers must be specified unless the default values are required. The default values are the following two lines, that can be added for clarity but also omitted.

params.Add(new DataItem(RestDataService.KeyAcceptHeader, RestDataService.ContentTypeApplicationXml));
params.Add(new DataItem(RestDataService.KeyOutputType, RestDataService.OutputTypeDataItem));


Use the Background Worker to Prevent UI Freeze

Now we’re almost done, but the data service require that it’s running on a background thread. If not, it will throw an Exception to make you aware of that. This is done to prevent potential UI freeze and annoyed users. Let’s have a look at a simple solution by using the BackgroundWorker class.

var worker = new BackgroundWorker();
// Set the function that performs the service call

// Set the function that performs update and clean-up after the call is done        

// Launch the service call and provide start parameters

The OnDoWork function will execute on the background  thread and call the data service. When done the OnRunWorkerCompleted function will execute on the UI thread to handle the response and do clean up after the call. Please, always handle Exceptions in your code!

public function OnDoWork(sender : Object, e : DoWorkEventArgs) 
       var serviceParameters = e.Argument;
       // The data service call is done here (this is the background thread)
       e.Result = serverResponse
       // Exceptions must be handled
public function OnRunWorkerCompleted(sender : Object, e : RunWorkerCompletedEventArgs) 
       var worker = sender;
       var serviceResponse = e.Result;
       // The worker has completed its work (this is the UI thread) 
        // Exceptions must be handled 

The Full Script Example

Here is the full script example for you to test in the ISO Script Tool mforms://jscript:

import MForms;
import Mango.Core.Services;
import System.ComponentModel;

package MForms.JScript 
   class RESTDemo 
      var debug;
      var controller;     
      public function Init(element: Object, args: Object, controller : Object, debug : Object) 
         this.debug = debug;
         this.controller = controller;        
         debug.WriteLine("Script Initializing.");            
      public function DoRestCallOnBackgroundWorker()
         debug.WriteLine("The REST service call is made on a background worker");          
         var worker = new BackgroundWorker();
         var userId = 7;         
      public function OnDoWork(sender : Object, e : DoWorkEventArgs) 
            debug.WriteLine("OnDoWork started");
            debug.WriteLine("Calling a REST service getting DataItem response data");

            var svc : IDataService = DataServiceManager.Current.Get("REST");
            var params = new DataItemCollection();
            params.Add(new DataItem(RestDataService.KeyBaseAddress, ""));             
            params.Add(new DataItem(RestDataService.KeyUri, "users/{userId}"));                          
            params.Add(new DataItem(RestDataService.KeyAcceptHeader, RestDataService.ContentTypeTextXml)); // default value                                  
            params.Add(new DataItem(RestDataService.KeyOutputType, RestDataService.OutputTypeDataItem));   // default value
            params.Add(new DataItem("userId", e.Argument)); 
            var dataRequest = new DataRequest(params);
            dataRequest.OperationType = "GET";
            var dataResponse = svc.Execute(dataRequest.OperationType, dataRequest);
            e.Result = dataResponse.Data;            
            debug.WriteLine("OnDoWork done");    
           debug.WriteLine("Exception: " + ex.Message);
           e.Result = null;
      public function OnRunWorkerCompleted(sender : Object, e : RunWorkerCompletedEventArgs) 
            debug.WriteLine("OnRunWorkerCompleted running on UI thread");    
            var worker = sender; 
            if(e.Error != null) 
               debug.WriteLine("Error: " + e.Error.Message); 
            debug.WriteLine("Fetched user data for:");           
            var dataItem = e.Result;
            debug.WriteLine(dataItem["name"] + " (" + dataItem["username"] + ")" + " Phone " + dataItem["phone"]);  
            debug.WriteLine("Exception: " + ex.Message);


Debug output when running the sample in the Script Tool.

Script Initializing.
The REST service call is made on a background worker
OnDoWork started
Calling a REST service getting DataItem response data
OnDoWork done
OnRunWorkerCompleted running on UI thread
Fetched user data for:
Kurtis Weissnat (Elwyn.Skiles) Phone 210.067.6132

The Sound of a Silent Install

The conventional way to install Infor Smart Office on client machines is to use Microsoft ClickOnce network deployment to get an isolated, secure, self-updating application that can be installed and run with minimal user interaction.

However, if you want to run Infor Smart Office client in a virtualized desktop environment, the Microsoft ClickOnce deployment is not recommended. Instead, install the Infor Smart Office client using the Windows installer (InforSmartOffice.msi) bundled in the software package.

The Windows installer launch a sequence of user interface screens that lead the user through the installation process and gather necessary information. In this case the user needs to enter the Smart Office server URL and the location of the Smart Office features.

For mass deployment it’s more convenient to have a silent scripted install without user interaction and this is possible if you know the name of the public properties for the Smart Office Windows installer and apply the appropriate MSI Command-Line Options.

The public properties for the Smart Office installation are SERVERURL and FEATURELOCATION as described in the Infor Smart Office Installation Guide [ISOIG].

Here is an example of a silent install using msiexec on the command-line run as administrator.

msiexec.exe /I InforSmartOffice.msi /QN /L*V iso_msi_install.log SERVERURL=httpsUrl_to_isoserver FEATURELOCATION=httpsUrl_to_features 

Explanation of options and parameters:
/I 				Install option
InforSmartOffice.msi 		Set the location path to the InforSmartOffice.msi file
/QN 				No user interface option
/L*V 				Log all information with Verbose output option
iso_msi_install.log 		EXISTING location path to the log file
SERVERURL=https... 		Smart Office server URL
FEATURELOCATION=https...	Smart Office feature URL

If you don’t have sufficient administrative privileges to do the installation for all users on the machine you will get a failed installation error code [1925] in the log file.

Important information!
Read the Infor Smart Office Installation Guide [ISOIG] for ISO feature limitations and the Virtualization & Hardware Support Statement regarding Smart Office client support for virtualized environments.


Snooping my Mashup for Missing Data

Sometimes when you’re developing a Mashup it happens that the data you’re expecting to appear in a databound control is not showing up. There’s a small developer tool named Snoop that will help you examine the runtime visual tree of a Windows Presentation Foundation (WPF) user interface.

Snoop WPF Spy utility


Launch Smart Office and open the Mashup Designer. In this post we use an example from the Help menu named Document found in the Infor Document Management category.


Run the example, save it and search for any Document Type e g CLM_Document. Depending on the available data, it will look something like this in the running Mashup.


Now it’s time to launch the Snoop utlitity tool. It has a slim and narrow window. ISOSnoop

Drag the Snoop hair-cross (marked yellow) and drop it on your Mashup window. A new window will open and present the visual tree representation of the user interface in the left-hand panel and the details of the selected UI element in the right-hand panel. Below the details panel there’s a preview panel to render and show the selected UI element (if actived with the power button).

Press down the CTRL- and SHIFT- key simultaneously while you drag the mouse over the Mashup window. The control beneath the mouse will be selected and decorated with a red border and the corresponding element in the Snoop visual tree view will be highlighted and selected. Navigation can also be done directly in the tree-view by selecting UI element nodes.



Let’s examine the bound data for the document attribute panel. Use the mouse or locate and select the LangAttrList (ListBox) in the visual tree. Scroll down in the Properties list until you find ItemsSource property for the ListBox control.

ISO IDM Snoop ItemsSource

It’s now possible to drill-down into the data collection with a double-click on the value of ItemsSource, in this example [System.Windows.Data.CompositeCollection]. Now you see that the collection contains 1 item: this[0]. You can continue to drill-down with a double-click on the value this[0] to see the details of the item or navigate back up by clicking the up-arrow button (marked yellow).

ISO IDM Snoop Drill-down and up

In this case the ListBox will apply a template for each document attribute found in a collection item. Select the attrTemplate under the ListBoxItem to show its properties. In most template cases the data will be in the DataContext property of the element. Select the Data Context tab for a dedicated view of the property, in this case the DataContext is a piece of XML.
Note that there’s a Binding Errors column in the properties list that will show an error message if the data binding declaration for a UI element property is wrong and the data source can’t be found.

ISO IDM Snoop Data Context

We’ve only scratched the surface of the Snoop tool functionality but it’s the basics needed to investige why your data is not showing up.

New Log Viewer – Part V

Part I – Overview of the Improved UI
Part II – How to Find Your Way
Part III – Getting the Facts and Categories
Part IV – ClickOnce Installation Log

M3 Transaction Time Measurements

When the Smart Office log (debug mode) contains M3 (MForms) time measurements, a tool area will open up beneath the content area with an overview of where the time is spent for the selected time log entry. The purpose of the overview is to put the time values in context and give a better understanding where to look further for percieved performance issues. Note that the chart values don’t always add up exactly due to rounding errors and measurement precision.

Click on the category Timer under the M3 section to focus on the time measurements. Select the first log line and use the up-/down- arrow keyboard keys to scroll through the list and see how the values change in the overview chart.


Depicted here is the standalone version of the Log Viewer, where Smart Office client dependent functionality have been hidden, therefore a few buttons are missing.

In the Tools context menu (found on any log line) you have export options for the measured times. Selecting an export option extracts all measurements and formats them as comma separated values that can be copied into the Clipboard, exported to Microsoft Excel or opened in the Windows associated text viewer.

Exporting the measurements to Microsoft Excel makes it easy to generate a line chart over the measured times for selected function calls.


How do I turn on the M3 time measurement on the server side?

In the Smart Office client you control the time measurement by launching:


The Smart Office log level setting must also be set to Debug.

New Log Viewer – Part IV

Part I – Overview of the Improved UI
Part II – How to Find Your Way
Part III – Getting the Facts and Categories
Part V – M3 Transaction Time Measurements

Smart Office ClickOnce Installation Log

Smart Office is using Microsoft ClickOnce Technology to achieve a self-updating client that can be installed and launched with minimal user interaction from a central location. Once in a while it can happen that the ClickOnce installation fails and the brief details provided in the error dialog can be hard to interpret. In verbose log mode you can follow the installation step-by-step.

In ISO HF23 and beyond the Log Viewer can enable the verbose Microsoft ClickOnce log from the tool menu. The ClickOnce log file setting is active for the current Windows user on the local machine until deactivated.
The verbose log can be activated manually, from another tool or other Smart Office installation by setting Windows Registry values.

ClickOnce Log Tool Options


Enable Log

Toggle the activation of the verbose ClickOnce log with the Enable Log menu item. A log will be created at the next launch of Smart Office or by any other application using ClickOnce technology. If ClickOnce log is deactivated with an Enable Log uncheck and the activation was not made by this tool, a warning will be presented to inform and verify the deactivation. The ClickOnce.log file is stored in the temporary path defined in the Windows environment.

Copy Log to Clipboard

If a ClickOnce.log file exists, the log content is copied into the Windows Clipboard.

Open Log in External Viewer

If a ClickOnce.log file exists, the log is opened in the Windows associated text viewer.

Open Log File Location

If a ClickOnce.log file exists, the folder location will open in Windows File Explorer.

Analyze ClickOnce Log

Runs an analysis of the current ClickOnce log and displays a summary overview  highlighting the sessions containing errors.


The Clipboard button copies the selected session to the Windows Clipboard and the View External button opens the selected session in the Windows associated text viewer.

Create Verbose Mode Setup File

As a Smart Office administrator you have the option to generate a file that modify the Windows Registry to enable/disable the ClickOnce verbose log when targeting another Windows client where the Smart Office installation fails. Windows security applies to the launch of registry files.

Enable ClickOnce Log

Select Enable ClickOnce Log to create the EnableClickOnceVerboseLog.reg file. After the file has been created the Windows File Explorer will open to its location. Verify that the named log file location matches the target client, otherwise change it. The default location is the temporary folder of the Windows environment.

Disable ClickOnce Log

Select Enable ClickOnce Log to create the DisableClickOnceVerboseLog.reg file. After the file has been created the Windows File Explorer will open to its location.

Open a Log from Another Computer

If you have a log file sent to you or copied from another machine, set the Enable Log toggle menu as checked and click on the menu Open Log File Location to get a Windows File Explorer showing the target folder. Ensure that the log file is named ClickOnce.log  and copy it to the target folder. Now you can select Analyze ClickOnce Log and see the overview in the tool view.


Moving Smart Office Favorites into H5

If you’re moving from the Smart Office client to the H5 client for M3, there are two utility tools that will help you to export and transform the compatible favorites of the Smart Office users. You can find the tools in the latest Smart Office delivery package (v10.2.1.0) under the Additional Files Folder; and Get the zip archives and extract the tools.

For older Smart Office versions read the chapter Importing User Files in Smart Office 10.2 using the MangoAdminTool in the Infor Smart Office Administration Guide (ISOAG_10.2.1 page 254).

Export the User Favorites from Smart Office

Launch the MangoAdminTool.exe, select and login to the Smart Office server.


  • Select the Export tab in the Mango Admin Tool
  • Check the Roaming files checkbox and type Favorites.lfv as filter in the field
  • Press the Export button to create the file
  • Extract the archive into a temporary folder

Transform the Favorites and Prepare for H5 Import

Launch the FavoritesMigrationTool.exe, browse and select the UserFiles in the temporary folder with the extracted content from The favorites for the selected users will be filtered, excluding all links but the ones with http, https and mforms as scheme.


  • Select the users to be exported among the ones listed
  • Press the Export button to create the

Windows File Explorer will open and show the location of the created In the same folder there is a transformation report named ISOtoH5FavoritesExportReport.txt as a receipt of what has been done during the operation.

Import the Favorites into H5

Launch the H5 client and select Administration Tools and Import of Favorites.


  • Press the Upload button and select the file
  • Press the Import button and then restart the server


New Log Viewer – Part III

Part I – Overview of the Improved UI
Part II – How to Find Your Way
Part IV – ClickOnce Installation Log
Part V – M3 Transaction Time Measurements

Two of the new features in the improved UI are the side-panels with categories to the left and facts to the right.

The Basic Facts

Every time the selected session changes, relevant support information are extracted and presented in the Fact area, e g Smart Office version, launch method, Windows related version, feature details, languages timeouts etc. The basic facts often needed in a support case.


To compare fact value changes between sessions in the log file, you select the full log file in the session selector.  This will list duplicate facts one for each session.

A click on a listed fact will scroll the originating log line into view and select it. The context menu on a selected fact reveals more options that may help you further.

Copy Value

Copy puts the presented value into the Windows Clipboard.

Copy Matches to Clipboard

Copy the log entries from where the fact was extracted into the Windows Clipboard.

View External

Show the log entries from where the fact was extracted in the Windows associated text viewer.


Browse is enabled if the fact value is an URL and the user is allowed to launch external applications in Windows according to the Smart Office settings. It will launch the URL in the Windows associated browser application.

Open file location

Open file location is enabled if the fact value is an existing file path and the user is allowed to launch external applications in Windows according to the Smart Office settings. It will launch the Windows File Explorer and show the folder.


I’ve got a recurring set of log entries I often look for

You can create a category in the category area that will collect the log entries that match any of the aspects defined. If you’re a feature or SDK application developer you can create a category that matches the origin i e the namespace of your assembly. Some entries may appear more than once in the result if many aspects matches.


Select one or many log entries that is representative for the category you wish to create and click on Create Category from in the context menu, it will open the category definition dialog with the values from the selection added as options for the category definition.

Select a category Section from the list of existing ones or type a new section name. Name the category in the Header field. Minimize the number of matching values to get fewer more relevant matches. All log entries that contains ANY of the aspects defined will be part of the category.


Press Save button and you will have your category in the left side-panel for quick content selection.


Launch the Log Viewer targeting a specific feature or SDK application

You can create a Shortcut with a parameterized link on the Canvas to launch the Log Viewer on specific content, for debugging scenarios or targeting a specific feature or SDK application. The base launch link for the Log Viewer is:


Add a free-text search parameter to start with all entries matching the search criteria, in this example all entries related to user idle detection.


This can be extended with a session parameter to specify the initial session to select in the log. It can be a value [1..n], last will select the current session, prev will select the previous session and full selects the whole log file. Previous is useful if you examine something that happens during shutdown and you examine the log after a restart.


and you can of course specify a category as initial selection e g your custom category

internal://log?cat=service unavailable
internal://log?cat=service unavailable&session=full

Finally you have a sessiontime parameter that may be useful in some special cases. If the sessiontime parameter is present, the session parameter is ignored.