Skip to content

Commit

Permalink
✨ 7-Zip.NativeAssets
Browse files Browse the repository at this point in the history
  • Loading branch information
AigioL committed May 16, 2024
1 parent 4078960 commit 3f789cf
Show file tree
Hide file tree
Showing 12 changed files with 177 additions and 40 deletions.
9 changes: 5 additions & 4 deletions SevenZip.Tests/FileCheckerTests.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
namespace SevenZip.Tests
namespace SevenZip.Tests
{
using System.Collections.Generic;
using System.IO;

using SevenZip;

using NUnit.Framework;
using System;

/// <summary>
/// Test data to use for CheckFileSignatureTest.
Expand All @@ -27,7 +28,7 @@ public FileCheckerTestData(string testDataFilePath, InArchiveFormat expectedForm
/// Path to archive file to test against.
/// </summary>
public string TestDataFilePath { get; }

public override string ToString()
{
// Used to get useful test results.
Expand Down Expand Up @@ -85,11 +86,11 @@ public void SetUp()
// Ensures we're in the correct working directory (for test data files).
Directory.SetCurrentDirectory(TestContext.CurrentContext.TestDirectory);
}

[TestCaseSource(nameof(TestData))]
public void CheckFileSignatureTest(FileCheckerTestData data)
{
if (!File.Exists(data.TestDataFilePath))
if (!File.Exists(Path.Combine(AppContext.BaseDirectory, data.TestDataFilePath)))
{
Assert.Ignore("No test data found for this format.");
}
Expand Down
2 changes: 1 addition & 1 deletion SevenZip.Tests/LibraryManagerTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace SevenZip.Tests
namespace SevenZip.Tests
{
using NUnit.Framework;

Expand Down
2 changes: 2 additions & 0 deletions SevenZip.Tests/MiscellaneousTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
[TestFixture]
public class MiscellaneousTests : TestBase
{
#if !NET5_0_OR_GREATER
[Test]
public void SerializationTest()
{
Expand All @@ -27,6 +28,7 @@ public void SerializationTest()
}
}
}
#endif

#if SFX
[Test]
Expand Down
15 changes: 15 additions & 0 deletions SevenZip.Tests/NativeAssetsTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using NUnit.Framework;
using System.Reflection;

namespace SevenZip.Tests;

sealed class NativeAssetsTest
{
[Test]
public void LibraryFilePath()
{
var libFilePath = typeof(SevenZipBase).Assembly.GetType("SevenZip.SevenZipLibraryManager").GetMethod("DetermineLibraryFilePath", BindingFlags.Static | BindingFlags.NonPublic).Invoke(null, null);
TestContext.WriteLine("libFilePath:");
TestContext.WriteLine(libFilePath);
}
}
3 changes: 2 additions & 1 deletion SevenZip.Tests/SevenZip.Tests.csproj
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net6.0</TargetFrameworks>
<TargetFrameworks>net8.0</TargetFrameworks>
<AssemblyTitle>SevenZip.Tests</AssemblyTitle>
<Product>SevenZipTests</Product>
<Copyright>Copyright © Joel Ahlgren 2023</Copyright>
Expand All @@ -18,6 +18,7 @@
<DebugSymbols>true</DebugSymbols>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="7-Zip.NativeAssets.Win32" Version="24.5.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
<PackageReference Include="NUnit" Version="3.13.3" />
<PackageReference Include="NUnit3TestAdapter" Version="4.4.2" />
Expand Down
2 changes: 1 addition & 1 deletion SevenZip.Tests/SevenZipExtractorAsynchronousTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace SevenZip.Tests
namespace SevenZip.Tests
{
using System.IO;
using System.Threading;
Expand Down
2 changes: 1 addition & 1 deletion SevenZip.Tests/SevenZipExtractorTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace SevenZip.Tests
namespace SevenZip.Tests
{
using System;
using System.Collections.Generic;
Expand Down
Binary file removed SevenZip/7z.dll
Binary file not shown.
Binary file removed SevenZip/7z64.dll
Binary file not shown.
161 changes: 141 additions & 20 deletions SevenZip/LibraryManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,114 @@ internal static class SevenZipLibraryManager

private static string DetermineLibraryFilePath()
{
if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["7zLocation"]))
//if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["7zLocation"]))
//{
// return ConfigurationManager.AppSettings["7zLocation"];
//}

//if (string.IsNullOrEmpty(Assembly.GetExecutingAssembly().Location))
//{
// return null;
//}

//return Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), Environment.Is64BitProcess ? "7z64.dll" : "7z.dll");

var baseDirectory = AppContext.BaseDirectory;
string runtimeIdentifier = null;
string libFileName = "7z.dll";
#if NET5_0_OR_GREATER
runtimeIdentifier = RuntimeInformation.RuntimeIdentifier;
#endif
if (string.IsNullOrWhiteSpace(runtimeIdentifier))
{
return ConfigurationManager.AppSettings["7zLocation"];
#if NET5_0_OR_GREATER
bool isWindows = OperatingSystem.IsWindows();
bool isMacOS = OperatingSystem.IsMacOS();
bool isMacCatalyst = OperatingSystem.IsMacCatalyst();
bool isLinux = OperatingSystem.IsLinux();
#else
bool isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
bool isMacOS = RuntimeInformation.IsOSPlatform(OSPlatform.OSX);
bool isMacCatalyst = false;
bool isLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux);
#endif
if (isWindows)
{
switch (RuntimeInformation.ProcessArchitecture)
{
case Architecture.X86:
runtimeIdentifier = "win-x86";
break;
case Architecture.X64:
runtimeIdentifier = "win-x64";
break;
case Architecture.Arm:
runtimeIdentifier = "win-arm";
break;
case Architecture.Arm64:
runtimeIdentifier = "win-arm64";
break;
}
}
else if (isMacOS)
{
switch (RuntimeInformation.ProcessArchitecture)
{
case Architecture.X64:
runtimeIdentifier = "osx-x64";
break;
case Architecture.Arm64:
runtimeIdentifier = "osx-arm64";
break;
}
libFileName = "7zz";
}
else if (isMacCatalyst)
{
switch (RuntimeInformation.ProcessArchitecture)
{
case Architecture.X64:
runtimeIdentifier = "maccatalyst-x64";
break;
case Architecture.Arm64:
runtimeIdentifier = "maccatalyst-arm64";
break;
}
libFileName = "7zz";
}
else if (isLinux)
{
switch (RuntimeInformation.ProcessArchitecture)
{
case Architecture.X86:
runtimeIdentifier = "linux-x86";
break;
case Architecture.X64:
runtimeIdentifier = "linux-x64";
break;
case Architecture.Arm:
runtimeIdentifier = "linux-arm";
break;
case Architecture.Arm64:
runtimeIdentifier = "linux-arm64";
break;
}
libFileName = "7zz";
}
}

if (string.IsNullOrEmpty(Assembly.GetExecutingAssembly().Location))

string libFilePath;
if (!string.IsNullOrWhiteSpace(runtimeIdentifier))
{
return null;
libFilePath = Path.Combine(baseDirectory, "runtimes", runtimeIdentifier, "native", libFileName);
if (File.Exists(libFilePath))
{
return libFilePath;
}
}

return Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), Environment.Is64BitProcess ? "7z64.dll" : "7z.dll");
libFilePath = Path.Combine(baseDirectory, libFileName);
return libFilePath;
}

