使用C#Interop获取所有MSACCESS应用程序实例

时间:2018-10-31 11:47:05

标签: c# ms-access office-interop

我需要获取系统(窗口)中所有当前打开的MSACCESS实例的列表,以便能够从我的应用程序中关闭其中的任何一个。我对EXCEL和WINWORD没问题,但是不能与Access挂钩。

我使用Office 2016,看到MSACCESS为每个打开的数据库文件创建了单独的procss。所以我认为我必须从窗口句柄中获取应用程序实例。我尝试修改以下代码:How to iterate through instance of Excel c#

我能够获得所有MSACCESS进程,但是Excel或Word代码不适用于MSACCESS。代码行:

if (buf.ToString() == "EXCEL7")

总是给我 MsoCommandBarDock 值。 关于如何实现这一目标有什么想法吗?

2 个答案:

答案 0 :(得分:0)

基于answer for Excel,Access版本类似:

const uint OBJID_NATIVEOM = 0xFFFFFFF0;

var procs = new List<Process>(Process.GetProcessesByName("MSACCESS.EXE"));

foreach (var p in procs)
{
    var mainHandle = (int)p.MainWindowHandle;
    if (mainHandle > 0)
    {
        var IID_IDispatch = new Guid("{00020400-0000-0000-C000-000000000046}");
        Microsoft.Office.Interop.Access.Application app = null;
        int res = AccessibleObjectFromWindow(mainHandle, OBJID_NATIVEOM, IID_IDispatch.ToByteArray(), ref app);
        if (res >= 0)
        {
            Debug.Assert(app.hWndAccessApp == mainHandle);
            Console.WriteLine(app.Name);
        }
    }
}

我在Windows 10(en-us区域设置)上使用Access 2016对其进行了测试。 主要区别在于访问的窗口层次结构不像Excel那样复杂,因此可以省略子窗口的迭代。

免责声明:这依赖于封闭源Windows应用程序的内部结构。作为其供应商的Microsoft出于明显的原因而阻止这种技巧:他们可能会在内部结构(窗口层次结构)发生更改的任何时候发布,更新或发布新版本,从而破坏了依赖于此的代码。同样,MS Access曾经具有单一文档查看模式,该模式可能会在同一发行版中为您提供两个版本的窗口层次结构。不要在商业产品/生产性软件中这样做。

答案 1 :(得分:0)

执行此操作的方法有很多,包括从ROT (运行对象表)中检索COM对象。由于您需要“ 公正”才能关闭应用,因此以下代码应该可以正常工作。

using System.Diagnostics;
using System.Linq;

Process.GetProcessesByName("MSACCESS").All(x => x.CloseMainWindow());

这会将关闭消息发送到所有访问主窗口,类似于用户关闭应用程序。

相关问题