在开发复杂的应用程序时,经常需要在应用程序中嵌入浏览器控件,以便用户能够浏览网页。然而,浏览器控件可能会遇到内存泄漏、错误和异常等问题,这些问题可能会影响整个应用程序的稳定性。为了解决这个问题,可以使用Microsoft AddIn Framework (MAF) 来在独立进程中托管浏览器控件,从而将这些问题隔离开来。本文将详细介绍如何实现这一目标。
对于不熟悉MAF的初学者,建议先访问MSDN文档,了解Pipeline Development的基本架构。MAF允许开发者创建可在不同进程中运行的插件,这些插件可以与宿主应用程序进行双向通信。
应用程序是一个WPF窗口应用程序,它使用AddIn浏览器控件在单独的进程中导航到指定的URL。以下是应用程序的主要功能:
项目包含七个项目,每个项目都引用了Pipeline Architecture中的一个层。以下是每个项目的主要功能:
项目1: AppContracts
定义接口IBrowserAddInContract,该接口派生自IContract,并将其标记为AddInContract。IBrowserAddInContract接口需要在AddIn中实现,以便使用AddIn框架在进程外运行浏览器。该接口有两个方法,一个用于获取句柄,另一个用于导航到指定的URL。
public interface IBrowserAddInContract : IContract
{
INativeHandleContract GetUI();
void Navigate(string url, string cookie);
void BeforeNavigateEventAdd(INavigateEventHandler handler);
void BeforeNavigateEventRemove(INavigateEventHandler handler);
}
定义两个接口,一个用于处理AddIns在宿主应用程序中引发的事件,另一个用于传递事件参数。
public interface INavigateEventHandler : IContract
{
bool Handler(INavigateEventArgs args);
}
public interface INavigateEventArgs : IContract
{
string url { get; }
}
项目2: HostSideAdapter
在这个项目中,引用AppContracts和BrowserHostView项目。实现两个类,一个用于从ContractToHost调用方法,另一个用于HostToContract。
项目3: AddInSideAdapter
在这个项目中,引用AppContracts和BrowserAddInView项目。这个项目中的一个重要任务是处理运行事件的调度器,这在AppDispatcher类中完成。
项目4 & 5: BrowserAddInView 和 BrowserHostView
这两个项目定义了视图类为抽象类。AppContracts中的所有方法都已定义。
[AddInBase]
public abstract class BrowserAddIn
{
public abstract event System.EventHandler Navigating;
public abstract FrameworkElement GetUI();
public abstract void Navigate(string url, string cookie);
}
项目6: BrowserHostApplication
在这个项目中,引用BrowserHostView。使用LoadAddIn方法中提到的特定类型的AddIn。使用AddInStore静态方法FindAddIns检索机器上特定路径上可用的AddIns。
private void LoadAddIn()
{
String path = Environment.CurrentDirectory;
String[] warnings = AddInStore.Rebuild(path);
IList<AddInToken> tokens = AddInStore.FindAddIns(
typeof(BrowserHostView.BrowserAddIn), path);
addins = new List<BrowserHostView.BrowserAddIn>();
ap = new AddInProcess();
ap.Start();
AddInStore.FindAddIns(
typeof(BrowserHostView.BrowserAddIn), PipelineStoreLocation.ApplicationBase);
addInInstance = tokens[0].Activate<BrowserHostView.BrowserAddIn>(ap,
AddInSecurityLevel.FullTrust);
addins.Add(addInInstance);
addInIndex = dp.Children.Add(c.GetUI());
addInInstance.Navigating +=
new EventHandler<BrowserHostView.NavigateEventArgs>(usercontrol_BeforeNavigate);
}
要卸载AddIn,移除事件并关闭进程:
private void UnloadAddIn()
{
addInInstance.Navigating -= usercontrol_BeforeNavigate;
dp.Children.RemoveAt(addInIndex);
addInInstance = null;
ap.Shutdown();
}
项目7: BrowserAddIn
声明一个新类BrowserAddInCode,并将其标记为[System.AddIn.AddIn("BrowserAddIn")]。实现抽象视图类及其方法GetUI、Navigate和NavigatingEventCall。这个类实例化了BrowserControl。