Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Single file deployment support #45

Open
mcpat-it opened this issue Oct 11, 2020 · 4 comments
Open

Single file deployment support #45

mcpat-it opened this issue Oct 11, 2020 · 4 comments

Comments

@mcpat-it
Copy link

Any plans to port to .NET5? Would be great!

Thx
Patrick

@adoconnection
Copy link
Owner

As long as I can see, its a matter of typing

<TargetFramework>net5.0</TargetFramework>

in project file, so of course I will do that after 5.0 release :)

@mcpat-it
Copy link
Author

Thank you

@mgpreston
Copy link

@adoconnection Thanks for the great library!

If you also want to support single file deployment in .NET 5, you'll need to change the way the 7z.dll library is loaded. When <IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract> is specified in the project file, the .dlls will be packaged in the single-file bundle, and will be extracted automatically, but there's no way to determine where it was extracted to. Instead, you can use the NativeLibrary.Load method to load the library from the extraction directory, by using a relative path:

NativeLibrary.Load(sevenZipLibPath, Assembly.GetEntryAssembly(), null);

In this case, sevenZipLibPath is "x64\7z.dll". The Assemby.GetEntryAssembly() part seems necessary to use the single-file app's customised loader, that knows to look in the extraction directory.

To support relative paths, you'll need to remove the File.Exists check in ArchiveFile.InitializeAndValidateLibrary:

if (!File.Exists(this.libraryFilePath))
{
throw new SevenZipException("7z.dll not found");
}

I also added an extra else block to determine libraryFilePath when one wasn't set, as all the other conditions rely on File.Exists which won't work for single file apps:

else
{
    this.libraryFilePath = Path.Combine(currentArchitecture, "7z.dll");
}

added to

if (File.Exists(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "7z-" + currentArchitecture + ".dll")))
{
this.libraryFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "7z-" + currentArchitecture + ".dll");
}
else if (File.Exists(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin", "7z-" + currentArchitecture + ".dll")))
{
this.libraryFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin", "7z-" + currentArchitecture + ".dll");
}
else if (File.Exists(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, currentArchitecture, "7z.dll")))
{
this.libraryFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, currentArchitecture, "7z.dll");
}
else if (File.Exists(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "7-Zip", "7z.dll")))
{
this.libraryFilePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "7-Zip", "7z.dll");
}

An alternative approach to handle single file apps would be to expose an ArchiveFile constructor that takes an IntPtr instead of libraryFilePath, and let the user load the library themselves using NativeLibrary.Load.

@adoconnection
Copy link
Owner

Hi, thanks for kind words and detailed info! I’ll implement it as soon as got some spare time.

@adoconnection adoconnection changed the title .NET 5 Single file deployment support Apr 8, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants