删除 CodeDomProvider 编译创建的程序集时访问被拒绝?
如果在编译完成后在 .NET 中使用 CodeDomProvider 类,则无法删除输出程序集。我希望能够删除输出程序集。 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
}
编辑 作为一种解决方法,我在类上使用静态构造函数来搜索临时文件夹并删除以前创建的程序集。
If you use the CodeDomProvider class in .NET after the compilation is complete you can't delete the output assembly. I want to be able to delete the output assembly. File.Delete returns an access denied exception.
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 As a work around I'm using a static constructor on the class that searches the temp folder and deletes previously created assemblies.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我怀疑问题在于程序集已加载(在内存中),并且打开了输出文件,就像当前加载的任何其他程序集将具有其可执行文件的句柄一样。
dom 实例或 CompilerResults 实例也有可能(尽管我认为不太可能)具有对打开文件的引用。 IDisposable 也不是,所以我怀疑他们没有保持文件打开。
可能的解决方案:
您可以将程序集编译到内存中。也就是说,不输出文件。这就解决了眼前的问题。但是,您仍然遇到编译后的程序集保留在内存中的问题。如果不拆除应用程序域,就无法卸载程序集。
您可以创建一个单独的应用程序域来进行编译,然后将结果传回您的主应用程序域。然后,您可以关闭编译器应用程序域,这将从内存中删除已编译的程序集,并释放引用您刚刚创建的文件的任何文件句柄。然后您的主程序可以删除有问题的文件。
I suspect the problem is that the assembly is loaded (in memory), and has the output file open, just as any other assembly that is currently loaded will have a handle to its executable file.
It's also possible (although I consider it unlikely) that the dom instance or the
CompilerResults
instance has a reference to the opened file. Neither isIDisposable
, so I suspect they're not holding the file open.Possible solutions:
You can compile the assembly to memory. That is, don't output a file. That solves the immediate problem. However, you still have the problem that the compiled assembly remains in memory. There's no way to unload an assembly without tearing down the app domain.
You can create a separate app domain to do the compile, and then communicate the results back to your main app domain. You can then shut down the compiler app domain, which will remove the compiled assembly from memory and also release any file handles that are referencing the file you just created. Your main program can then delete the file in question.