/// <summary>
Expand Down Expand Up @@ -125,14 +222,26 @@ public static void LoadLibrary(object user, Enum format)
throw new SevenZipLibraryException("DLL file does not exist.");
}

#if NETCOREAPP3_0_OR_GREATER
if ((_modulePtr = NativeLibrary.Load(_libraryFileName)) == IntPtr.Zero)
#else
if ((_modulePtr = NativeMethods.LoadLibrary(_libraryFileName)) == IntPtr.Zero)
#endif
{
throw new SevenZipLibraryException($"failed to load library from \"{_libraryFileName}\".");
}

#if NETCOREAPP3_0_OR_GREATER
if (NativeLibrary.GetExport(_modulePtr, "GetHandlerProperty") == IntPtr.Zero)
#else
if (NativeMethods.GetProcAddress(_modulePtr, "GetHandlerProperty") == IntPtr.Zero)
#endif
{
#if NETCOREAPP3_0_OR_GREATER
NativeLibrary.Free(_modulePtr);
#else
NativeMethods.FreeLibrary(_modulePtr);
#endif
throw new SevenZipLibraryException("library is invalid.");
}
}
Expand Down Expand Up @@ -188,7 +297,7 @@ private static string GetResourceString(string str)
private static bool ExtractionBenchmark(string archiveFileName, Stream outStream, ref LibraryFeature? features, LibraryFeature testedFeature)
{
var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(GetResourceString(archiveFileName));

try
{
using (var extractor = new SevenZipExtractor(stream))
Expand Down Expand Up @@ -350,7 +459,7 @@ public static void FreeLibrary(object user, Enum format)
sp.Demand();
#endif
lock (SyncRoot)
{
{
if (_modulePtr != IntPtr.Zero)
{
if (format is InArchiveFormat archiveFormat)
Expand All @@ -360,14 +469,14 @@ public static void FreeLibrary(object user, Enum format)
_inArchives[user][archiveFormat] != null)
{
try
{
{
Marshal.ReleaseComObject(_inArchives[user][archiveFormat]);
}
catch (InvalidComObjectException) {}
catch (InvalidComObjectException) { }

_inArchives[user].Remove(archiveFormat);
_totalUsers--;

if (_inArchives[user].Count == 0)
{
_inArchives.Remove(user);
Expand All @@ -385,11 +494,11 @@ public static void FreeLibrary(object user, Enum format)
{
Marshal.ReleaseComObject(_outArchives[user][outArchiveFormat]);
}
catch (InvalidComObjectException) {}
catch (InvalidComObjectException) { }

_outArchives[user].Remove(outArchiveFormat);
_totalUsers--;

if (_outArchives[user].Count == 0)
{
_outArchives.Remove(user);
Expand All @@ -404,12 +513,16 @@ public static void FreeLibrary(object user, Enum format)

if (_totalUsers == 0)
{
#if NETCOREAPP3_0_OR_GREATER
NativeLibrary.Free(_modulePtr);
#else
NativeMethods.FreeLibrary(_modulePtr);
#endif
_modulePtr = IntPtr.Zero;
}
}
}
}
}
}

/// <summary>
Expand Down Expand Up @@ -440,7 +553,11 @@ public static IInArchive InArchive(InArchiveFormat format, object user)

var createObject = (NativeMethods.CreateObjectDelegate)
Marshal.GetDelegateForFunctionPointer(
#if NETCOREAPP3_0_OR_GREATER
NativeLibrary.GetExport(_modulePtr, "CreateObject"),
#else
NativeMethods.GetProcAddress(_modulePtr, "CreateObject"),
#endif
typeof(NativeMethods.CreateObjectDelegate));

if (createObject == null)
Expand All @@ -461,7 +578,7 @@ public static IInArchive InArchive(InArchiveFormat format, object user)
throw new SevenZipLibraryException("Your 7-zip library does not support this archive type.");
}

InitUserInFormat(user, format);
InitUserInFormat(user, format);
_inArchives[user][format] = result as IInArchive;
}

Expand Down Expand Up @@ -491,16 +608,20 @@ public static IOutArchive OutArchive(OutArchiveFormat format, object user)

var createObject = (NativeMethods.CreateObjectDelegate)
Marshal.GetDelegateForFunctionPointer(
#if NETCOREAPP3_0_OR_GREATER
NativeLibrary.GetExport(_modulePtr, "CreateObject"),
#else
NativeMethods.GetProcAddress(_modulePtr, "CreateObject"),
#endif
typeof(NativeMethods.CreateObjectDelegate));
var interfaceId = typeof(IOutArchive).GUID;


try
{
var classId = Formats.OutFormatGuids[format];
createObject(ref classId, ref interfaceId, out var result);

InitUserOutFormat(user, format);
_outArchives[user][format] = result as IOutArchive;
}
Expand All @@ -520,7 +641,7 @@ public static void SetLibraryPath(string libraryPath)
{
throw new SevenZipLibraryException($"can not change the library path while the library \"{_libraryFileName}\" is being used.");
}

if (!File.Exists(libraryPath))
{
throw new SevenZipLibraryException($"can not change the library path because the file \"{libraryPath}\" does not exist.");
Expand Down
Loading

0 comments on commit 3f789cf

Please sign in to comment.