我需要获取系统(窗口)中所有当前打开的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 值。 关于如何实现这一目标有什么想法吗?
答案 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());
这会将关闭消息发送到所有访问主窗口,类似于用户关闭应用程序。