如何解压缩 Fody.Costura 打包的程序集

How to decompress a Fody.Costura packed assembly

我的一个朋友给了我一个挑战,要我解压一个装有 Fody.Costura 的程序集。该程序集具有作为资源嵌入的 dll 依赖项。我尝试用 dotPeek 提取这个 .zip 资源并用这里的代码解压它

public static void Decompress(string path)
{
    using (var stream = File.OpenRead(path))
    using (var compressStream = new DeflateStream(stream, CompressionMode.Decompress))
    {
        compressStream.Seek(0, SeekOrigin.Begin);
        var fs = File.Create(path + ".decompressed");
        compressStream.CopyTo(fs);
        fs.Close();
    }
}

这在提取 .zip 时有效,但结果非常无用

是否有合适的解决方案来解压缩这个打包的 dll?

Costura 用来解压这些资源的代码在这里。

https://github.com/Fody/Costura/blob/master/src/Costura.Template/Common.cs

static void CopyTo(Stream source, Stream destination)
{
    var array = new byte[81920];
    int count;
    while ((count = source.Read(array, 0, array.Length)) != 0)
    {
        destination.Write(array, 0, count);
    }
}

static Stream LoadStream(string fullname)
{
    var executingAssembly = Assembly.GetExecutingAssembly();

    if (fullname.EndsWith(".zip"))
    {
        using (var stream = executingAssembly.GetManifestResourceStream(fullname))
        using (var compressStream = new DeflateStream(stream, CompressionMode.Decompress))
        {
            var memStream = new MemoryStream();
            CopyTo(compressStream, memStream);
            memStream.Position = 0;
            return memStream;
        }
    }

    return executingAssembly.GetManifestResourceStream(fullname);
}

要解压缩这些资源,有 this 个项目。

这是我简单的 C# 控制台应用程序代码(框架 4),我只是通过 "drag and drop"(Costura 压缩)文件编译(ConsoleApp1)可执行文件来使用它。

using System;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text.RegularExpressions;

namespace ConsoleApp1
{
  class Program
  {
    static void CopyTo(Stream source, Stream destination) {
      int count;
      var array = new byte[81920];
      while ((count = source.Read(array, 0, array.Length)) != 0) {
        destination.Write(array, 0, count);
      }
    }

    static Stream LoadStream(string fullname) {
      FileStream stream = default(FileStream);
      if (fullname.EndsWith(".zip")) {
        using (stream = new FileStream(fullname, FileMode.Open)) {
          using (var compressStream = new DeflateStream(stream, CompressionMode.Decompress)) {
            var memStream = new MemoryStream();
            CopyTo(compressStream, memStream);
            memStream.Position = 0;
            return memStream;
          }
        }
      }
      return stream;
    }

    static void Main(string[] args) {
      Stream stream; Stream file;
      string RefilePath = @"^.+[^\]+\"; string fullname; string newFile;
      for (int i = 0; i < args.Count(); i++) {
        fullname = args[i];
        newFile = Regex.Replace(fullname, "\.zip$", string.Empty);
        Console.Write("{0} -> {1}\r\n",
          Regex.Replace(fullname, RefilePath, string.Empty),
          Regex.Replace(newFile, RefilePath, string.Empty));
        try
        {
          stream = LoadStream(fullname);
          using (file = File.Create(newFile)) {
            CopyTo(stream, file);
          }
        }
        catch (Exception ex) {
          Console.Write("{0}", ex.ToString());
        }
      }
    }
  }
}

基于