如何获得“实际"主机应用程序实例? [英] How do I get the *actual* host application instance?
问题描述
我在VBE的C#加载项中有此代码(强调"VBE":不是是MS-Office加载项):
I have this code in a C# add-in for the VBE (emphasis "VBE": it's not a MS-Office add-in):
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
类,例如,Microsoft.Office.Interop.Excel.Application
类型;在applicationName
中,Excel的参数将为"Excel".
Where TApplication
is a MS-Office interop Application
class, for example, a Microsoft.Office.Interop.Excel.Application
type; here the applicationName
parameter would be "Excel" for, well, Excel.
问题在于,Marshal.GetActiveObject
似乎只返回创建的 first 实例,并且不一定是托管当前VBE环境的实例,并且
The problem is that Marshal.GetActiveObject
seems to only ever return the first instance created, and that's not necessarily the instance that's hosting the current VBE environment, and this causes issues.
如何获得 actual 主机应用程序实例?
How can I get ahold of the actual host application instance?
推荐答案
为了杀死僵尸,您可以通过以下方式获得VBE主机的 name :
For the sake of slaying a zombie, you can get the name of the VBE's host by:
-
检查将您带到主机的CommandBarButton的标题.该按钮位于标准工具栏"上,也位于视图"菜单中.
Inspecting the caption of the CommandBarButton that takes you to the host. The button is on the Standard Toolbar, but also in the View Menu.
检查引用的名称.通常,第一个引用不是VBA,而是BuiltIn
.
Inspecting the names of the references. Typically the first reference that isn't VBA but is BuiltIn
.
检查文档组件的Properties集合的Application.Name属性.
Inspecting the Application.Name property of document component's Properties collection.
要可靠地获取对VBE主机的引用,必须使用文档类型组件的Properties集合.例如,一旦您知道主机的名称是"Microsoft Excel",您只需要找到Workbook文档组件(通常命名为ThisWorkbook),就可以从组件的属性集合.
And to reliably get a reference to the VBE's host, you have to use the Properties collection of the document-type components. For example, once you know that the name of the host is "Microsoft Excel", you just need to find the Workbook document-component (typically named ThisWorkbook), then you can get the host from the component's Properties collection.
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
方法.
But not all vbProjects have document-type components, so for such projects you'll have to resort to the GetActiveObject
approach.
这篇关于如何获得“实际"主机应用程序实例?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!