powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Не освобождается DLL после AppDomain.Unload()
14 сообщений из 14, страница 1 из 1
Не освобождается DLL после AppDomain.Unload()
    #39098666
Марк333
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Пытаюсь выполнить метод из DLL, скомпилированной из строки, для чего делаю так:

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
using System;
using System.CodeDom.Compiler;
using System.IO;
using System.Reflection;

namespace EvalInDomain
{
  class Program
  {

    static string sourceCode =
@"
using System;
namespace TestNameSpace
{
  public class TestClass : MarshalByRefObject 
  {
     public void TestMethod()
     {
        Console.WriteLine(""Hello, AppDomain \""{0}\""!"", 
          AppDomain.CurrentDomain.FriendlyName);
     }
  }
}";
    static void Main()
    {
      CodeDomProvider compiler = CodeDomProvider.CreateProvider("CSharp");
      string DllDir = AppDomain.CurrentDomain.BaseDirectory;
      string tmpDllName = Path.Combine(DllDir,Guid.NewGuid().ToString()) + ".dll";
      CompilerParameters compilerParameters = new CompilerParameters()
      {
        CompilerOptions = "/t:library", 
        OutputAssembly = tmpDllName, 
        GenerateInMemory = true, 
      };
      CompilerResults results = compiler.CompileAssemblyFromSource(compilerParameters, sourceCode);
      AppDomainSetup ads = new AppDomainSetup() { ApplicationBase = Path.GetDirectoryName(tmpDllName)  };
      AppDomain newDomain = AppDomain.CreateDomain("Another Domain", null, ads);
      object instance = newDomain.CreateInstanceAndUnwrap(results.CompiledAssembly.FullName, "TestNameSpace.TestClass");
      Type objectType = instance.GetType(); 
      MethodInfo mi = objectType.GetMethod("TestMethod"); 
      mi.Invoke(instance,null);
      AppDomain.Unload(newDomain);
      //Пытаемся прибрать мусор:
      File.Delete(tmpDllName); //Ошибка (файл занят)...
      //
      Console.Write("Press any key to exit... ");
      Console.ReadKey(false);
    }
  }
}


Но File.Delete(tmpDllName) в конце не работает, т.к. файл занят.
Как освободить файл (или, ещё лучше бы - как выполнить DLL в памяти, не используя этот файл, но только так, чтобы потом её выгрузить) ? Или, может даже не DLL, а просто метод, скомпилированный каким-то образом в процессе выполнения из строки?
...
Рейтинг: 0 / 0
Не освобождается DLL после AppDomain.Unload()
    #39098708
Roman Mejtes
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Не освобождается DLL после AppDomain.Unload()
    #39098717
Фотография Antonariy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: c#
1.
Type objectType = instance.GetType();

В этот момент сборка TestNameSpace подгружается в основной домен.
Нельзя выпускать объекты Reflection за пределы домена.

Марк333а просто метод, скомпилированный каким-то образом в процессе выполнения из строки?да. не указывать OutputAssembly :)
...
Рейтинг: 0 / 0
Не освобождается DLL после AppDomain.Unload()
    #39098725
Фотография Antonariy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Antonariyда. не указывать OutputAssembly :)файл все равно будет создан на диске, но fw знает в каком месте, и со временем он будет подчищен самой системой. можно не париться с аппдоменами, я когда-то юзал такой код, с трудом его нашел:

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
    Private Function CreateAssembly(ByVal sScript As String) As System.Reflection.Assembly
        On Error GoTo errh
        Dim c As VBCodeProvider = New VBCodeProvider()
        Dim cp As CompilerParameters = New CompilerParameters()
        cp.ReferencedAssemblies.Add("system.dll")
        cp.ReferencedAssemblies.Add("system.xml.dll")
        cp.ReferencedAssemblies.Add("system.data.dll")
        cp.ReferencedAssemblies.Add(System.Reflection.Assembly.GetExecutingAssembly.Location)
        cp.CompilerOptions = "/t:library"
        cp.GenerateInMemory = True
        ' Complete the user code so that it can be compiled
        Dim sb As System.Text.StringBuilder = New System.Text.StringBuilder("")
        sb.AppendLine("Imports System")
        sb.AppendLine("Imports System.IO")
        sb.AppendLine("Imports System.Xml")
        sb.AppendLine("Imports System.Data")


        sb.AppendLine("Public class Script")

        sb.AppendLine("End Class")

        Dim cr As CompilerResults = c.CompileAssemblyFromSource(cp, sb.ToString())
        If cr.Errors.HasErrors Then
            Dim er As CompilerError
            For Each er In cr.Errors
                Debug.Print(er.ErrorText)
            Next
            Return Nothing
        End If
        Return cr.CompiledAssembly
    End Function
...
Рейтинг: 0 / 0
Не освобождается DLL после AppDomain.Unload()
    #39098726
Марк333
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Хм...
Эту ссылку я почитал, кое-что полезное почерпнул. Но вот это
AntonariyНе совсем победил. При отдаче ссылки на Reflection.Assembly за пределы домена, в котором сборка создается, она загружается и в вызывающий домен, то есть домен студии. Придется всю обработку сборки в AssemblyAnalyser перетаскивать.совсем не радует...
В моём примере метод, который ничего не принимает и ничего не возвращает. Но хотелось бы уметь и вернуть что-нибудь оттуда...
...
Рейтинг: 0 / 0
Не освобождается DLL после AppDomain.Unload()
    #39098732
Фотография Antonariy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Марк333В моём примере метод, который ничего не принимает и ничего не возвращает. Но хотелось бы уметь и вернуть что-нибудь оттуда...для этого создается класс, экземпляр которого создается в отдельном домене, он работает с Reflection и возвращает результат в основной домен.
...
Рейтинг: 0 / 0
Не освобождается DLL после AppDomain.Unload()
    #39098746
