I'm currently working on a WinForms .NET application on Visual Studio Community 2022. I'm having some trouble with a library I created, called UpdaterLibrary. This library has all the methods necessary to update my application, but because of that, I can't update that file with its own code, cause that means deleting the file and replacing it by the new one. What I did was using all the methods I could from that library and copying some of that code (the delete and copy methods I created for updating the application files) so I can delete and copy the new UpdaterLibrary from the update path. The problem is that if I use that library, the application doesn't close the file even when I dispose the class or when I put it inside a using statement. My question is: Is there any way to close the file / dispose it after using it? Here's the code:
private static async Task CheckForUpdatesForUpdaterLibrary()
{
await Task.Run(async () =>
{
try
{
UpdaterLibrary.UpdaterClass updater = await UpdaterLibrary.UpdaterClass.CreateInstance();
Version localUpdaterLibraryVersion = await updater.GetFileVersion("UpdaterLibrary.dll", false);
if (await updater.VersionIsLower("UpdaterLibrary.dll", localUpdaterLibraryVersion))
{
updater.Dispose();
await UpdateUpdaterLibrary();
}
}
catch (Exception ex)
{
MessageBox.Show($"Hubo un error al actualizar la aplicación. Vuelva a intentarlo más tarde. \n{ex.Message} \n\n {ex.StackTrace}");
}
});
}
private static async Task UpdateUpdaterLibrary()
{
await Task.Run(async () =>
{
if (await UpdaterLibrary.UpdaterClass.IsRunningAsAdmin())
{
if (!Directory.Exists(UpdatePath))
{
Directory.CreateDirectory(UpdatePath);
}
MessageBox.Show("Hay una actualización disponible para la librería del actualizador de la aplicación. Espere un momento mientras se instala la actualización.");
List<string> updaterLibraryList = new List<string>
{
"UpdaterLibrary.dll"
};
await UpdateFiles(updaterLibraryList);
}
else
{
MessageBox.Show("Hay una actualización disponible para la librería del actualizador de la aplicación. Se reiniciará la aplicación y se le pediran permisos para poder actualizarlo.");
await UpdaterLibrary.UpdaterClass.RunAsAdmin();
Environment.Exit(0);
}
});
}
public static async Task UpdateFiles(List<string> filesToUpdate)
{
await Task.Run(async () =>
{
HttpClient client = await SetClient(new Version("1.0.0"), token);
await DownloadNewFiles(filesToUpdate, client);
await DeleteOldFiles(filesToUpdate);
await CopyFiles(filesToUpdate);
});
}
public static async Task DownloadNewFiles(List<string> newFiles, HttpClient client)
{
await Task.Run(async () =>
{
string updatePath = UpdatePath;
JArray contentArray = await GetGitHubContents(client);
foreach (JObject contentItem in contentArray.Cast<JObject>())
{
string name = (string)contentItem["name"];
if (newFiles.Contains(name))
{
string downloadUrl = (string)contentItem["download_url"];
byte[] downloadBytes = await client.GetByteArrayAsync(downloadUrl);
string filePath = $@"{updatePath}\{name}";
File.WriteAllBytes(filePath, downloadBytes);
}
}
});
}
public static async Task DeleteOldFiles(List<string> filesToDelete)
{
await Task.Run(() =>
{
string path = AppPath;
foreach (string file in filesToDelete)
{
string fileName = $@"{path}\{file}";
File.Delete(fileName);
}
});
}
The code inside the UpdaterLibrary doesn't really matter, that works all well. I don't know if it's not disposing maybe has to be with the fact that I'm using only static methods, but I don't think so.
CodePudding user response:
your question: "Is it possible to dispose a library in C#"
answer:
No, because of the garbage collector which is not able to split memory holded by instances of things inside assemblies.
some details:
If the framework would support unloading linked assemblies like in c / c , the garbarge collecter would have a big problem to keep the integrity of the object dependency tree. That's the (short) reason, why it is inpossible to unload a loaded assembly in a managed application process.
workarounds:
But, as the guy's said in the comments, you can do a App-Domain, which is more or less a sub-process. The drawback is, like in every inter process communication: it's a different process and you need do deal with it if you want to exchange data between them.