DnsApplicationAssemblyLoadContext: updated implementation to load managed reference DLLs too using temp files to allow update/uninstall of app at runtime on Windows.

This commit is contained in:
Shreyas Zare
2025-01-26 17:11:44 +05:30
parent 02355affb6
commit 764fa4935e

View File

@@ -37,7 +37,7 @@ namespace DnsServerCore.Dns.Applications
readonly AssemblyDependencyResolver _dependencyResolver; readonly AssemblyDependencyResolver _dependencyResolver;
readonly Dictionary<string, IntPtr> _loadedUnmanagedDlls = new Dictionary<string, IntPtr>(); readonly Dictionary<string, IntPtr> _loadedUnmanagedDlls = new Dictionary<string, IntPtr>();
readonly List<string> _unmanagedDllTempPaths = new List<string>(); readonly List<string> _dllTempPaths = new List<string>();
#endregion #endregion
@@ -50,11 +50,11 @@ namespace DnsServerCore.Dns.Applications
Unloading += delegate (AssemblyLoadContext obj) Unloading += delegate (AssemblyLoadContext obj)
{ {
foreach (string unmanagedDllTempPath in _unmanagedDllTempPaths) foreach (string dllTempPath in _dllTempPaths)
{ {
try try
{ {
File.Delete(unmanagedDllTempPath); File.Delete(dllTempPath);
} }
catch catch
{ } { }
@@ -116,7 +116,12 @@ namespace DnsServerCore.Dns.Applications
{ {
string resolvedPath = _dependencyResolver.ResolveAssemblyToPath(assemblyName); string resolvedPath = _dependencyResolver.ResolveAssemblyToPath(assemblyName);
if (!string.IsNullOrEmpty(resolvedPath) && File.Exists(resolvedPath)) if (!string.IsNullOrEmpty(resolvedPath) && File.Exists(resolvedPath))
return LoadFromAssemblyPath(resolvedPath); {
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
return LoadFromAssemblyPath(GetTempDllFile(resolvedPath));
else
return LoadFromAssemblyPath(resolvedPath);
}
} }
foreach (Assembly loadedAssembly in Default.Assemblies) foreach (Assembly loadedAssembly in Default.Assemblies)
@@ -199,26 +204,9 @@ namespace DnsServerCore.Dns.Applications
//load the unmanaged DLL //load the unmanaged DLL
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{ value = LoadUnmanagedDllFromPath(GetTempDllFile(unmanagedDllPath));
//copy unmanaged dll into temp file for loading to allow uninstalling/updating app at runtime.
string tempPath = Path.GetTempFileName();
using (FileStream srcFile = new FileStream(unmanagedDllPath, FileMode.Open, FileAccess.Read))
{
using (FileStream dstFile = new FileStream(tempPath, FileMode.Create, FileAccess.Write))
{
srcFile.CopyTo(dstFile);
}
}
_unmanagedDllTempPaths.Add(tempPath);
value = LoadUnmanagedDllFromPath(tempPath);
}
else else
{
value = LoadUnmanagedDllFromPath(unmanagedDllPath); value = LoadUnmanagedDllFromPath(unmanagedDllPath);
}
_loadedUnmanagedDlls.Add(unmanagedDllPath.ToLowerInvariant(), value); _loadedUnmanagedDlls.Add(unmanagedDllPath.ToLowerInvariant(), value);
} }
@@ -231,6 +219,24 @@ namespace DnsServerCore.Dns.Applications
#region private #region private
private string GetTempDllFile(string dllFile)
{
//copy dll into temp file for loading to allow uninstalling/updating app at runtime.
string tempPath = Path.GetTempFileName();
using (FileStream srcFile = new FileStream(dllFile, FileMode.Open, FileAccess.Read))
{
using (FileStream dstFile = new FileStream(tempPath, FileMode.Create, FileAccess.Write))
{
srcFile.CopyTo(dstFile);
}
}
_dllTempPaths.Add(tempPath);
return tempPath;
}
private string FindUnmanagedDllPath(string unmanagedDllName, string runtime, string[] prefixes, string[] extensions) private string FindUnmanagedDllPath(string unmanagedDllName, string runtime, string[] prefixes, string[] extensions)
{ {
foreach (string prefix in prefixes) foreach (string prefix in prefixes)