Home > database >  Is it possible to dispose a library in C#?
Is it possible to dispose a library in C#?

Time:10-01

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.

  • Related