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

发布于 2024-09-12 07:22:28 字数 632 浏览 3 评论 0 原文

我正在开发一个自定义 MSBuild 任务,该任务构建 ORM 层,并在项目。我受到 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 锁定?

I'm developing a custom MSBuild task that builds an ORM layer, and using it in a project. I'm being hampered by Visual Studio's behaviour of holding onto MSBuild task DLLs and not letting go.

I'd like to organize my solution like this;

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)" />

However, when project (2) builds, it locks onto the assembly from project (1). So now I can't build project (1) again without closing the solution and re-opening it.

Is there any way I can organize things so that the custom build task is not kept locked by Visual Studio?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

内心激荡 2024-09-19 07:22:28

编辑: 赛义德·易卜拉欣·哈希米,字面意思是写了关于 msbuild 的书,建议 AppDomainIsolatedTask 类以获得更好的方法)

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

找到了这个 来自 Dan Moseley 的论坛帖子 ,来自微软的 MSBuild 开发人员之一:

你好,

不幸的是,这是因为 MSBuild 在
主应用程序域。 CLR 不允许卸载程序集
来自应用程序域,因为这允许对其进行重要的优化
部分。

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


msbuild 上的开发人员
丹莫斯利 - MSFT

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

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

       
    <目标名称=“构建”>   
         >   
    
    
  • 如果需要,可以将其添加到 Visual Studio,但使用配置管理器来确保它内置在任何配置中。只需让 VS 处理源代码控制等事务,而不是构建。

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

    ;   
         $(SolutionDir)Prebuild\Prebuild.csproj   
       
    <目标名称=“BeforeBuild”>   
         >   
    
    

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

(Edit: Sayed Ibrahim Hashimi, who literally wrote the book on msbuild, suggests the AppDomainIsolatedTask class for a better approach)

I've managed to solve this one myself...

Found this forum post from Dan Moseley, one of the MSBuild developers from Microsoft:

Hi there,

Unfortunately this is because MSBuild loads task assemblies in the
primary appdomain. The CLR does not allow assemblies to unload
from an appdomain as this allows important optimizations on their
part.

The only workarounds I suggest is to call out tomsbuild.exe to
build the projects that use the task. To do this, create
MSBuild.exe <> as an external tool in VS.

Dan
developer on msbuild
DanMoseley - MSFT

So, it seems that to stop the locks, you must spawn out a new MSBuild.exe process. It can't be the one that runs inside Visual Studio, because when MSBuild runs, it loads the tasks into Visual Studio's primary app domain, and that can never be unloaded.

  • create a new MSBuild project (a .csproj or similar) which overrides the 'Build' Target and performs your custom actions, eg;

    <!-- fragment of Prebuild.csproj -->   
    <Target Name="Build">   
         <BuildOrmLayerTask Repository="$(Repository)" />   
    </Target>
    
  • Add it to visual studio if you want, but use Configuration Manager to make sure it is notbuilt in any configuration. Just let VS take care of source control and suchlike, not building.

  • Edit the .csproj file of the project that depends on Prebuild.csproj. Add a BeforeBuild target which invokes MSBuild using the Exec task. This will start a new process, and when that process ends, the file locks are released. Example;

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

Now, when you build the dependent project, it executes MSBuild in a new process before running the compile.

知足的幸福 2024-09-19 07:22:28

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

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

请告诉我这是否适合您。

Can you edit the project files and include the following property declaration

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

Let me know if that works for you.

倾其所爱 2024-09-19 07:22:28

正如我在针对 @Al-Muhandis 的评论中提到的,似乎可以围绕自定义任务创建一个包装器,以便包装器被锁定,但自定义任务 DLL 不会被锁定。我已经通过 isolated-task 项目初步尝试这样做。它可能有 bug,并且目前仅适用于 VS2008。欢迎拉请求。

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

As I mentioned in a comment directed at @Al-Muhandis, it seems possible to create a wrapper around the custom task so that the wrapper gets locked but not the custom task DLL. I have taken an initial shot at doing so with the isolated-task project. It may be buggy, and it only works with VS2008 for now. Pull requests welcome.

The idea for the project was based on the observation that tasks deriving from MarshalByRefObject (using, perhaps, AppDomainIsolatedTask) appear to be loaded into the main application domain for reflection purposes, but a new application domain is created to execute the task. Since loading into the main application domain still seems to lock the DLL, it was useful to create a DLL with a task derived from AppDomainIsolatedTask that loads the custom task DLLs. That way, the wrapper DLL gets locked, but because it executes in its own app domain, the custom task DLLs are unloaded when the wrapper task's executing domain is unloaded. This procedure avoids keeping a lock on the custom task DLLs after the build is complete.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文