Problems When Calling into Script Functions in a Task Pane from Managed Code

We have been receiving questions about problems deploying some InfoPath solutions created with the InfoPath 2003 Toolkit that call into script functions in a task pane from managed code. These solutions work on the developer's machine, but then fail when deployed on user's machines if the MSHTML primary interop assembly (PIA) - microsoft.mshtml.dll - is missing.

This problem is caused by InfoPath object model members that return types from the MSHTML PIA. The MSHTML PIA is installed by default with Visual Studio .NET 2003, but is not installed by InfoPath 2003 SP1 or with the .NET Framework. As a result, when the solution is deployed on a machine missing the MSHTML PIA, the solution throws an exception.

There are two ways to resolve this issue: 1) Install and register the MSHTML PIA on the user's machine, or 2) Use late binding in your form code to call such functions.

Installing the MSHTML PIA on User's Machines

The MSHTML PIA is a redistributable component installed with Visual Studio .NET 2003 (as defined in the <drive>:Program FilesMicrosoft Visual Studio .NET 2003redist.txt file), so you can deploy it on all client machines where you want the solution to run. Refer to the End User License Agreement (EULA) for your edition of Visual Studio .NET 2003 for terms and conditions on redistributing components.

The MSHTML PIA (microsoft.mshtml.dll) needs to be copied to the user's machine, installed in the Global Assembly Cache (GAC) using the Global Assembly Cache tool (gacutil /i microsoft.mshtml.dll), and then registered using the Assembly Registration Tool (regasm microsoft.mshtml.dll).

Using Late Binding to Call Script Functions From Managed Code

You may also consider using late-bound calls to objects previously passed by the task pane script to the managed code in your form code. The following is a code fragment that shows how to do this by using the InvokeMember method of the System.Type class in the .NET Framework. Note that the managed code requires FullTrust permissions to work with late-bound calls. For more information on FullTrust permissions and how to deploy form templates that require this permission set, see Understanding Fully Trusted Forms.

Taskpane.htm:

<HTML>
<script>
function Initialize()
{
var XDoc = window.external.XDocument;
XDoc.Extension.SetTaskPaneWindow(window);
}

   function MyScriptFunc(s)
{
window.alert(s);
}
</script>

<BODY onload="Initialize();" />
// Remaining taskpane HTML goes here.
</BODY>
</HTML>

FormCode.cs:

private XDocument thisXDocument;
private Application thisApplication;
private object taskPaneWindow;
...

// Note: The MatchPath attribute should match your control's ID.
[InfoPathEventHandler(MatchPath="CTRL1_5", EventType=InfoPathEventType.OnClick)]
public void CTRL1_5_OnClick(DocActionEvent e)
{
object[] args = new object[] {"Hello from InfoPath script"};

      // Call into script through CLR late binding using the InvokeMember method.
taskPaneWindow.GetType().InvokeMember(
"MyScriptFunc", // late-bound method
BindingFlags.InvokeMethod | // binding flags
BindingFlags.DeclaredOnly |
BindingFlags.Public |
BindingFlags.Instance,
null, // binder object
taskPaneWindow, // target object
args);
}

   public void SetTaskPaneWindow(object window)
{
taskPaneWindow = window;
}