Good day! Something prohibitively long poking around with a seemingly foolish venture ...

The task is to dynamically load the assembly SevenZipSharp.dll (a known library for working with archives ), then create an instance of SevenZipExtractor(string ArchiveFullName) and call the ExtractArcive(string directory) method ExtractArcive(string directory) , which should unpack the specified archive into the specified directory.

I do this:

 //Π’Π°ΠΊ ΠΊΠ°ΠΊ зависимостСй Ρƒ Π»ΠΈΠ±Ρ‹ Π½Π΅Ρ‚, Ρ‚ΠΎ Π³Ρ€ΡƒΠΆΡƒ сборку ΠΈΠ· рСсурсов Π² массив Π±Π°ΠΉΡ‚, минуя Π²Ρ‹Π³Ρ€ΡƒΠ·ΠΊΡƒ Π² Ρ„Π°ΠΉΠ». var resourceBuffer = Properties.Resources.ResourceManager.GetObject(resnameSevenZipSharpLibrary) as byte[]; Assembly _SevenZipSharp = Assembly.Load(resourceBuffer); //Π‘Π±ΠΎΡ€ΠΊΠ° ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎ загруТаСтся, ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌ ΠΈΠ½Ρ„ΠΎ ΠΏΠΎ Ρ‚ΠΈΠΏΡƒ SevenZip.SevenZipExtractor var extaractorClassType = _SevenZipSharp.GetType(SevenZip_ExtractorClassName); string ArchiveFullPath = "D:\\TEST.ARJ"; //ΠŸΡ€ΠΎΠ±ΡƒΠ΅ΠΌ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ экзСмпляр класса, ΠΏΠ΅Ρ€Π΅Π΄Π°Π² ΠΎΠ΄Π½ΠΎΠΌΡƒ ΠΈΠ· конструкторов Π² качСствС Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚Π° ΠΏΠΎΠ»Π½ΠΎΠ΅ имя Π°Ρ€Ρ…ΠΈΠ²Π°: var Extractor = Activator.CreateInstance(extaractorClassType, new object[] { ArchiveFullPath }); 

