如何获得*实际的*主机应用实例?
本文关键字:应用 实例 主机 何获得 | 更新日期: 2023-09-27 18:16:17
我在VBE的c#插件中有这段代码(强调"VBE":它是而不是一个MS-Office插件):
public abstract class HostApplicationBase<TApplication> : IHostApplication
where TApplication : class
{
protected readonly TApplication Application;
protected HostApplicationBase(string applicationName)
{
Application = (TApplication)Marshal.GetActiveObject(applicationName + ".Application");
}
其中TApplication
为MS-Office互操作Application
类,例如:a Microsoft.Office.Interop.Excel.Application
类型;这里的applicationName
参数将是"Excel",用于Excel。
问题是Marshal.GetActiveObject
似乎只返回创建的第一个实例,而这不一定是承载当前VBE环境的实例,这导致了问题。
如何获取实际的主机应用实例?
为了杀死僵尸,您可以通过以下方式获取VBE主机的名称:
-
检查带您到主机的CommandBarButton的标题。该按钮在标准工具栏上,但也在视图菜单中。
-
检查引用的名称。通常第一个引用不是VBA,而是
BuiltIn
。 -
正在检查应用程序。
并且为了可靠地获得对VBE主机的引用,您必须使用文档类型组件的Properties集合。例如,一旦你知道主机的名称是"Microsoft Excel",你只需要找到工作簿文档组件(通常名为ThisWorkbook),然后你可以从组件的属性集合中获得主机。
var appProperty = vbe.VBProjects
.Cast<VBProject>()
.Where(project => project.Protection == vbext_ProjectProtection.vbext_pp_none)
.SelectMany(project => project.VBComponents.Cast<VBComponent>())
.Where(component => component.Type == vbext_ComponentType.vbext_ct_Document
&& component.Properties.Count > 1)
.SelectMany(component => component.Properties.OfType<Property>())
.FirstOrDefault(property => property.Name == "Application");
if (appProperty != null)
{
Application = (TApplication)appProperty.Object;
}
else
{
Application = (TApplication)Marshal.GetActiveObject(applicationName + ".Application");
}
但是并不是所有的vbProjects都有文档类型的组件,所以对于这样的项目,你必须求助于GetActiveObject
方法。