跟踪用于将本机C ++ DLL包装到.NET的DLL依赖项

时间:2022-09-01 23:47:40

I have a C++ DLL (no code) that I want to expose to .NET applications.

我有一个C ++ DLL(没有代码),我想向.NET应用程序公开。

After pondering all the options I have/know of/could find (COM, P/Invoke, SWIG, etc.), I'm writing a .NET Class Library (in C++/CLI). Now the resulting DLL (class library) requires the original DLL and its dependencies, too. My problem lies in automagically keeping track of such things, so that applications that use the wrapper don't have to keep track of the other (native) DLLs (especially if the original DLL(s) develop a new dependancy).

在思考了我/已知/可以找到的所有选项(COM,P / Invoke,SWIG等)之后,我正在编写一个.NET类库(在C ++ / CLI中)。现在生成的DLL(类库)也需要原始DLL及其依赖项。我的问题在于自动跟踪这些事情,因此使用包装器的应用程序不必跟踪其他(本机)DLL(特别是如果原始DLL开发新的依赖项)。

To be more precise (and have something concrete to discuss), I'm trying to wrap cmr, so I write MR, the class library (which depends on cmr, naturally). cmr depends on PNL, OpenCV, and others. When I tried adding a reference to MR in a (C#) project, Visual Studio (2005 SP1) just copied MR.DLL, leaving all the dependencies behind, and then complaining (throwing a FileNotFoundException about missing modules). Manually copying cmr, PNL, etc. to the bin directory fixed the problem.

为了更加精确(并且有一些具体的讨论),我正在尝试包装cmr,所以我写了MR,类库(它自然地取决于cmr)。 cmr取决于PNL,OpenCV等。当我尝试在(C#)项目中添加对MR的引用时,Visual Studio(2005 SP1)只是复制了MR.DLL,留下了所有依赖项,然后抱怨(抛出关于缺少模块的FileNotFoundException)。手动将cmr,PNL等复制到bin目录修复了问题。

Without further ado, my question is this: Is there a way for .NET apps to only add a reference to one DLL, and everything just works?

不用多说,我的问题是:.NET应用程序是否只能添加对一个DLL的引用,一切正常?

I've been scouring through Google and SO, to no avail...

我一直在搜索Google和SO,但无济于事......

EDIT: mergebin seems the closest to what I'm looking for, but it can only merge a .NET DLL with one native DLL. Too bad one can't merge native DLLs.

编辑:mergebin似乎最接近我正在寻找,但它只能将.NET DLL与一个本机DLL合并。太糟糕了,无法合并本机DLL。

4 个解决方案

#1


You might take a look at mergebin, a tool that allows you to combine unmanaged and managed DLLs into one assembly. System.Data.SQLite uses this approach.

您可以查看mergebin,这是一个允许您将非托管DLL和托管DLL组合到一个程序集中的工具。 System.Data.SQLite使用此方法。

#2


I'm currently having a very similar problem.

我目前遇到了类似的问题。

One big step too meet my goal was to copy the Native .DLL into the output directory by a pre-built step in the C++/CLI project and add the linker option

同样重要的一步是通过C ++ / CLI项目中预先构建的步骤将Native .DLL复制到输出目录中并添加链接器选项

/ASSEMBLYLINKRESOURCE:"$(OutDir)\Native.dll"

This writes into the resulting assembly that there is a file "Native.dll" that belongs to the assembly. Now all projects referencing that project/assembly will also copy the Native.dll around! (It should also go into the GAC if you put you're assembly there - I didn't check that).

这会在生成的程序集中写入存在属于程序集的文件“Native.dll”。现在,引用该项目/程序集的所有项目也将复制Native.dll! (如果你把它放在那里也应该进入GAC - 我没有检查它)。

Okay, you still have to add all depending native.dll's. I also don't know if the native DLL is found on run-time if you load the assembly via Assembly.LoadFrom() from a very different path (this is something I have to solve for my problem because our C++/CLI wrapper assembly is needed by the Visual Studio designer).

好的,您仍然需要添加所有依赖native.dll的。如果你通过Assembly.LoadFrom()从一个非常不同的路径加载程序集,我也不知道是否在运行时找到本机DLL(这是我必须解决的问题,因为我们的C ++ / CLI包装程序集是Visual Studio设计者所需要的。

I hope this helps you a bit for you're problem.

我希望这可以帮助你解决一些问题。

EDIT:

Further investigations showed that the Wrapper .DLL always finds the native .DLL...that's the good thing. The bad thing is that the Visual Studio Designer copies the needed assemblies to a temporary directory (somewhere inside the user directory) when you open a form. When it copies the assemblies it ignores the linked resources and by this the native .DLL!

进一步的调查表明,Wrapper .DLL总是找到原生的.DLL ......这是好事。不好的是,当您打开表单时,Visual Studio Designer会将所需的程序集复制到临时目录(用户目录中的某个位置)。当它复制程序集时,它会忽略链接的资源,并通过本机.DLL!

#3


Sounds like you have two specific issues:

听起来你有两个具体问题:

  1. How to copy over the native code dlls before the build starts
  2. 如何在构建开始之前复制本机代码dll

  3. How to dynamically figure out the native code dependancies that need to be copied over in case they change.
  4. 如何动态地找出需要复制的本机代码依赖项,以防它们发生变化。

For 1), you could use a pre-build step in your C# project to call a custom util to copy over the correct files.

对于1),您可以在C#项目中使用预构建步骤来调用自定义util来复制正确的文件。

