You may receive the System.Reflection.TargetInvocationException unhandled exception when you use the FormsFactory class to open a form in Small Business Accounting (906467)



The information in this article applies to:

  • Microsoft Office Small Business Accounting 2006
  • Microsoft Office Small Business Management Edition 2006
  • Microsoft Office Small Business Accounting 2006 Software Development Kit 1.2

SYMPTOMS

In Microsoft Office Small Business Accounting, you may receive the System.Reflection.TargetInvocationException unhandled exception when you use the FormsFactory class to open a form that has a user interface add-in installed.

CAUSE

This problem occurs because the Microsoft .NET Framework deserializer that is defined in the mscorlib assembly tries to load the assembly in which the object to be deserialized is defined. The .NET Framework cannot locate the Small Business Accounting assemblies because the application that made the call was started from a different directory.

RESOLUTION

To resolve this problem, you must explicitly create an application domain. You must set up this domain to include the path of Small Business Accounting and the path of the integrating application. To do this, follow these steps:
  1. Install Small Business Accounting and the integrating application in the same root directory.

    Note The default installation directory for Small Business Accounting is C:\Program Files\Microsoft Small Business\Small Business Accounting. If this directory is the directory where Small Business Accounting is installed, use the following installation paths:
    • \Program Files\Microsoft Small Business\Small Business Accounting
    • \Program Files\Microsoft Small Business\My Integration
  2. Put the code that opens the form by using the FormsFactory class in its own class. Also, put the code that calls the FormsFactory class in its own class. To do this, see the code in the "More Information" section.

MORE INFORMATION

Run the following code that constructs and then uses the FormsFactory class and the Small Business Accounting form in the domain that is explicitly created.

The following code creates the application domain.
AppDomain myDomain = AppDomain.CreateDomain(
	"MyDomain", 
	null, 
	GetSbaFullBusinessLogicAssemblyPath(""), 
	"My Integration;Small Business Accounting", 
	false);

ObjectHandle objectHandle = myDomain.CreateInstance(
	Assembly.GetExecutingAssembly().FullName,
	"SBA.ExecutingCode");

ExecutingCode ec = (ExecutingCode) objectHandle.Unwrap();

ec.LaunchCustomerForm();
The following code adds the directories that are involved in the application domain.
static string GetSbaFullBusinessLogicAssemblyPath(string assemblyName)
{
	// If you run the Setup program, the installation path is in the registry.
	const string InstallPathRegKey = 
		@"SOFTWARE\Microsoft\Business Solutions eCRM\2.0";
	const string MagellanInstallPathRegKey = 
		@"SOFTWARE\Microsoft\Business Solutions eCRM";
	const string InstallPathRegValue = "AccountingUI";            
	const string DefaultPath = 
		@"C:\Program Files\Microsoft Small Business\";

	StringBuilder installPath = new StringBuilder();

	RegistryKey regkey = 
		Registry.LocalMachine.OpenSubKey(InstallPathRegKey);

	if (regkey != null)
	{
		// A Small Business Accounting installation exists.
		installPath.Append(
			regkey.GetValue(InstallPathRegValue).ToString());

		// This line removes the file name and the Small Business Accounting folder.
		if (installPath.ToString().EndsWith("sbaui.dll"))
		{
			int lastSlash = installPath.ToString().LastIndexOf(@"\");
			int charToEnd = installPath.Length - (lastSlash);

			// This line tells where the last slash is.
			installPath.Remove(lastSlash, charToEnd);

			// This line finds the newest last slash.
			lastSlash = installPath.ToString().LastIndexOf(@"\");

			// This line determines how many characters the Remove method must remove.
			charToEnd = installPath.Length - (lastSlash);

			// This line removes the directory name.
			installPath.Remove(lastSlash, charToEnd);
		}
	}
	else 
	{
		// This line looks for a Magellan installation. 
		regkey =			Registry.LocalMachine.OpenSubKey(MagellanInstallPathRegKey);

		if (regkey != null)
		{
			Object temp = regkey.GetValue(InstallPathRegValue);

			if (temp != null)
			{
				installPath.Append(temp.ToString() );
			}
		}
	}

	if (regkey != null)
	{
		regkey.Close();
	}

	if (installPath.Length == 0)
	{
		// This line appends the default value of the installation path.
		installPath.Append(DefaultPath);
	}

	installPath.Append(assemblyName);

	return installPath.ToString();
}
The following code creates an instance of the ExecutingCode class that opens the Small Business Accounting form by using the FormsFactory class.
[Serializable]
public class ExecutingCode : MarshalByRefObject
{
	public void LaunchCustomerForm()
	{
		ObjectHandle sbiHandle = 
			AppDomain.CurrentDomain.CreateInstance(
				"SBAAPI",
				"Microsoft.BusinessSolutions.SmallBusinessAccounting.SmallBusinessInstance");

		ISmallBusinessInstance iSbi = 
			(ISmallBusinessInstance) sbiHandle.Unwrap();

		// This line determines that you can log on by using the database name and the server name.
		iSbi.LogOn(companyName, serverName);

		DataRow dr = iSbi.CustomerAccounts.DataView.Table.Rows[6];
		ICustomerAccount cust = 
			(ICustomerAccount)iSbi.CustomerAccounts.GetByDataRow(dr);

		ObjectHandle ffHandle = AppDomain.CurrentDomain.CreateInstance(
			"SBAUI", 
			"Microsoft.BusinessSolutions.SmallBusinessAccounting.UI.FormsFactory");
		IFormsFactory iFF = (IFormsFactory) ffHandle.Unwrap();
		iFF.Initialize(iSbi);
		Form form = iFF.CreateForm(cust);
		form.ShowDialog();
		form.Dispose();
		iFF.UnInitialize(false);
	}
}

Modification Type:MinorLast Reviewed:4/4/2006
Keywords:kbtshoot kbMBSMigrate kbprb KB906467 kbAudITPRO kbAudDeveloper