【问题标题】:Utilizing a Managed C# DLL from an ETL Tool via a Mixed-Mode C++/CLI DLL - Possible?通过混合模式 C++/CLI DLL 从 ETL 工具使用托管 C# DLL - 可能吗?
【发布时间】:2016-11-15 20:38:30
【问题描述】:

我正在使用 32 位 ETL 工具(Pervasive Data Integrator v9)。我需要让这个工具能够调用外部函数,该函数将从 ZIP 存档中删除文件而不提取存档。

ETL 工具提供了加载外部 DLL 并调用其函数的能力。 DLL 及其函数被 ETL 工具的自定义脚本语言引用,如下所示:

Declare function OemToCharA lib "user32" (byval lpszSrc as string, byval lpszDst as string) as long

然后在该声明之后的脚本行中的某处调用函数(本例中为 OemToCharA)。我已经使用注册的 DLL 对此进行了测试,并且可以正常工作。

所以我想构建一个 DLL,其中包含一个可以进行 zip 操作的函数。

由于我不知道如何以编程方式操作 zip 文件,我找到了 DotNetZip - 一个免费的 .NET 类库,它为 zip 归档操作提供了繁重的工作。对我来说问题是它是 .NET(托管)。我仍然想尝试使用它。因此,我构建了一个 C# DLL (.NET 4.0),其函数利用 DotNetZip 执行所需的 zip 文件操作。我传入两个参数,“zip 文件位置”和“要删除的文件”,然后 zip 存档得到更新。

我了解到构建混合模式 C++/CLI DLL 以利用本地世界中托管的 .NET 代码的想法。我找到了this VS 解决方案,其中包含 3 个基本项目:

  1. 托管 (C#) DLL 项目
  2. 引用 C# DLL 的混合模式 C++ DLL 包装器项目
  3. 一个本地(非托管)C++ 控制台测试应用项目,它引用了 C++ 包装器

我基于该模式构建了一个测试解决方案,它从 zip 存档中删除了一个文件,并且效果很好。但请注意,混合模式 DLL 是从本机 C++ 控制台应用程序调用的,该应用程序是 VS 解决方案的一部分。我不必注册任何 DLL,它就可以工作。

但最终我需要 ETL 工具来调用混合模式 DLL。我无法让它工作。

到目前为止我在 ETL 服务器上尝试过的事情:

  • 我尝试注册混合模式包装 DLL,但 SysWow64\regsvr32 未能在 DLL 中找到入口点。
  • 我在 ETL 服务器上安装了 VS 2015 VC++ x86 和 x64 可再发行库。
  • 我将解决方案中的 DLL(即混合模式、c# 和 dotnetzip dll)放在 ETL 引擎文件夹中,因为控制台应用程序在 DLL 位于其部署文件夹中时工作。

ETL 工具能够调用外部应用程序,因此我相信我可以让它调用类似于我的 VS 测试解决方案的控制台应用程序,但我真的很想让它只与 DLL 一起工作。这可能吗?如果是这样,我错过了什么?

【问题讨论】:

  • 您不需要运行 regsvr32,因为混合 DLL 不是 COM DLL。除了 C++ 运行时,您是否在目标机器上安装了 .NET?你们都是 32 位的 DLL 吗?
  • 谢谢马特,是的 .NET 安装在目标机器上,我验证了 4.0 存在。我可能在这里表现出我的无知,但我相信 DLL 都是 32 位的。控制台应用程序和混合模式 DLL 项目的目标平台是 Win32。 C# DLL 的目标平台是 Any CPU。不确定如何判断它们是否为 32 位?
  • 目标机器是 Windows Server 2012 R2 Datacenter
  • 任何 CPU 都适用于 C# DLL。也许缺少一些依赖项。如果目标机有VS,可以运行Fuslogvw.exe进行诊断:msdn.microsoft.com/en-us/library/e74a18c4(v=vs.110).aspx
  • 另外,如果你没有安装VS,你可以试试进程监控:technet.microsoft.com/en-us/sysinternals/processmonitor.aspx。请记住添加过滤器以仅查看来自您的 exe 的日志。

标签: c# c++ dll unmanaged managed


【解决方案1】:

向 Matt 致敬,感谢您使用 Process Monitor 的提示。

  • ETL 工具未找到 DLL,但 Process Monitor 告诉我它正在检查的文件夹...我将 DLL 移动到选中的文件夹之一
  • 我的包装函数最初是 void,其返回值的输出参数是 - 这会导致问题,因为我在 ETL 文档中没有关于如何调用 void 函数的好示例。我将函数更改为返回“long”并删除了输出参数。

进行这两项更改后,它开始工作。再次感谢马特!

【讨论】:

    猜你喜欢
    • 2011-10-24
    • 2011-02-11
    • 1970-01-01
    • 1970-01-01
    • 2010-11-07
    • 2015-11-02
    • 2011-03-02
    • 2011-03-04
    • 2010-12-13
    相关资源
    最近更新 更多