[英]How do I get the *actual* host application instance?
I have this code in a C# add-in for the VBE (emphasis "VBE": it's not a MS-Office add-in): 我在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");
}
Where TApplication
is a MS-Office interop Application
class, for example, a Microsoft.Office.Interop.Excel.Application
type; 其中
TApplication
是MS-Office互操作Application
类,例如, Microsoft.Office.Interop.Excel.Application
类型; here the applicationName
parameter would be "Excel" for, well, Excel. 这里的
applicationName
参数对于Excel来说就是“Excel”。
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 . 问题是
Marshal.GetActiveObject
似乎只返回创建的第一个实例,并且不一定是托管当前VBE环境的实例, 这会导致问题 。
How can I get ahold of the actual host application instance? 如何获得实际的主机应用程序实例?
For the sake of slaying a zombie, you can get the name of the VBE's host by: 为了杀死一个僵尸,你可以通过以下方式获得VBE主机的名称 :
Inspecting the caption of the CommandBarButton that takes you to the host. 检查将您带到主机的CommandBarButton标题。 The button is on the Standard Toolbar, but also in the View Menu.
该按钮位于标准工具栏上,但也位于“视图”菜单中。
Inspecting the names of the references. 检查参考文献的名称。 Typically the first reference that isn't VBA but is
BuiltIn
. 通常,第一个不是VBA的引用是
BuiltIn
。
Inspecting the Application.Name property of document component's Properties collection. 检查文档组件的Properties集合的Application.Name属性。
And to reliably get a reference to the VBE's host, you have to use the Properties collection of the document-type components. 要可靠地获取对VBE主机的引用,您必须使用文档类型组件的Properties集合。 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.
例如,一旦您知道主机的名称是“Microsoft Excel”,您只需要找到工作簿文档组件(通常名为ThisWorkbook),然后您就可以从组件的Properties集合中获取主机。
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");
}
But not all vbProjects have document-type components, so for such projects you'll have to resort to the GetActiveObject
approach. 但并非所有vbProject都具有文档类型组件,因此对于此类项目,您将不得不求助于
GetActiveObject
方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.