Skip to content
This repository has been archived by the owner on Nov 1, 2020. It is now read-only.

How to use the System.IO.Compression namespace ? #5496

Open
brunomlopes opened this issue Mar 5, 2018 · 12 comments
Open

How to use the System.IO.Compression namespace ? #5496

brunomlopes opened this issue Mar 5, 2018 · 12 comments
Milestone

Comments

@brunomlopes
Copy link

Say I've got the following core on a .net core console app:

        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
            using(var stream = File.OpenRead(args[0]))
            using (var compressed = new ZipArchive(stream, ZipArchiveMode.Read))
            {
                foreach (var zipArchiveEntry in compressed.Entries)
                {
                    using (var fileStream = zipArchiveEntry.Open())
                    using (var outputStream = new MemoryStream())
                    {
                        fileStream.CopyTo(outputStream);
                    }

                    Console.WriteLine($"Wrote {zipArchiveEntry.FullName}");
                }
            }
        }

If I compile it with dotnet publish -c Release -r win-x64, and try to run it with CoreRt.TestCompression.exe ..\sample-zip.zip, it fails with

Unhandled Exception: System.IO.Compression.ZLibException: The underlying compression routine could not be loaded correctly. ---> System.DllNotFoundException: Unable to load DLL 'clrcompression.dll': The specified module could not be found.
   at CoreRt.TestCompresssion!<BaseAddress>+0x11d293
   at CoreRt.TestCompresssion!<BaseAddress>+0x11d1b0
   at Interop.zlib.inflateInit2_(Byte*, Int32, Byte*, Int32) + 0x42
   at Interop.zlib.InflateInit2_(ZLibNative.ZStream&, Int32) + 0x49
   at System.IO.Compression.ZLibNative.ZLibStreamHandle.InflateInit2_(Int32) + 0x29
   at System.IO.Compression.Inflater.InflateInit(Int32) + 0x40

From a quick search, this looks like clrcompression.dll is native code that doesn't get pulled in?
Is there anything I can do to work past this?

@jkotas
Copy link
Member

jkotas commented Mar 5, 2018

We have not done the work to link clrcompression into the final binary.

The workaround is to copy clrcompression.dll next the native .exe. E.g. publish the app as regular standalone app using
dotnet.exe" publish -c Release -r win-x64 /p:NativeCompilationDuringPublish=false first, save clrcompression.dll that got published, and then publish it again as native and copy clrcompression saved earlier next to the native .exe.

This workaround won't give you a single file native binary. Is it something that you need to have?

@MichalStrehovsky MichalStrehovsky added this to the Preview milestone Mar 5, 2018
@brunomlopes
Copy link
Author

Thanks, the workaround works.

I'd prefer a single binary, but a binary and a dll is good enough and a large improvement.
I mostly wanted to reduce the number of files in the final folder, and take advantage of faster startup.

brunomlopes added a commit to brunomlopes/nuget.vendor that referenced this issue Mar 6, 2018
clrcompression needs to be manually copied beside the final .exe, but other than that, it's a single .exe file which can take nugets and de-compresses them.
See dotnet/corert#5496

Also, it can decompress into long paths!
@wieslawsoltes
Copy link

I have run into same issue:

The underlying compression routine could not be loaded correctly.
   at System.IO.Compression.Inflater.InflateInit(Int32) + 0x1ba
   at System.IO.Compression.DeflateStream.InitializeInflater(Stream, Boolean, Int32) + 0x3e
   at System.IO.Compression.ZipArchiveEntry.GetDataDecompressor(Stream) + 0x3d
   at System.IO.Compression.ZipArchiveEntry.OpenInReadMode(Boolean) + 0x86
   at Core2D.Containers.ProjectContainer.ReadProject(ZipArchiveEntry, IFileSystem, IJsonSerializer) + 0x1b
   at Core2D.Containers.ProjectContainer.Open(Stream, IFileSystem, IJsonSerializer) + 0xa6
   at Core2D.Containers.ProjectContainer.Open(String, IFileSystem, IJsonSerializer) + 0x39
   at Core2D.Editor.ProjectEditor.OnOpenProject(String) + 0xfe

Copying the clrcompression.dll dll fixes the issue for now.

@jkotas
Copy link
Member

jkotas commented Apr 23, 2018

The work required for this:

@ShayeHorwitz
Copy link

The recommended workaround isn't working for me. I just get an error message that says System.EntryPointNotFoundException: Unable to find an entry point named 'CompressionNative_DeflateInit2_' in DLL 'clrcompression.dll'.

The DLL in question is labeled as version 4.6.26515.6, if it matters, and dotnet --version reports 2.1.300.

@jkotas
Copy link
Member

jkotas commented Jun 25, 2018

clrcompression.dll needs to be in sync with the rest of framework bits. Here is how you can get the right bits manually at the moment:

I am adding the good clrcompression.dll to CoreRT package in #6009. It will make this workaround easier (binplace it from the CoreRT package, no need to fish for the right version).

MichalStrehovsky pushed a commit that referenced this issue Jun 25, 2018
This makes it easier to work around #5496
@jkotas
Copy link
Member

jkotas commented Feb 21, 2019

The workaround for now is to add this snippet to your .csproj file:

  <Target Name="CopyClrCompressionDll" AfterTargets="Publish">
    <Copy SourceFiles="$(IlcPath)\framework\clrcompression.dll" DestinationFolder="$(PublishDir)" />
  </Target>

@NotoriousRebel
Copy link

Bumping as I just ran into this issue. Would adding clrcompression.dll as a reference dll solve this issue for a temporary workaround to produce a single binary?

@NotoriousRebel
Copy link

The answer was no
image

@NotoriousRebel
Copy link

@brunomlopes have you tried again since the most recent merge?

@brunomlopes
Copy link
Author

Not yet, my use case for this has been running ok with the previous workaround, and hadn't had a reason to revisit it.

@ryancheung
Copy link

The workaround for now is to add this snippet to your .csproj file:

  <Target Name="CopyClrCompressionDll" AfterTargets="Publish">
    <Copy SourceFiles="$(IlcPath)\framework\clrcompression.dll" DestinationFolder="$(PublishDir)" />
  </Target>

If you are in Linux, the following would be neat:

  <Target Name="CopyClrCompressionDll" AfterTargets="Publish" Condition="'$(OS)' != 'Unix'">
    <Copy SourceFiles="$(IlcPath)\framework\clrcompression.dll" DestinationFolder="$(PublishDir)" />
  </Target>

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

7 participants