在 C# COM-DLL 项目中使用外部 DLL 用于 MS-Access 使用

Posted

技术标签:

【中文标题】在 C# COM-DLL 项目中使用外部 DLL 用于 MS-Access 使用【英文标题】:Using external DLL's in C# COM-DLL project for MS-Access usage 【发布时间】:2019-12-23 23:39:33 【问题描述】:

用户的主要应用是ms-access(带有ms-sql server)。 vba 中的大量代码。 我必须体现的主要功能之一是控制我客户的 voip 电话。我的计划是制作一个 ms-access 可以使用的 COM DLL。

到目前为止,我已经设法编写了一个 C# 项目(vs2019 .net 框架),它使用 json 很好地处理 voip pbx,并完成了所有必要的任务,例如调用呼叫、发送短信、获取呼叫列表、 recodings 列表,获取录音 wav 文件并将其转换为 mp3。我使用 Newtopsoft.Json 和 NAudio.Lame。

但它只能作为独立的 .net 项目或 exe 工作。 作为一个 COM DLL(类库)——ms-access 可以处理和使用它,直到它到达代码使用任何外部 dll 功能的部分——并且它崩溃(使用 newtonsoft)或只是不工作(使用 naudio),尽管dll 位于工作文件夹中。

我知道我必须找到一种方法让这些外部 dll 在办公室(32 位)环境下工作。 几天来,我一直在尝试和猜测许多代码示例。我尝试按照 Assembly.Load/From/File 示例动态加载并包含 dll,但我未能在我的代码中吸收它,甚至无法充分理解它。

我希望我能在这里得到解决方案。 谢谢:)

【问题讨论】:

如何将软件转换为您使用 com dll 调用的 API/服务? 感谢您的回复。我现在正在寻找几种替代方案:) 【参考方案1】:

嗯,我可以创建一个用于 Access 的 COM 对象。当该类代码用作 Access 中的 COM 对象时,用于序列化数据的外部库代码(在我的情况下为 Newton 软件)工作得很好。 您没有提及其他库是托管代码还是外部win32 .dll?然而,我已经将非托管 .dll 与 .net COM 对象一起使用,然后从 MS-access 中使用了它。 项目资源管理器中的唯一问题是确保您对外部引用的 .net .dll 库具有复制本地设置 = true。 (这是默认设置,所以我相信你会这样做。 下一个问题当然是配置文件有没有用? (app.config)等?这样做的原因当然是因为您的应用程序是使用 msaccess.exe 启动的,因此将假定配置和设置位于 office 安装文件夹中,而不是本地应用程序中。因此,将这些 app.config 文件移动/复制到 msaccess.exe 所在的 office 文件夹中并不是那么实际。并且配置文件名不仅要在同一个文件夹中,还要命名。

Msaccess.exe.config.

代替

YourDotNet.exe.config

当然,如果您将项目构建为 .net 执行程序?那么当然任何配置设置(应用程序,而不是用户)都将放置在此配置文件中,当然该文件必须与 .exe 文件放在同一文件夹中。

因此,可以将“测试”函数(任何函数都是该类的方法)添加到您从 VBA 测试/调用的类中,以确保可以看到和读取此类设置(如果您正在使用任何设置)。

例如:

System.Reflection.Assembly.GetExecutingAssembly().Location + ".config"

因此,返回它以访问并显示此结果。

另一个问题当然是强制你的项目到 x86。我不会使用“任何”CPU。虽然这个“可能”有效,但由于您使用的是 access x32,那么我会强制将您的 .net 类编译为 x86,而不是“任何”CPU。如果将某些外部程序集与特定位大小进行比较,这也会产生一些错误,因此 x86 设置将导致您的类不使用某些外部 .net .dll。

现在您“注意到”您的项目作为 .exe 工作,然后“有点”作为类工作,“.dll”注册为 COM。

但是,您没有提及如何将其从 .exe“翻转”到类,或者您只是有一个作为 .exe 运行的 .net“测试”项目,它当然有对该类 .dll 的引用。而且您没有使用“COM”进行此测试。

如果您的 test.exe 程序可以使用该外部程序集?

然后我会创建一个 test2 项目,但这次不要引用程序集(如 .net),而是尝试使用 .net CreateObject()。 (我认为 c# 有这个选择——vb.net 肯定有)。

因此您可以尝试在此 .net 测试示例中使用 CreateObject(),从而从 .net 作为 COM 进行测试。

因此,这个测试 .net 程序(没有引用程序集的程序)将在您一直跳到 ms-access + VBA 测试代码之前进行中间测试。

但是,我将首先测试/检查此处是否使用了 app.config 文件,因为正如您在切换到 COM 对象时所指出的那样,然后在 Access/VBA 中创建该对象的实例? 那么配置文件将不会被使用。您可以在 .net 代码中强制/更改该运行程序集中的 app.config 文件,但我似乎找不到执行此操作的代码示例。但在我们确认您在此处使用 app.exe.config 文件之前,我不会深入挖掘。

编辑

出于好奇,我用谷歌搜索了 naudio。它是托管代码。因此,该库应该可以正常工作。如果该项目被编译为“ANY CPU”,您可以尝试重新编译为 x86,也可以将您的测试程序重新编译为 x86。然后,当您创建一个 COM 对象时,再次将其编译为 x86。

如前所述,我为 ms-access 做了相当多的 COM 工作,我毫无问题地将 Newtonsoft(用于 jason 序列化/反序列化)用作 ms-access 使用的 COM 对象。

鉴于 naudio 是托管代码,我不明白为什么会出现问题。您在这里使用的任何其他 3rd 方 .dll 吗?作为一个快速测试,我会将所有项目设置为 x86。您似乎“提到”了 COM 对象的“一些”有效,但不是全部。

【讨论】:

非常感谢 Albert 的详尽回答。我不清楚 - 我做了一个独立的 exe 项目,它运行良好。我做了一个单独的 COM 项目,但访问失败。由于您的回答是您没有像我使用 COM for Access 那样遇到任何问题(我眼中的泪水......:P),我很怀疑我没有很好地封闭和定义 COM,并且在此过程中犯了一些错误.我会做一些孤立的测试项目来找出我错在哪里。 NewtionSoft (jason lib) 很好,我在 .net 中多次使用它作为 Access 中的 COM 对象。我将创建一个测试 .net 项目来使用该类。让它全部工作,然后尝试将单独的类作为 COM 对象。这种方法将允许您测试 + 让类更快地工作,并且所有测试和开发都将在 VS 中进行。因此,在 .net 中创建一个新的仅类项目,将您需要的任何内容放入该类项目中,然后从另一个“主”.exe .net 项目中使用它。一旦这一切正常,然后尝试将类作为 Access 中的 COM。

以上是关于在 C# COM-DLL 项目中使用外部 DLL 用于 MS-Access 使用的主要内容,如果未能解决你的问题,请参考以下文章

使用 user32.dll 从外部应用程序的文本框(Unicode)中提取文本到 C# 应用程序中

Unity使用DLL库

C#中导入外部dll文件,如果不放在当前目录下,通过设置工程属性-引用路径选项卡添加文件路径,为何报错啊

C# t4模版引擎笔记 引入外部dll

从 C# 中的外部 DLL 访问 windows 窗体控件

C#上位机开发(十四)—— C#中通过dll库调用外部C/C++函数