Марк333
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
AntonariyМарк333а просто метод, скомпилированный каким-то образом в процессе выполнения из строки?да. не указывать OutputAssembly :)

Если я комментирую строчку
//OutputAssembly = tmpDllName,
то получаю примерно вот такую ошибку:

Не удалось загрузить файл или сборку "jadotpmm, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null" либо одну из их зависимостей. Не удается найти указанный файл.

т.е. он всё равно хочет какой-то файл. Хотя, если делать в основном домене - да, нормально можно загрузить такую сборку.
...
Рейтинг: 0 / 0
Не освобождается DLL после AppDomain.Unload()
    #39098780
Фотография Antonariy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Марк333т.е. он всё равно хочет какой-то файл. Хотя, если делать в основном домене - да, нормально можно загрузить такую сборку.ну и загружай в основной домен. новый файл в той же сессии будет создан с новым случайным именем, а уборка мусора больше не твоя задача.
...
Рейтинг: 0 / 0
Не освобождается DLL после AppDomain.Unload()
    #39098892
Марк333
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Antonariyну и загружай в основной домен. новый файл в той же сессии будет создан с новым случайным именем, а уборка мусора больше не твоя задача.
Так-то оно так. Дисковый мусор когда-нибудь удалится. Но ведь тогда из памяти я это дело выгрузить не смогу, пока не завершён процесс. И если таких динамических компиляций много (скажем, берём из БД какую-то формулу, выполняем по ней расчёты, и так много-много раз, и формул таких много на разные случаи, а редактирует их юзер), это ведь каждый раз новая сборка, загружаемая в память навсегда. Конечно, памяти на компах нынче много (что и развращает), но сам подход как-то не очень мне нравится... Даже если создавать из этого делегатов и кэшировать их, а потом использовать, таская из кэша и создавая только ранее не используемые, всё равно как-то не то...
...
Рейтинг: 0 / 0
Не освобождается DLL после AppDomain.Unload()
    #39098952
Фотография Antonariy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Марк333Antonariyну и загружай в основной домен. новый файл в той же сессии будет создан с новым случайным именем, а уборка мусора больше не твоя задача.
Так-то оно так. Дисковый мусор когда-нибудь удалится. Но ведь тогда из памяти я это дело выгрузить не смогу, пока не завершён процесс. И если таких динамических компиляций много (скажем, берём из БД какую-то формулу, выполняем по ней расчёты, и так много-много раз, и формул таких много на разные случаи, а редактирует их юзер), это ведь каждый раз новая сборка, загружаемая в память навсегда. Конечно, памяти на компах нынче много (что и развращает), но сам подход как-то не очень мне нравится... Даже если создавать из этого делегатов и кэшировать их, а потом использовать, таская из кэша и создавая только ранее не используемые, всё равно как-то не то...ну ты же не сказал сразу, что твой процесс будет работать постоянно, до последнего этот сюрприз берег.
значит выносить работу с Reflection в отдельный класс и создавать его в отдельном домене.

есть еще вариант без сборок и компиляции, может тебе его хватит: http://www.codeproject.com/Articles/538920/Dynamic-Expresso
...
Рейтинг: 0 / 0
Не освобождается DLL после AppDomain.Unload()
    #39099134
Марк333
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасибо, вот это ближе к тому, что я искал. Попробую.

А я уже нашёл и опробовал несколько другой вариант: http://www.codeproject.com/Articles/46350/Evaluate-Expressions-from-C-using-JavaScript-s-Eva

Это небольшой отход от c# (крохотная функция на java), но мне-то какая разница - всё равно код для .net получается.
"По мотивам" этого написал вот такой батник:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
echo off
set JSFile=JSMath
set JSCompiler=C:\Windows\Microsoft.NET\Framework\v4.0.30319\jsc.exe

del %JSFile%.dll

echo class JsMath > %JSFile%.js
echo { >> %JSFile%.js
echo   static function Eval(expression : String, x : double) : double >> %JSFile%.js
echo   { >> %JSFile%.js
echo     with (Math) { >> %JSFile%.js
echo        return eval(expression); >> %JSFile%.js
echo     } >> %JSFile%.js
echo   }; >> %JSFile%.js
echo } >> %JSFile%.js

%JSCompiler% /t:library %JSFile%.js
del %JSFile%.js

получаю им DLL, подключаю к проекту, и юзаю метод Eval, который есть обёртка над java - функцией eval(). Понятно, что для конкретных целей можно сколь угодно усложнить. Благо, тут есть with, так что не придётся писать в выражениях "Math.Sin(x)..." к примеру, а можно просто "Sin(x)" и т.д.
...
Рейтинг: 0 / 0
Не освобождается DLL после AppDomain.Unload()
    #39099284
Фотография Antonariy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
это просто жесть



уж лучше бы VBScript подключил.
...
Рейтинг: 0 / 0
Не освобождается DLL после AppDomain.Unload()
    #39099322
Фотография buser
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
колеса покруглее https://www.simple-talk.com/dotnet/.net-framework/dynamic-language-integration-in-a-c-world/, http://jint.codeplex.com/documentation, c IronRuby таже история...
Ну и искать... Незабвенный МСУ что-то в свои рецепты положил http://codearticles.ru/articles/537 ...
Еще что-то было, но я туп и не нашел...
...
Рейтинг: 0 / 0
Не освобождается DLL после AppDomain.Unload()
    #39099414
Winnipuh
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Задача не совсем понятна, может легче воспользоваться этим?

http://www.csscript.net/
...
Рейтинг: 0 / 0
14 сообщений из 14, страница 1 из 1
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Не освобождается DLL после AppDomain.Unload()
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]