Visual Studio 2008锁定自定义MSBuild任务程序集

时间:2010-07-30 12:51:17

标签: c# visual-studio-2008 msbuild msbuild-task

我正在开发一个自定义MSBuild任务,用于构建ORM layer并在项目中使用它。我受到Visual Studio保留MSBuild任务DLL而不放手的行为的阻碍。

我想像这样组织我的解决方案;

My Solution
 |
 +- (1) ORM Layer Custom Task Project
 |  |
 |  +- BuildOrmLayerTask.cs     // here's my task
 |  
 +- (2) Business Logic Project  // and here's the project that uses it.
    |
    +- <UsingTask TaskName="BuildOrmLayerTask" AssemblyFile="$(TaskAssembly)" />

但是,当项目(2)构建时,它会从项目(1)锁定到程序集。所以现在我无法在不关闭解决方案并重新打开它的情况下再次构建项目(1)。

我有什么方法可以组织事情,以便Visual Studio不会锁定自定义构建任务吗?

3 个答案:

答案 0 :(得分:25)

编辑: Sayed Ibrahim Hashimi,在msbuild上按字面意思wrote the book,建议使用AppDomainIsolatedTask类来获得更好的方法。

我自己设法解决了这个......

找到了这个来自Microsoft的MSBuild开发人员之一的forum post from Dan Moseley

  

你好,

     

不幸的是,这是因为MSBuild加载了任务程序集   主appdomain。 CLR不允许卸载程序集   从appdomain,因为这允许对他们的重要优化   一部分。

     

我建议的唯一解决方法是调用tomsbuild.exe   构建使用该任务的项目。为此,请创建   MSBuild.exe&lt;&gt;作为VS的外部工具。

     


  开发人员在msbuild上   DanMoseley - MSFT

因此,似乎要停止锁定,您必须生成一个新的MSBuild.exe进程。它不能是在Visual Studio中运行的那个,因为当MSBuild运行时,它会将任务加载到Visual Studio的主应用程序域中,并且永远不能卸载。

  • 创建一个新的MSBuild项目(.csproj或类似项目),它覆盖“Build”目标并执行自定义操作,例如;

    <!-- fragment of Prebuild.csproj -->   
    <Target Name="Build">   
         <BuildOrmLayerTask Repository="$(Repository)" />   
    </Target>
    
  • 如果需要,可将其添加到visual studio,但使用Configuration Manager确保在任何配置中 。只是让VS负责源控制等,而不是构建。

  • 编辑依赖于Prebuild.csproj的项目的.csproj文件。添加BeforeBuild目标,使用Exec任务调用MSBuild。这将启动一个新进程,当该进程结束时,将释放文件锁。实施例;

    <PropertyGroup>   
         <PrebuildProject>$(SolutionDir)Prebuild\Prebuild.csproj</PrebuildProject>   
    </PropertyGroup>   
    <Target Name="BeforeBuild">   
         <Exec Command="msbuild.exe &quot;$(PrebuildProject)&quot;" />   
    </Target>
    

现在,当您构建依赖项目时,它会在运行编译之前在新进程中执行MSBuild。

答案 1 :(得分:4)

您可以编辑项目文件并包含以下属性声明

<PropertyGroup>
    <GenerateResourceNeverLockTypeAssemblies>true</GenerateResourceNeverLockTypeAssemblies>
</PropertyGroup>

请告诉我这是否适合您。

答案 2 :(得分:3)

正如我在针对@ Al-Muhandis的评论中提到的,似乎可以围绕自定义任务创建一个包装器,以便包装器被锁定但不是自定义任务DLL。我已经开始使用isolated-task项目进行初步尝试。它可能是错误的,它现在只适用于VS2008。拉请求欢迎。

该项目的想法是基于这样的观察结果:从MarshalByRefObject(可能使用AppDomainIsolatedTask)派生的任务似乎被加载到主应用程序域中以用于反射目的,但是新的应用程序创建域以执行任务。由于加载到主应用程序域仍然似乎锁定了DLL,因此创建一个带有从AppDomainIsolatedTask派生的加载自定义任务DLL的任务的DLL非常有用。这样,包装器DLL被锁定,但由于它在自己的应用程序域中执行,因此在卸载包装器任务的执行域时卸载自定义任务DLL。此过程可避免在构建完成后保留对自定义任务DLL的锁定。