如何获得“实际"主机应用程序实例? [英] How do I get the *actual* host application instance?

查看:79
本文介绍了如何获得“实际"主机应用程序实例?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