使用 COM Interop 从 VSTO C# 列出现有 Access 实例的 MS Access 表

List MS Access tables of existing Access instance from VSTO C# using COM Interop

使用 VSTO 和 COM Interop,我正在尝试访问和操作已在 Microsoft Access 中打开的数据库。我可以获得 Access 应用程序对象、当前用户名和其他属性。但是,当我尝试获取 table 的列表以打印 table 名称时,代码失败了。

我的最终目标是 运行 使用 'application.Run("MyMacroName")' 的 Access VBA 宏。谁能告诉我我错过了什么或做错了什么?谢谢。

更新解决方案

感谢 Albert(见下文)一直提供 (Visual Basic) 信息,直到我能够使 C# 代码工作。我缺少的最重要的事情是 1) 使用引用的 DAO(VStudio 说我最初不需要它),以及 2) 循环的 explicit DAO TableDef 类型('var' 不工作)。

可用的更新代码:

using System.Runtime.InteropServices;
using Microsoft.Office.Interop.Access;
using Microsoft.Office.Interop.Access.Dao;  // *MUST* have DAO as well
using Access = Microsoft.Office.Interop.Access; // Access = a namespace qualifier

[TestMethod()]
  public void MsAccessComInteropTest() {
    // explicitly cast the object to an Access.Application
    // I used 'Access.Application' to qualify from a System.xxxx.Application type
    var app = (Access.Application) Marshal.GetActiveObject("Access.Application");
    Dprint($"{app.Name}"); // prints Microsoft Access
    Dprint($"{app.CurrentUser()}"); // prints Admin

    var db = app.CurrentDb();

    // *MUST* use TableDef type explicitly from DAO in loop - cannot use 'var'
    foreach (TableDef tbl in db.TableDefs) {
      // Attributes == 0 means a user-defined table
      if (tbl.Attributes == 0) {
        Debug.Print($"{tbl.Name}  '{tbl.Attributes.ToString()}'");
      }
    }

    app.Run("MyVbaMacroName");  
}

如果你想要完整的表格列表,通常使用CurrentDb.Tabledefs

var db = app.CurrentDb(); 
foreach (var td in db.TableDefs) {
    Dprint(td.Name);
}

您需要对 Access 和 DAO 的引用。

这两个:

Microsoft.Office.Interop.Access
C:\Program Files (x86)\Microsoft Visual Studio 12.0\
Visual Studio Tools for Office\PIA\Office14\
Microsoft.Office.Interop.Access.dll

你需要这个:

Microsoft.Office.Interop.Access.Dao
C:\Program Files (x86)\Microsoft Visual Studio 12.0\
Visual Studio Tools for Office\PIA\Office14\
Microsoft.Office.interop.access.dao.dll

因此您的代码将如下所示:

{
Access.Application app;

app = Interaction.GetObject(Class: "Access.Application");
Access.Dao.Database db;
db = app.CurrentDb;
Access.Dao.TableDef tblDef;

foreach (var tblDef in db.TableDefs)
    Debug.Print(tblDef.Name);
 }

事实上,您可以使用后期绑定,甚至不引用互操作程序集。

例如:

{
var app = Interaction.GetObject(Class: "Access.Application");
var db = app.CurrentDB;
var tblDef;
foreach (var tblDef in db.TableDefs)
    Debug.Print(tblDef.Name);
}

但是,如果您进行 100% 后期绑定,那么您将无法获得任何智能感知。

此外,这看起来很奇怪:

using Access = Microsoft.Office.Interop.Access;  

为什么上面的“=” - 我认为它看起来不对。

应该是:

using Access Microsoft.Office.Interop.Access;  

因此,如果您要使用互操作进行引用 - 您需要 Access + DAO。 (它们是不同的程序集,但使用相同的名称 space - 不确定这是否是 c# 中的问题,但它在 vb.net