Looks like 2) has already been answered here on Stack Overflow.

看起来2)已经在Stack Overflow上得到了解答。

#4


Well, you could simply add commands to automatically copy the required DLLs into the correct output directory, as part of the Build process. This is done in Visual Studio by going to the project's properties.

好吧,您可以简单地添加命令以自动将所需的DLL复制到正确的输出目录中,作为构建过程的一部分。这是通过转到项目的属性在Visual Studio中完成的。

Project -> MyProjectName Properties... -> Build Events

项目 - > MyProjectName属性... - >构建事件

Add the commands to copy the files you need into the $(TargetPath) and you're done.

添加命令将您需要的文件复制到$(TargetPath)中,然后就完成了。

Another option would be to simply set the current working directory of your project (when you're running it from within Visual Studio only) to be the directory in which all the DLLs you need reside. You'll still have to manually copy the files when executing the program externally, but it will make development a little easier.

另一种选择是简单地将项目的当前工作目录(当您从Visual Studio中运行它时)设置为您需要的所有DLL所在的目录。在外部执行程序时,您仍然需要手动复制文件,但这会使开发变得更容易。

#1


You might take a look at mergebin, a tool that allows you to combine unmanaged and managed DLLs into one assembly. System.Data.SQLite uses this approach.

您可以查看mergebin,这是一个允许您将非托管DLL和托管DLL组合到一个程序集中的工具。 System.Data.SQLite使用此方法。

#2


I'm currently having a very similar problem.

我目前遇到了类似的问题。

One big step too meet my goal was to copy the Native .DLL into the output directory by a pre-built step in the C++/CLI project and add the linker option

同样重要的一步是通过C ++ / CLI项目中预先构建的步骤将Native .DLL复制到输出目录中并添加链接器选项

/ASSEMBLYLINKRESOURCE:"$(OutDir)\Native.dll"

This writes into the resulting assembly that there is a file "Native.dll" that belongs to the assembly. Now all projects referencing that project/assembly will also copy the Native.dll around! (It should also go into the GAC if you put you're assembly there - I didn't check that).

这会在生成的程序集中写入存在属于程序集的文件“Native.dll”。现在,引用该项目/程序集的所有项目也将复制Native.dll! (如果你把它放在那里也应该进入GAC - 我没有检查它)。

Okay, you still have to add all depending native.dll's. I also don't know if the native DLL is found on run-time if you load the assembly via Assembly.LoadFrom() from a very different path (this is something I have to solve for my problem because our C++/CLI wrapper assembly is needed by the Visual Studio designer).

好的,您仍然需要添加所有依赖native.dll的。如果你通过Assembly.LoadFrom()从一个非常不同的路径加载程序集,我也不知道是否在运行时找到本机DLL(这是我必须解决的问题,因为我们的C ++ / CLI包装程序集是Visual Studio设计者所需要的。

I hope this helps you a bit for you're problem.

我希望这可以帮助你解决一些问题。

EDIT:

Further investigations showed that the Wrapper .DLL always finds the native .DLL...that's the good thing. The bad thing is that the Visual Studio Designer copies the needed assemblies to a temporary directory (somewhere inside the user directory) when you open a form. When it copies the assemblies it ignores the linked resources and by this the native .DLL!

进一步的调查表明,Wrapper .DLL总是找到原生的.DLL ......这是好事。不好的是,当您打开表单时,Visual Studio Designer会将所需的程序集复制到临时目录(用户目录中的某个位置)。当它复制程序集时,它会忽略链接的资源,并通过本机.DLL!

#3


Sounds like you have two specific issues:

听起来你有两个具体问题:

  1. How to copy over the native code dlls before the build starts
  2. 如何在构建开始之前复制本机代码dll

  3. How to dynamically figure out the native code dependancies that need to be copied over in case they change.
  4. 如何动态地找出需要复制的本机代码依赖项,以防它们发生变化。

For 1), you could use a pre-build step in your C# project to call a custom util to copy over the correct files.

对于1),您可以在C#项目中使用预构建步骤来调用自定义util来复制正确的文件。

Looks like 2) has already been answered here on Stack Overflow.

看起来2)已经在Stack Overflow上得到了解答。

#4


Well, you could simply add commands to automatically copy the required DLLs into the correct output directory, as part of the Build process. This is done in Visual Studio by going to the project's properties.

好吧,您可以简单地添加命令以自动将所需的DLL复制到正确的输出目录中,作为构建过程的一部分。这是通过转到项目的属性在Visual Studio中完成的。

Project -> MyProjectName Properties... -> Build Events

项目 - > MyProjectName属性... - >构建事件

Add the commands to copy the files you need into the $(TargetPath) and you're done.

添加命令将您需要的文件复制到$(TargetPath)中,然后就完成了。

Another option would be to simply set the current working directory of your project (when you're running it from within Visual Studio only) to be the directory in which all the DLLs you need reside. You'll still have to manually copy the files when executing the program externally, but it will make development a little easier.

另一种选择是简单地将项目的当前工作目录(当您从Visual Studio中运行它时)设置为您需要的所有DLL所在的目录。在外部执行程序时,您仍然需要手动复制文件,但这会使开发变得更容易。