views:

22

answers:

0

hello,
in my application, i use CSharpCodeProvider class to dynamically create a dll file and load the file into another appdomain to use the class in it. when i am done with the class, i simply unload the appdomain. everything is perfect so far.
but if i try to recompile the dll at runtime, i get the following error.

E:\projects\CompilerTester\Debug> "C:\Windows\Microsoft.NET\Framework\v2.0.50727 \csc.exe" /t:library /utf8output /R:"system.dll" /R:"E:\projects\CompilerTester\ Debug\BaseClassContainer.dll" /out:"dynamic.dll" /debug- /optimize+ /platform:x8 6 "E:\projects\CompilerTester\Debug\..\UserLibraryFiles\DerivedClass.cs"

Microsoft (R) Visual C# 2005 Compiler version 8.00.50727.4927 for Microsoft (R) Windows (R) 2005 Framework version 2.0.50727 Copyright (C) Microsoft Corporation 2001-2005. All rights reserved.

error CS0016: Could not write to output file 'e:\projects\CompilerTester\Debug\d ynamic.dll' -- 'The process cannot access the file because it is being used by a nother process. '

here is the source code of my simple application. the shared library between the executable and the dynamically loaded assembly // BaseClass.cs using System; using System.Collections.Generic; using System.Linq; using System.Text;

namespace BaseNameSpace
{
  public class BaseClass
  {
    public BaseClass()
    {
      Console.WriteLine("BaseClass message.");
    }
    public virtual void Write(string txt)
    {
      Console.WriteLine("BaseClass Text : " + txt);
    }
  }
}

the code of dynamically loaded assembly: derivedclass.cs


using System;
using BaseNameSpace;  
namespace DerivedNameSpace
{
  public class DerivedClass : BaseClass
  {
    public DerivedClass(string txt) : base()
    {
      Console.WriteLine(txt);
    }  
    public override void Write(string txt)
    {
      Console.WriteLine("DerivedClass Text : "+ txt);
    }
  }
}
  

and last one, the executable :


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.CSharp;
using System.CodeDom.Compiler;
using System.Reflection;
using System.IO;
using BaseNameSpace;
namespace Tester
{
  class Program
  {
    static bool DynamicCompile(ref Assembly ass)
    {
      CSharpCodeProvider csCompiler = new CSharpCodeProvider();
      CompilerParameters compilerParams = new CompilerParameters();
      compilerParams.IncludeDebugInformation = false;
      compilerParams.OutputAssembly = "dynamic.dll";
      compilerParams.ReferencedAssemblies.Add("system.dll");
      compilerParams.ReferencedAssemblies.Add(AppDomain.CurrentDomain.BaseDirectory + @"BaseClassContainer.dll");
      compilerParams.GenerateExecutable = false;
      compilerParams.GenerateInMemory = true;
      compilerParams.CompilerOptions = "/platform:x86";
      CompilerResults cr = csCompiler.CompileAssemblyFromFile(compilerParams, Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory + @"\..\UserLibraryFiles"));
      if (cr.Output.Count > 0)
      {
        foreach (string s in cr.Output)
          Console.WriteLine(s);
      }
      ass = cr.CompiledAssembly;
      return cr.Output.Count == 0;
    }

    static void Main(string[] args)
    {
      Assembly ass = null;
      if (!DynamicCompile(ref ass)) return;

      AppDomainSetup ads = new AppDomainSetup();
      ads.DisallowBindingRedirects = false;
      ads.DisallowCodeDownload = true;
      ads.ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;

      AppDomain newdomain = AppDomain.CreateDomain("NEWDOMAIN", null, ads);
      newdomain.Load(ass.FullName);

      BaseClass yazici = (BaseClass)ass.CreateInstance("DerivedNameSpace.DerivedClass", true, BindingFlags.Default, null, new object[] { "Some text." }, null, null);
      yazici.Write("Another Text");

      ass = null;
      AppDomain.Unload(newdomain);

      DynamicCompile(ref ass); // Error CS0016

      Console.ReadKey();

    }
  }
}
 

The executable and the dynamic libraries are all in the same directory, which is AppDomain.CurrentDomain.BaseDirectory

also i tried reading the assembly file to raw byte[], and loading it by Assembly ass = newdomain.Load(byt)
it didn't work either.
i put a breakpoint on the error line to pause the program, then i could cut and paste the dynamic.dll file to somewhere else, which showed that the file itself was not being used or somehow in the memory.
how am i supposed to renew the derivedclass.cs and recompile it. what is wrong here?
please help me out !!!