Отказано в доступе при удалении сборки, созданной компиляцией CodeDomProvider? - PullRequest
3 голосов
/ 17 мая 2011

Если вы используете класс CodeDomProvider в .NET после завершения компиляции, вы не сможете удалить выходную сборку.Я хочу иметь возможность удалить выходную сборку.File.Delete возвращает исключение об отказе в доступе.

string asmPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N") + ".exe");
string keyPath = "some path to a *.snk file that works";
// build compiler
CodeDomProvider dom = CodeDomProvider.CreateProvider("VisualBasic");
CompilerParameters cp = new CompilerParameters();
cp.TreatWarningsAsErrors = false;
cp.GenerateInMemory = false;
cp.GenerateExecutable = true;
cp.CompilerOptions = "/target:winexe /keyfile:\"" + keyPath + "\"";
cp.OutputAssembly = asmPath;
// add all the other assembly references
string netPath = @"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\";
cp.ReferencedAssemblies.Add(netPath + @"System.dll");
cp.ReferencedAssemblies.Add(netPath + @"System.Core.dll");
cp.ReferencedAssemblies.Add(netPath + @"System.Data.dll");
cp.ReferencedAssemblies.Add(netPath + @"System.Xml.dll");
CompilerResults cr = dom.CompileAssemblyFromSource(cp, new string[] { code });
if (cr.Errors.Count == 0)
{
    cr.TempFiles.Delete();
    dom.Dispose();
// do stuff
...
//
    File.Delete(asmPath); // fails here Access Denied
}

Edit В качестве обходного пути я использую статический конструктор для класса, который ищет временную папку и удаляет ранее созданные сборки.

1 Ответ

3 голосов
/ 18 мая 2011

Я подозреваю, что проблема в том, что сборка загружена (в памяти) и имеет открытый выходной файл, так же как и любая другая загружаемая сборка будет иметь дескриптор своего исполняемого файла.также возможно (хотя я считаю маловероятным), что экземпляр dom или экземпляр CompilerResults имеет ссылку на открытый файл.Также нет IDisposable, поэтому я подозреваю, что они не держат файл открытым.

Возможные решения:

Вы можете скомпилировать сборку в память.То есть не выводить файл.Это решает насущную проблему.Тем не менее, у вас все еще есть проблема, что скомпилированная сборка остается в памяти.Невозможно выгрузить сборку, не разрушив домен приложения.

Вы можете создать отдельный домен приложения для выполнения компиляции, а затем передать результаты обратно в основной домен приложения.Затем вы можете закрыть домен приложения компилятора, который удалит скомпилированную сборку из памяти, а также освободит все файловые дескрипторы, которые ссылаются на только что созданный файл.Ваша основная программа может затем удалить рассматриваемый файл.

...