C# 如何从VBE加载项获取正确的活动应用程序?

C# 如何从VBE加载项获取正确的活动应用程序?,c#,ms-access,C#,Ms Access,我正在为access的VBE编写COM外接程序,我想在单击commandbar按钮后从C#执行vba函数 因此,我使用以下代码: const string ApplicationObjectName = "Access.Application"; Microsoft.Office.Interop.Access.Application app = (Microsoft.Office.Interop.Access.Application)Marshal.GetActiveObject(Applica

我正在为access的VBE编写COM外接程序,我想在单击commandbar按钮后从C#执行vba函数

因此,我使用以下代码:

const string ApplicationObjectName = "Access.Application";
Microsoft.Office.Interop.Access.Application app = (Microsoft.Office.Interop.Access.Application)Marshal.GetActiveObject(ApplicationObjectName);
app.Run(functionName);
如果只有一个ms access db处于打开状态,则此操作可以正常工作。但是,如果有两个开放的数据库,'GetActiveObject'获取错误的应用程序,并在另一个数据库中调用该函数。命令栏按钮不是其中的一部分


那么,如何获得正确的应用程序对象(=单击按钮的对象)?

此时我使用此处的代码段(仅德语):

但必须有更好的办法来解决这个问题

这里也讨论了类似的问题:这里:

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;

namespace Rainbird.Tools.COMInterop
{
    public class RunningObjectTable
    {
        private RunningObjectTable() { }

        [DllImport("ole32.dll")]
        private static extern int GetRunningObjectTable(uint reserved, out IRunningObjectTable pprot);

        [DllImport("ole32.dll")]
        private static extern int CreateBindCtx(uint reserved, out IBindCtx pctx);

        public static object GetRunningCOMObjectByName(string objectDisplayName)
        {
            IRunningObjectTable runningObjectTable = null;

            IEnumMoniker monikerList = null;

            try
            {
                if (GetRunningObjectTable(0, out runningObjectTable) != 0 || runningObjectTable == null) return null;

                runningObjectTable.EnumRunning(out monikerList);

                monikerList.Reset();

                IMoniker[] monikerContainer = new IMoniker[1];

                IntPtr pointerFetchedMonikers = IntPtr.Zero;

                while (monikerList.Next(1, monikerContainer, pointerFetchedMonikers) == 0)
                {
                    IBindCtx bindInfo;

                    string displayName;

                    CreateBindCtx(0, out bindInfo);

                    monikerContainer[0].GetDisplayName(bindInfo, null, out displayName);

                    Marshal.ReleaseComObject(bindInfo);

                    if (displayName.IndexOf(objectDisplayName) != -1)
                    {
                        object comInstance;
                        runningObjectTable.GetObject(monikerContainer[0], out comInstance);
                        return comInstance;
                    }
                }
            }
            catch
            {
                return null;
            }
            finally
            {
                if (runningObjectTable != null) Marshal.ReleaseComObject(runningObjectTable);
                if (monikerList != null) Marshal.ReleaseComObject(monikerList);
            }
            return null;
        }

        public static IList<string> GetRunningCOMObjectNames()
        {
            IList<string> result = new List<string>();

            IRunningObjectTable runningObjectTable = null;

            IEnumMoniker monikerList = null;

            try
            {
                if (GetRunningObjectTable(0, out runningObjectTable) != 0 || runningObjectTable == null) return null;

                runningObjectTable.EnumRunning(out monikerList);

                monikerList.Reset();

                IMoniker[] monikerContainer = new IMoniker[1];

                IntPtr pointerFetchedMonikers = IntPtr.Zero;


                while (monikerList.Next(1, monikerContainer, pointerFetchedMonikers) == 0)
                {
                    IBindCtx bindInfo;

                    string displayName;

                    CreateBindCtx(0, out bindInfo);

                    monikerContainer[0].GetDisplayName(bindInfo, null, out displayName);

                    Marshal.ReleaseComObject(bindInfo);

                    result.Add(displayName);
                }
                return result;
            }
            catch
            {
                return null;
            }
            finally
            {

                if (runningObjectTable != null) Marshal.ReleaseComObject(runningObjectTable);
                if (monikerList != null) Marshal.ReleaseComObject(monikerList);
            }
        }
    }
}
var activeProject = m_VBE.ActiveVBProject;
Microsoft.Office.Interop.Access.Application app = (Microsoft.Office.Interop.Access.Application)RunningObjectTable.GetRunningCOMObjectByName(activeProject.FileName);
app.Run(functionName);