【问题标题】:Add a Reference from a C# App to a DLL compiled without /clr?将 C# 应用程序的引用添加到没有 /clr 编译的 DLL?
【发布时间】:2010-01-18 17:18:46
【问题描述】:

我正在使用 Visual Studio 2008 构建一个包含两个项目的解决方案:一个 C# 控制台应用程序和一个 C++ DLL。我希望应用程序使用 P/Invoke 从 dll 调用一个函数。因此,我尝试将 dll 添加为对 C# 应用程序的引用。但是当我尝试添加引用命令时,Visual Studio 不会让我这样做,除非我在 dll 上设置 /clr 属性(在配置属性:常规下)。现在,我认为 P/Invoke 可以处理普通的 win32 dll。事实上,如果我在没有 /clr 的情况下构建我的 dll 并手动将其复制到 bin/Debug,那么应用程序运行良好。那么为什么需要 /clr 来添加 dll 作为参考呢?如果 VS 不让我添加它,是否有一些(干净的)解决方法以便我的应用找到 dll?

我看到有人在这里遇到了类似的问题(尽管使用的是第 3 方 dll): Unable to add a DLL Reference to VS 2008 他得到的答案是构建一个包装器。但这并不是必需的,因为应用程序可以很好地使用 dll;只是“添加引用”步骤不起作用。此外,包装代码是否不需要引用 dll,从而引发与以前相同的问题?我真的很想要一个完全不涉及编写包装器的答案。

【问题讨论】:

    标签: c# c++ visual-studio visual-studio-2008 pinvoke


    【解决方案1】:

    为什么不添加一个构建后步骤来将非托管 DLL 复制到项目目录?您不需要“引用”即可引用非托管 DLL,听起来您遇到的唯一问题是由于文件未自动复制到搜索路径中。

    【讨论】:

    • 我使用这个命令行为 C# 应用程序编写了一个预构建步骤:复制“$(SolutionDir)Debug\MathDll.dll”“$(TargetDir)”。唉,我希望“添加引用”功能能够正常工作,因为现在我必须维护它,而且我想发布版本会有所不同......我真的不明白为什么“添加引用”不应该处理这种事情。
    • 我刚刚找到了一种更简洁的方法。我没有使用构建前/构建后的 DOS 命令,而是将 dll 作为“现有项”添加到 C# 项目中。然后在其属性下,我将“复制到输出目录”设置为“如果更新则复制”。 (它的“构建操作”是“内容”。)这对我来说似乎仍然有点骇人听闻,但至少它解决了 Debug-vs-Release 问题,并且更容易发现。
    • 糟糕——我意识到我的第二个解决方法不能解决 Debug-vs-Release 问题,因为我从 Debug 文件夹中引用了 dll。另一方面,第一个解决方法可以通过将命令更改为复制“$(SolutionDir)$(Configuration)\MathDll.dll”“$(TargetDir)”来解决此问题。
    • @Paul 我使用了 copy "$(ProjectDir)Resources\*" "$(TargetDir)" 因为我将 DLL 放在了资源目录中。 VS 识别的“$...”列表在哪里?
    • 小心检查 errorlevel 在构建后步骤中的 each 批处理命令之后,因为 MSBuild 会忽略除最后一个命令之外的所有命令的错误代码 (read more)
    【解决方案2】:

    在 C++ DLL 上使用 PInvoke 时,无需添加引用。只有在调用另一个 DLL 中的托管代码时才需要引用。只需将 C++ DLL 放在同一目录中,并将其名称添加到 DllImport 属性中

    【讨论】:

      【解决方案3】:

      理论上,您可以将 C++-DLL 作为链接资源添加到您的 C#-DLL。这将使.NET 将您的 C++-DLL 复制到将 C#-DLL 复制到 GAC 的任何位置。 理论上意味着有一些缺点:

      • 您可以通过命令行选项指示 C# 编译器 (csc.exe) 添加链接资源,但我从未找到通过 .csproj 文件甚至 Visual Studio 执行此操作的方法
      • 如果 C#-DLL 包含 WinForms 用户控件并且您想在设计器中使用它,它将无法工作,因为 Winforms-Designer 会将 C#-DLL 复制到加载它的临时位置,但它会忽略链接的资源。
      • 我不知道如果您将 C#-DLL 放入 GAC 是否有效(是的,C++-DLL 也将作为资源放入,但我不知道在运行您的 C# 时是否找到它- DLL!)

      因此,如果以上都不适合您,您可以调用 csc.exe 如下:

      csc.exe ... /linkresource:cpp.dll
      

      希望这会有所帮助!

      【讨论】:

        【解决方案4】:

        通过执行以下操作解决了类似问题:

        1. 在所有开发机器上,将相关 dll-s 的路径添加到 PATH 环境变量中。这样,所有开发人员都可以使用非托管 dll-s 调试所有引用程序集的可执行文件,而无需为每个可执行文件编写构建后脚本。

        2. 对于生产,每晚 msbuild 任务将所有内容构建到单个文件夹中,并且标记为“内容/始终复制”的非托管 dll-s 会自动包含在它们所属的一个程序集的构建中的。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-05-04
          • 1970-01-01
          • 1970-01-01
          • 2011-09-07
          相关资源
          最近更新 更多