Using 7zSharp which spawns processes

Coordinator
Nov 25, 2007 at 2:10 PM
Edited Nov 25, 2007 at 2:47 PM
For now, 7zSharp.dll is a thin wrapper around 7z.exe located at C:\Program Files\7-zip\7z.exe. In the future, without changing the API, 7zSharp.dll will directly link to 7z source code to create a fully contained Compression and Decompression engine. For now, we span processes to execute the compression or decompression.

To change the location of the executable, do the following:

ICompressionEngine engine = SevenZSharp.CompressionEngineFactory.Default.GetCompressionEngine();
ShellEngine shellEngine = engine as ShellEngine;
if (shellEngine != null)
{
    shellEngine.Seven7Location = @"\7-zip\7za.exe";
}
engine.Encoder.EncodeFromDirectory(@"C:\temp", @"C:\temp.zip");
Jan 26, 2008 at 8:34 PM
Hi!
I think that there is really a need for this project as 7z on one hand is undoubtedly the most efficient compression available while on the other hand the 7z SDK has NO USABLE DOCUMENTATION AT ALL and it's not so easy to just "use it" in .NET languages. This wrapper is a very good thing and most usable! Thank you!

Of course a pure managed DLL would be nice to have - only one file instead of the .NET DLL plus the 7za.exe - but there would be a performance loss as c++ code is - sad but true - a lot faster than the .NET code.
Maybe a .NET DLL using the methods from a COM DLL (C+) instead of an .exe would be also great, but I cannot find a dll version of the c+ 7z and I am not a c++ programmer, so that I could make one from source :(
I also would be willing to contribute, but I don't have the slightest clue about compression algorithms :(
Right now I am facing the choice of a compression library for a small c# project and it's between the SharZipLib an 7z. I really would like to use 7z as it's superior to all others but the usage is - at the moment - simply a pain.

Thanks for this nice Wrapper and I hope it will be continued, used and appreciated by the community!
Coordinator
Jan 26, 2008 at 9:32 PM
Hey Wintermute, thanks for the comment!

Well, I started off by wrapping the C# 7Z SDK (http://www.7-zip.org/sdk.html), because I agree it is not quite so obvious. But then I realized that I also needed the rest of the power of 7Z in all of the other formats it supports. So the way 7zSharp works is that if you are using LZMA compression or decompression, then it is all done in the .NET runtime; otherwise, it launches the 7za.exe.

Of course, I'd like to convert 7z to managed code or call out to a COM dll. I like your idea of a COM DLL because there are very few context switches over the COM calls, and not much to marshall. From what I understand, 7Z is a pseudo-COM dll and is used by commercial products such as WinRAR as a COM DLL. When I first started the project, I investigated this, but I did not have much time, and could not figure out how to call the "non-standard" COM conventions.

So, to answer your question, if you are only using 7Z (.7z) compression/decompression, you can simply do:

ICompressionEngine engine = SevenZSharp.CompressionEngineFactory.Default.GetCompressionEngine(CompressionType.LZMA);

This will actually return a SevenZSharp.Lzma.LzmaCompressionEngine instead of a SevenZSharp.ShellEngine. The ShellEngine is the one which spawns 7za. The LzmaCompressionEngine is completely .NET, although the LzmaEncoder class does not yet support (De)EncodeFromDirectory, only (De)EncodeSingleFile.

Anyway, that was a complicated answer, but basically: I agree with you, but I do not have much time right now to make this project more powerful :). Once I have time though, I will implement exactly what you are looking for, because I am interested in the same thing. It hurts to spawn a process each time.

Any help is appreciated,

Thanks,
Kevin
Jan 27, 2008 at 5:45 AM
Edited Jan 27, 2008 at 5:57 AM
Wow!
I am deeply impressed by your quick response :)

Ok, here is my 1st little contribution: I found a very small bug, so sorry ;)

If 7z is not on the target machine under program files, your first post suggests to set shellEngine.Seven7Location = @"\7-zip\7za.exe"; to point to the deviating location of the exe, but the GetShellProcess() Method in ShellEngine.cs ignores this and it doesn't use the assigned private field m_7zLocation so setting the location of the 7z.exe isn't working as expected.

Just change ShellEngine.cs line 50 from
process.FileName = @"C:\Program Files\7-Zip\7z.exe";
to
process.FileName = m_7zLocation;
and everything works fine with the exe in another location.

Tested on XP Pro 32 Bit and Vista Business 32 Bit

Another thing to consider might be using Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) instead of "C:\Program Files\" as default, because names vary depending on language of operating system. My German XP uses "C:\Programme\" as default while Vista is more english and sticks to "program files" in all languages, however.
Don't get me wrong, I do not want to criticize, just help; I like your software much, already.

btw: why is it called Seven7Location and not SevenZLocation? - ok, I'm getting nosy, nevermind, drank to muche coke ;)
Funny coincidence: we carry the same first name


Have a nice weeekend,

Kevin
Jan 29, 2008 at 4:41 AM
Edited Jan 29, 2008 at 4:46 AM
How I encode and split to volumes?

-oops, don't reply here, I create new discussion
Coordinator
Jan 30, 2008 at 8:28 AM
This discussion has been copied to a work item. Click here to go to the work item and continue the discussion.
Coordinator
Jan 30, 2008 at 12:19 PM
Hi, I have created a new release (1.0.2) which addresses the 3 coding errors you brought up. Thanks for finding those! Don't worry about "criticizing," it is good feedback.

I have refactored a lot of the structure, with two things worth noting:

  1. Removed ICompressionEngineFactory and moved everything into the CompressionEngine class, so the code now becomes:

// encode:
CompressionEngine.Current.Encoder.EncodeFromDirectory(@"C:\someDirectory", "C:\out\someDirectory.7z");
 
// decode:
CompressionEngine.Current.Decoder.DecodeIntoDirectory(@"C:\out\someDirectory.zip", "C:\someDirectory"); 

The default compression engine is a "delegation" compression engine which will pass calls on depending on the types of files to be compressed. Right now it passes to ShellEngine, but may pass onto the LZMA compression engine, or others. The purpose of this change is so that the user of the library doesn't have to worry about instantiating the right engine depending on the file type.

  1. No longer need to cast the engine as a ShellEngine to change the path to 7z, just do:

CompressionEngine.SetOptions("Some other location");

Thanks!
Kevin