我编写了一个C# WPF应用程序来在运行时编译代码。应用程序基本上执行以下步骤
StreamWriter创建代码文件Microsoft.Build.Execution.BuildManager类构建代码文件Assembly.LoadFrom(filePath))assembly.CreateInstance(NamespaceName + "." + ClassName))中包含的类的实例化。I工作正常,但只有一次(我需要重新启动应用程序才能再次完成)
这就是下一次执行过程中发生的情况。
StreamWriter创建代码文件Microsoft.Build.Execution.BuildManager类->Produces生成代码文件--一个错误说明该DLL文件已被锁定。进程无法访问文件“DLL\generatedflexform.dll”,因为其他进程正在使用它
当我省略步骤2时,问题不会发生,因为这样代码文件是相同的。因此,BuildManager不会重新创建/复制dll。
我需要弄清楚如何在BuildManager完成他的工作后释放DLL。这是因为代码文件很可能经常更改,否则,我必须关闭并重新打开应用程序的每一次代码更改。
编辑:我的第一个想法是,BuildManager会导致锁定,但事实并非如此。我更倾向于认为当我试图加载DLL时会发生锁定。我将尝试Shadow副本思考(正如@granadaCoder所提到的)。
private Window LoadWindowFromDll(string filePathToDll)
{
var assembly = Assembly.LoadFrom(filePathToDll);
var window = assembly.CreateInstance(NamespaceName + "." + ClassName) as Window;
return window;
}发布于 2013-03-06 10:12:07
解决方案:
我必须更改LoadWindowFromDllmethod以避免DLL锁定。
private Window LoadWindowFromDll(string filePathToDll)
{
byte[] readAllBytes = File.ReadAllBytes(filePathToDll);
Assembly assembly = Assembly.Load(readAllBytes);
var window = assembly.CreateInstance(NamespaceName + "." + ClassName) as Window;
return window;
}但是,pdb文件被锁定了,当我尝试执行两次时,这会导致构建失败。
我通过在构建文件中添加一行来修正这种行为:
<DebugType>none</DebugType>以下是完整的构建文件:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<AssemblyName>generatedflexform</AssemblyName>
<OutputPath>DLL\</OutputPath>
<OutputType>Library</OutputType>
<DebugType>none</DebugType>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Xaml">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
<Reference Include="WindowsBase" />
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
</ItemGroup>
<ItemGroup>
<Page Include="MyForm.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Compile Include="MyForm.xaml.cs">
<DependentUpon>MyForm.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>接下来是编译magic>公共窗口BuildXamlWindowFromStrings(string,string ){ //Erstellen ( xaml和codeBehind) this.CreateCodeFile( CodeBehind);this.CreateXamlFile (XAML );
//Erstellen der project file
this.CreateProjectFile();
//Build der DLL
//using (var buildManager = BuildManager.DefaultBuildManager)
using (var buildManager = new BuildManager())
{
var result = buildManager.Build(this.CreateBuildParameters(), this.CreateBuildRequest());
if (result.OverallResult == BuildResultCode.Success)
{
return this.LoadWindowFromDll(FolderPath + DllRelativeFilePath + NamespaceName + DllFileExtension);
}
}
//Error handling
var stringbuilder = new StringBuilder();
using (var reader = new StreamReader(DebuggerLogFileName))
{
stringbuilder.Append(reader.ReadToEnd());
}
throw new CompilerException(stringbuilder.ToString());
}辅助方法:
private BuildParameters CreateBuildParameters()
{
var projectCollection = new ProjectCollection();
var buildLogger = new FileLogger { Verbosity = LoggerVerbosity.Detailed, Parameters = "logfile=" + DebuggerLogFileName };
var buildParameters = new BuildParameters(projectCollection) { Loggers = new List<ILogger>() { buildLogger } };
return buildParameters;
}
private BuildRequestData CreateBuildRequest()
{
var globalProperties = new Dictionary<string, string>();
var buildRequest = new BuildRequestData(FolderPath + ProjectFileName, globalProperties, null,
new string[] { "Build" }, null, BuildRequestDataFlags.ReplaceExistingProjectInstance);
return buildRequest;
}发布于 2013-03-05 19:27:08
看看“影子复制”。
影子复制使应用程序域中使用的程序集能够在不卸载应用程序域的情况下进行更新。这对于必须连续可用的应用程序尤其有用。
http://msdn.microsoft.com/en-us/library/ms404279.aspx
另请参阅:
http://gotchahunter.net/2010/12/net-how-do-you-load-an-assembly-programmatically-and-avoid-a-file-lock/
和
http://blogs.msdn.com/b/junfeng/archive/2004/02/09/69919.aspx
https://stackoverflow.com/questions/15229058
复制相似问题