Перемещение зависимостей для моего приложения вызывает исключение System.IO.FileNotFoundException - PullRequest
0 голосов
/ 13 февраля 2020

Я пытаюсь очистить папку Release, чтобы у файлов зависимостей была какая-то организация. Моя цель в этом случае состоит в том, чтобы собрать все зависимости, которые мне нужны для моего модуля сжатия, в одну папку. Для этой первой части моей новой библиотеки классов я просто пытаюсь поддерживать файлы 7zip. Я делаю это с помощью SevenZipSharp.Interop NuGet , который зависит от SevenZipSharp NuGet .

. По умолчанию вышеупомянутая сборка NuGets приводит к моим папкам Release / Debug и выглядит как следующее ...

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

Поскольку я добавляю больше поддержки в мою библиотеку классов, я хочу убедиться, что у всех есть своя собственная папка и т. д. c. Итак, я хочу организовать это следующим образом ...

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

Я делаю это, выполняя несколько команд POST BUILD, и после сборки проекта я получаю структуру, которую я хочу выше (последняя). Тем не менее, при отладке, после того, как я скомпилировал и произошла команда POST BUILD, приложение пытается запуститься, и я получаю ошибку System.IO.FileNotFoundException, сообщающую, что не может найти SevenZipSharp.dll. Я знал, что это произойдет в глубине души, но надеялся, что есть способ сообщить приложению о новом местоположении зависимостей.

Можно ли переместить файлы, а затем сообщить моему приложению, что они как-то в другом месте?

1 Ответ

0 голосов
/ 26 февраля 2020

В итоге я использовал пакет NuGet Costura.Fody (хранилище найдено здесь ). То, как он оборачивает зависимости в вашем модуле класса (или программе), не что иное, как magi c. При использовании Costura.Fody он будет искать любые зависимости и автоматически сжимать их в вашу библиотеку классов dll, создавая одну dll. Затем все ссылки на ресурс будут указывать на встроенные ресурсы в вашей dll. Все, что вам нужно сделать, это добавить два пакета NuGet, и он выполнит всю работу при сборке проекта. Это действительно отлично!

Важное примечание: Fody's (зависимость 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). Вы делаете это, добавляя следующие папки в root вашего проекта, а также соответствующие файлы архитектур. Затем добавьте их как Build Action: Embedded Resource.

enter image description here

Это позволит извлечь зависимость 7zip.dll во время выполнения при необходимости, чтобы я мог ссылаться на путь, когда используя библиотеку SevenZipSharp. На данный момент я не выяснил, как получить ссылку на каталог (C83815D61CE49B2E8D23145A1B95A956, может быть, контрольную сумму всех файлов в самом каталоге?), Который он использует, но в моем случае это где его извлекали в ...

%tmp%\Costura\C83815D61CE49B2E8D23145A1B95A956\32\ enter image description here

Обновление: я нашел обходной путь для получения пути к этому каталогу, подобному контрольной сумме, используя информацию о сборке. Я создал следующую функцию, чтобы попытаться установить путь к библиотеке 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.");
...