Actually, this is where the application crashes:

 System.Reflection.TargetInvocationException ("АдрСсат Π²Ρ‹Π·ΠΎΠ²Π° создал ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅.") ... Inner excepton: System.TypeInitializationException ("Π˜Π½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ‚ΠΎΡ€ Ρ‚ΠΈΠΏΠ° "SevenZip.SevenZipLibraryManager" Π²Ρ‹Π΄Π°Π» ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅.") Π² SevenZip.SevenZipLibraryManager.LoadLibrary(Object user, Enum format) Π² SevenZip.SevenZipExtractor.Init(String archiveFullName) Π² SevenZip.SevenZipExtractor..ctor(String archiveFullName) Inner excepton: System.ArgumentException ("ΠŸΡƒΡ‚ΡŒ ΠΈΠΌΠ΅Π΅Ρ‚ Π½Π΅Π΄ΠΎΠΏΡƒΡΡ‚ΠΈΠΌΡƒΡŽ Ρ„ΠΎΡ€ΠΌΡƒ.")` 

If you set, for example, the path as ArchiveFullPath = "TEST.ARJ" , then it will ArchiveFullPath = "TEST.ARJ" error file not found (which is completely logical, because there is CurrentDirectory archive in CurrentDirectory ). Those. the path in the form of a short file name, he seems to be chewing, but if you specify a disk, he no longer wants.

Perhaps someone faced a similar problem, or maybe something is not doing. I already had an eye on my eyes, tried differently, through GetConstructor , for example.

Of course, it doesn't even get to the call to the ExtractArchive method.

Yes, I know that you can add a link to the assembly to the project before compiling, and use the classes from the SevenZip namespace unhindered, please do not offer this option. One could do so - the brain would not float and do it right away.

Thanks for attention!

  • one
    If to cause legally - the problem manifests itself? - Monk
  • No, there is no problem, otherwise there would be no question. In a test project, I refer to the link via Referencies, it works quite well without any problems like this: using (var arj = new SevenZipExtractor(arjArchiveName)) { arj.ExtractArchive(targetDir); } using (var arj = new SevenZipExtractor(arjArchiveName)) { arj.ExtractArchive(targetDir); } - BlackWitcher

1 answer 1

The situation was decided somewhat differently, the desired result was achieved in a different way. The solution was inspired by this issue , but does not affect the Build Action and the EmbeddedResource along with the AssemblyResolve event.

Total:

  1. SevenZipSharp.dll was attached to the resources of the project itself, i.e. inside the assembly: Project -> Properties -> Resources along with 7z.dll, which is necessary for the operation of SevenZipSharp.dll.

  2. Links to assemblies (References) have added a link to the SevenZipSharp.dll file. In the properties of the link, Copy Local = False was set so that when building the project, this assembly was not copied to the same place as the main project binary. Everything, now you can use the namespace SevenZip in the code and create any objects without attracting reflection.

  3. A simple method was written that takes and extracts resources from a project to disk as files. Yes, it was possible to directly save each resource, referring to it, for example, like this: byte[] lib = Properties.Resources.SevenZipSharp; . But I wanted to upload the file by the resource name and reuse this method again:

     private static bool ExtractBinaryResourceToFile(string resourceName, string filename) { if (string.IsNullOrEmpty(resourceName)) { throw new ArgumentNullException(resourceName, "НС ΡƒΠΊΠ°Π·Π°Π½ΠΎ имя ΠΈΠ·Π²Π»Π΅ΠΊΠ°Π΅ΠΌΠΎΠ³ΠΎ рСсурса."); } if (string.IsNullOrEmpty(filename)) { throw new ArgumentNullException(filename, "НС ΡƒΠΊΠ°Π·Π°Π½ΠΎ имя Ρ„Π°ΠΉΠ»Π°, Π² ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΡΠΎΡ…Ρ€Π°Π½ΡΡ‚ΡŒ рСсурс."); } var resourceBuffer = Properties.Resources.ResourceManager.GetObject(resourceName) as byte[]; if (resourceBuffer == null) return false; try { File.WriteAllBytes(filename, resourceBuffer); } catch (Exception e) { throw e; //ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Π² ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΈ Π΅ΡΡ‚ΡŒ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ошибок, Ρ‚ΠΎ просто Π³Π΅Π½Π΅Ρ€ΠΈΠΌ ΠΎΡˆΠΈΠ±ΠΊΡƒ, ΠΊΠΎΡ‚ΠΎΡ€ΡƒΡŽ ΠΎΠ½ ΠΎΡ‚Π»ΠΎΠ²ΠΈΡ‚. } return File.Exists(filename); } 
  4. Working with SevenZipSharp is quite simple, like this:

      using (var arj = new SevenZip.SevenZipExtractor(ArchiveFullPath)) { arj.ExtractArchive(TargetDir); } 
  5. PROFIT !! 1

Since I have a number of limitations in the project (the solution should look like ONE DLL, which, in turn, is an application module), I had to do this. Therefore, when you initialize your module, you have to unpack and save 7z.dll and SevenZipSharp.dll into the same folder where the main module is located (the same one in which all this stuff is stored).

Then in this case the AssemblyResolve handler of the main application sees the SevenZipSharp.dll library, and that, in turn, perfectly sees 7z.dll even without explicitly specifying the path to SevenZipExtractor.SetLibraryPath() .

Perhaps I missed something, but could not come up with another solution to the situation. For even if you load the assembly SevenZipSharp.dll directly from resources in AssemblyResolve , but this is unlikely to happen with unmanaged 7z.dll.

Because of this, when my assembly is initialized, the necessary libraries are downloaded from the resources of the main assembly to files.