Используйте сборку.NET без блокировки файла DLL

У меня есть служба Windows, которая выполняется один раз в день. Это всего лишь 10 минут действия.

Я создаю файлы сервиса в папке bin сайта, потому что сервис использует dll сайта.

К сожалению, я заметил, что когда я установил модуль веб-сайта (модуль dotnetnuke.zip установщиком веб-сайта), я получил ошибку, что файл заблокирован другим процессом.

Отключение службы перед установкой каждого модуля очень проблематично, поэтому я хочу, чтобы моя служба не блокировала используемые в ней библиотеки DLL.

Я читал об опциях AppDomain и ShadowCopyFiles, но не могу заставить их работать на меня.

Это пример того, как я использую ShadowCopyFiles:

class Program
{
    static string GenerateRandomName()
    {
        //maybe name must be unique?!
        var random = new Random();
        return "a" + random.Next().ToString() + "b" + random.Next();
    }

    static int RandomNumber()
    {
        var info = ConfigureAppDomainSettings();

        var domain = AppDomain.CreateDomain(GenerateRandomName(), null, info);
        var assembly = domain.Load("SharedLibrary");
        var shared = (SharedLibrary.IShared)assembly.CreateInstance("SharedLibrary.Shared");

        int retVal = shared.RandomNumber();

        AppDomain.Unload(domain);

        domain = null;
        assembly = null;
        shared = null;
        info = null;

        Console.WriteLine("before cleanning");
        GC.Collect();
        GC.WaitForPendingFinalizers();
        GC.Collect();
        GC.WaitForFullGCComplete();
        GC.Collect();
        Console.WriteLine("after cleanning");

        return retVal;
    }

    static AppDomainSetup ConfigureAppDomainSettings()
    {
        AppDomainSetup domainSettings = AppDomain.CurrentDomain.SetupInformation;
        domainSettings.ShadowCopyFiles = "true";
        domainSettings.CachePath = @"C:\inetpub\wwwroot\eshop\DesktopModules\Rossnet_EShop\SharedAssemblyTest\PrivateCache";

        return domainSettings;
    }

    static void Main(string[] args)
    {
        Console.WriteLine(RandomNumber());

        Console.ReadKey();
    }
}

Код примера сборки:

public interface IShared
{
    int RandomNumber();
}

[Serializable]
public class Shared : IShared
{
    public int RandomNumber()
    {
        var random = new Random();
        return random.Next(20);
    }
}

Закрытый кеш создается и не блокируется, а исходный файл блокируется. <- сейчас это абсурдно для меня.

1 ответ

Решение

Если у вас есть доступ для изменения всего кода, который использует сборки, просто загрузите их с помощью перегрузки Assembly.Load, которая принимает byte[] должен сделать свое дело. Вы сами прочитаете файл и передадите его этому методу. Я сам использую этот подход (хотя и по другим причинам), и он дает мне возможность обновлять файлы в любое время.

Способ сделать это легко (хотя и немного странно) - переименовать ваши файлы (из.dll во что-то другое, чтобы их нельзя было найти), а затем подписаться на событие AppDomain.AssemblyResolve, которое будет вызываться, когда они отсутствует, в этот момент вы можете иметь свой код, который загружает сборки вручную.

Другие вопросы по тегам