0

我正在尝试清理我的 Release 文件夹,以便依赖文件对它们具有某种类型的组织。在这种情况下,我的目标是将压缩模块所需的所有依赖项包含在一个文件夹中。对于我的新类库的第一部分,我只是想支持 7zip 文件。我使用SevenZipSharp.Interop NuGet执行此操作,它依赖于SevenZipSharp NuGet

默认情况下,上面的 NuGet 构建结果在我的 Release/Debug 文件夹中,如下所示...

Release
|- x64
| `- 7z.dll
|- x86
| `- 7z.dll
|- SevenZipSharp.dll
`- compressionmodule.dll

当我向我的类库添加更多支持时,我想确保所有内容都有自己的文件夹等。所以,我想按以下方式组织它......

Release
|- compressionmodule
| `- 7zip
|   |- x64
|   | `- 7z.dll
|   |- x86
|   | `- 7z.dll
|   `- SevenZipSharp.dll
`- compressionmodule.dll

我通过运行一些 POST BUILD 命令来做到这一点,一旦项目构建,我就会得到上面想要的结构(后者)。但是,在调试时,在我编译并发生 POST BUILD 命令后,应用程序尝试运行,但我收到一条System.IO.FileNotFoundException错误消息,告诉我它找不到SevenZipSharp.dll. 我知道这会发生在我的脑海中,但希望有一种方法可以让应用程序知道依赖项的新位置。

是否可以重新定位文件,然后让我的应用程序知道它们以某种方式位于不同的位置?

4

1 回答 1

0

我最终使用了NuGet 包 Costura.Fody(在此处找到存储库)。它在您的类模块(或程序)中包装依赖项的方式简直就是魔术。使用 Costura.Fody 时,它会查找任何依赖项并自动将它们压缩到您的类库 dll 中,从而生成单个 dll。然后它将使对资源的所有引用指向您的 dll 中的嵌入资源。您需要做的就是添加两个 NuGet 包,它会在您构建项目时完成所有工作。真的很滑!

重要提示:Fody(运行 Costura.Fody 所需的 Costura.Fody 的依赖项)当前版本仅与 Visual Studio 2019(使用 MSBuild 16)兼容。就我而言,我有 Visual Studio 2017(它使用 MSBuild 15)。我不得不使用 Costura.Fody仍然使用旧 MSBuild 的旧版本。这也要求我降级Fody。所以我最终使用了适用于 MSBuild 15 的最新版本。Fody 版本 4.2.1 和 Costura.Fody 版本 3.3.3 非常适用于 Visual Studio 2017。

如果需要,它甚至支持提取资源。例如,我希望在SevenZipSharp图书馆中使用它。它需要一个7zip.dll要使用的文件的路径。因此,我在FodyWeavers.xml与您的解决方案位于同一目录中的文件中使用了以下内容。

<?xml version="1.0" encoding="utf-8"?>
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
  <Costura CreateTemporaryAssemblies='true' IncludeDebugSymbols='false'>
    <Unmanaged32Assemblies>
      7z
    </Unmanaged32Assemblies>
    <Unmanaged64Assemblies>
      7z
    </Unmanaged64Assemblies>
  </Costura>
</Weavers>

您还需要在项目中包含 7zip.dll,以便编译 dll,因为它们不像资源那样使用(就像 SevenZipSharp 库一样)。为此,您可以在项目的根目录中添加以下文件夹以及相应的架构文件。然后将它们添加为Build Action: Embedded Resource.

在此处输入图像描述

这将在需要时在运行时提取 7zip.dll 依赖项,因此我可以在使用 SevenZipSharp 库时引用该路径。在这一点上,我还没有找到如何获取对它使用的(C83815D61CE49B2E8D23145A1B95A956 可能是目录本身中所有文件的校验和?)目录的引用,但在我的情况下,这是将其提取到的位置...

%tmp%\Costura\C83815D61CE49B2E8D23145A1B95A956\32\ 在此处输入图像描述

更新:我找到了一种解决方法来获取该校验和的路径,例如使用程序集信息的目录。我创建了以下函数来尝试设置 7Zip 库路径。它可能对某些人有帮助,所以我把它包括在这里。

private bool SetupSevenZipLibrary()
{
    string costuraExtractionPath = null;

    try
    {
        //This will use the embeded resource to try and set a base path to the extraction
        //location created by by Costura.Fody
        string sevenZipAssembly = typeof(SevenZip.ArchiveFileInfo).Assembly.Location;
        if (File.Exists(sevenZipAssembly))
            costuraExtractionPath = Path.GetDirectoryName(sevenZipAssembly);
    }
    catch
    {
        //Issue trying to grab the extraction path from the Assembly information so try
        //to use the first path found in the Costura directory as a last ditch effort

        DirectoryInfo di = null;

        string costuraTempPath = Path.Combine(
            Path.GetTempPath(), //ex: C:\Users\username\AppData\Local\Temp
            "Costura" //ex: Costura
        );

        di = new DirectoryInfo(costuraTempPath);
        if (!di.Exists)
            return false;
        //ex: C:\Users\username\AppData\Local\Temp\Costura\C83815D61CE49B2E8D23145A1B95A956\
        costuraExtractionPath = di.GetDirectories().First().FullName;
    }

    try
    {
        if (!Directory.Exists(costuraExtractionPath))
            throw new Exception();

        string sevenZipPath = Path.Combine(
            costuraExtractionPath, //ex: C:\Users\username\AppData\Local\Temp\Costura\C83815D61CE49B2E8D23145A1B95A956
            Environment.Is64BitProcess ? "64" : "32", //ex: 32
             "7z.dll" //ex: 7z.dll
        );

        if (!File.Exists(sevenZipPath))
            throw new Exception();

        SevenZipBase.SetLibraryPath(sevenZipPath);
        return true;
    }
    catch { return false; }
}

是使用...

if (!SetupSevenZipLibrary())
    throw new Exception("Error setting the path of the 7zip library.");
于 2020-02-26T14:32:00.247 回答