4

我有一个 MS Access 数据库,上面有一个按钮,可以运行我编写的工具。该工具有效。Access 数据库有效。运行该工具的 VBA 有效。

但是,从 VBA 运行该工具时会出现问题。尝试加载 XML 配置数据时它总是崩溃。我通过检查我的错误报告工具(控制面板 -> 管理工具 -> 事件查看器)对此进行了测试。我还编写了我的工具的第二个版本,其中包含硬编码的所有 XML 数据。

我想知道发生这种情况是否有已知的原因,以及是否有解决此错误的可行解决方案。硬编码我的所有配置数据并不是一个真正理想的解决方案,因为配置数据需要可修改,而无需重新编译整个项目并推出更新。

信息:

  • MS Access 2010 与 Visual Basic for Applications(使用 Shell 进行应用程序调用)
  • 使用引用(IO、Linq、Xml.Linq、Data.OleDb、全球化)具有 XML 配置数据的 C# 应用程序

感谢您提供的任何帮助。

根据请求,这是我用来运行应用程序的代码:

Dim hProcess As Long
Dim myPath As String
dim myFile As String

myPath = Environ("ProgramFiles(x86)" & "\mytool\"
myFile = "mytool.exe"

hProcess = Shell( myPath & myFile, vbNormalFocus )

该应用程序是一个 WinForms 应用程序,它允许用户将 csv 中的列名映射到访问的字段。唯一实际的问题是它尝试加载 XML 配置数据的部分:

XDocument xDoc = XDocument.Load(Environment.CurrentDirectory + "\\config.xml");

同样,如果我将配置数据硬编码到应用程序本身中,那么在运行应用程序时完全没有问题。但是,如果我尝试加载 XML 配置数据,它会在事件查看器中给出一个错误事件,指出加载 XML 文件时存在未处理的异常。如果我在 VBA Shell 调用之外运行应用程序,它运行良好并且可以加载 XML 文件。它只会在尝试从 VBA Shell 加载 XML 时崩溃。

4

1 回答 1

2

根据我的经验,从 MS Access 执行 .NET 代码似乎会“搞乱”一些 .NET 的“获取当前目录”方法,如果您在没有 Access 的情况下直接运行完全相同的 .NET 应用程序,这些方法都可以正常工作。

如果你想看看我在说什么,在 Visual Studio 中创建一个新的控制台应用程序并粘贴以下代码:

using System;
using System.IO;

namespace CurrentDirTest
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(Environment.CurrentDirectory);
            Console.WriteLine(Directory.GetCurrentDirectory());
            Console.WriteLine(System.Threading.Thread.GetDomain().BaseDirectory);
            Console.WriteLine(AppDomain.CurrentDomain.BaseDirectory);
            Console.ReadLine();
        }
    }
}

当我直接从 Visual Studio 运行它时,它会输出这个(如预期的那样):

C:\Dev\Code\CurrentDirTest\CurrentDirTest\bin\Debug
C:\Dev\Code\CurrentDirTest\CurrentDirTest\bin\Debug
C:\Dev\Code\CurrentDirTest\CurrentDirTest\bin\Debug\
C:\Dev\Code\ CurrentDirTest\CurrentDirTest\bin\Debug\

现在将已编译的 .exe 放在您的Program Files (x86)\mytool\文件夹中,并尝试从 Access 中调用它,并使用您问题中的 VBA 代码。

当我在我的机器上这样做时,我得到了这个:

C:\Users\MyUserName\Documents
C:\Users\MyUserName\Documents
C:\Program Files (x86)\mytool\
C:\Program Files (x86)\mytool\

很奇怪,不是吗?从 MS Access 执行应用程序后
Environment.CurrentDirectory,两者都会返回我的“文档”文件夹。 我不知道为什么会发生这种情况,但确实如此。 Directory.GetCurrentDirectory()

解决方案:
如果您在您的机器上得到与我在我的机器上相同的结果,那么您的问题的解决方案很简单:只需使用System.Threading.Thread.GetDomain().BaseDirectoryorAppDomain.CurrentDomain.BaseDirectory获取当前目录。


以防万一有人在使用 COM-Interop 时遇到类似问题:当您通过 MS Access 中的 COM-Interop 执行 .NET 程序集时,问题会更加严重。
如果我没记错的话,两者都System.Threading.Thread.GetDomain().BaseDirectoryAppDomain.CurrentDomain.BaseDirectory我不起作用,因为两者都返回了msaccess.exe.
我不得不使用它this.GetType().Assembly.Location来获取 .NET 程序集的实际位置。

于 2012-05-21T21:24:35.127 回答