首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在BuildManager中创建后释放DLL

在BuildManager中创建后释放DLL
EN

Stack Overflow用户
提问于 2013-03-05 16:27:56
回答 2查看 922关注 0票数 1

我编写了一个C# WPF应用程序来在运行时编译代码。应用程序基本上执行以下步骤

  1. 单击按钮编译内容
  2. 通过StreamWriter创建代码文件
  3. 使用Microsoft.Build.Execution.BuildManager类构建代码文件
  4. 使用反射访问DLL文件(Assembly.LoadFrom(filePath))
  5. 创建dll (assembly.CreateInstance(NamespaceName + "." + ClassName))中包含的类的实例化。

I工作正常,但只有一次(我需要重新启动应用程序才能再次完成)

这就是下一次执行过程中发生的情况。

  1. 单击按钮编译内容
  2. 通过StreamWriter创建代码文件
  3. 使用Microsoft.Build.Execution.BuildManager类->Produces生成代码文件--一个错误说明该DLL文件已被锁定。

进程无法访问文件“DLL\generatedflexform.dll”,因为其他进程正在使用它

当我省略步骤2时,问题不会发生,因为这样代码文件是相同的。因此,BuildManager不会重新创建/复制dll。

我需要弄清楚如何在BuildManager完成他的工作后释放DLL。这是因为代码文件很可能经常更改,否则,我必须关闭并重新打开应用程序的每一次代码更改。

编辑:我的第一个想法是,BuildManager会导致锁定,但事实并非如此。我更倾向于认为当我试图加载DLL时会发生锁定。我将尝试Shadow副本思考(正如@granadaCoder所提到的)。

代码语言:javascript
复制
private Window LoadWindowFromDll(string filePathToDll)
{
    var assembly = Assembly.LoadFrom(filePathToDll);
    var window = assembly.CreateInstance(NamespaceName + "." + ClassName) as Window;
    return window;
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-03-06 10:12:07

解决方案:

我必须更改LoadWindowFromDllmethod以避免DLL锁定。

代码语言:javascript
复制
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文件被锁定了,当我尝试执行两次时,这会导致构建失败。

我通过在构建文件中添加一行来修正这种行为:

代码语言:javascript
复制
<DebugType>none</DebugType>

以下是完整的构建文件:

代码语言:javascript
复制
<?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 );

代码语言:javascript
复制
        //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());
    }

辅助方法:

代码语言:javascript
复制
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;
}
票数 1
EN

Stack Overflow用户

发布于 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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15229058

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档