msbuild覆盖我的pdb

时间:2013-07-16 18:06:15

标签: .net msbuild msbuild-task mono.cecil

我正在使用mono的Mono.Cecil包,当我从自定义的msbuild任务调用以下内容时遇到问题:

ModuleDefinition.Write(AssemblyFileName, new WriterParameters { WriteSymbols = true });

装配保存正常,完全符合我的要求。如果我更改了汇编文件名以测试是否创建了pdb,那么当它被替换为另一个pdb时,它正在调试。但是,当我正常构建时,程序集的pdb仍然是旧的pdb。我认为mono正在创建pdb,而msbuild正在用旧的覆盖它。

这是我尝试导入项目的目标:

<PropertyGroup>
    <TaskAssemblyFileDir>$(SolutionDir)PropertyObserver.Tasks\$(OutDir)</TaskAssemblyFileDir>
    <TaskAssemblyFileUnescapeDir>$([MSBuild]::Unescape('$(TaskAssemblyFileDir)'))</TaskAssemblyFileUnescapeDir>
    <TaskAssemblyFile>$(TaskAssemblyFileUnescapeDir)PropertyObserver.Tasks.dll</TaskAssemblyFile>
</PropertyGroup>
<UsingTask TaskName="PropertyObserverTask" AssemblyFile="$(TaskAssemblyFile)" />
<Target Name="PropertyObserver" DependsOnTargets="AfterBuild">
    <PropertyObserverTask AssemblyPath="$(TargetPath)" />
</Target>

我不确定目标msbuild调用什么来创建pdb。我推测它是AfterBuild,但事实并非如此。

任何建议都会有所帮助。

1 个答案:

答案 0 :(得分:0)

如果要应用自定义重写,请务必覆盖obj文件夹中的目标文件。

这一点至关重要,因为msbuild会从这里复制这些文件。

请参阅我的回答HERE

在我的例子中,除了我的重写任务外,我还使用PostSharp。

但这对你的案子来说没问题:

<PropertyGroup>
    <CompileDependsOn>
        $(CompileDependsOn);
        ApplyILRewriting
    </CompileDependsOn>
    <BuildDependsOn>
        $(BuildDependsOn);
        AfterILRewritingPostBuild
    </BuildDependsOn>
</PropertyGroup>

<Target Name="ApplyILRewriting">
    <ILTransformationTask IntermediateAssemblyPath="$(ProjectDir)$(BaseIntermediateOutputPath)$(Configuration)\$(TargetFileName)" />
</Target>
<!-- Override this target in another file. Build your nuget packages here for example. -->
<Target Name="AfterILRewritingPostBuild">
</Target>

关于我的解决方案的一个很酷的部分是,转换程序集的代码是从目标程序集加载的。因此,您可以在属性上实现接口,并将属性放在目标类型上。它将在接口上运行应用于目标的每个属性的方法。

这使您可以在目标程序集中包含重写指令,这意味着对于每个项目,您都可以轻松添加自己的转换。

如您所见,我在obj文件夹中传递程序集的路径。 我的解决方案是这样的(我不想在此刻发布完整的源代码,抱歉):

  1. 在obj文件夹中创建预转换文件夹
  2. 将所有文件从obj /复制到文件夹
  3. 创建一个帖子转换文件夹
  4. 将所有文件从obj /复制到文件夹
  5. 使用反射检查类型:
    • 加载输出程序集的引用程序集
    • 过滤属性类型继承ITransformation接口
    • 查找已应用这些属性类型的类型
  6. 使用post transform dir
  7. 中的cecil加载匹配的装配和类型
  8. 对您在类型上反映的属性执行Transform(reflectionDeclaringType,cecilDeclaringTypeDefinition)方法;这是您的自定义cecil代码使用ITransformation接口应用重写的地方
  9. 我还创建了另一个接口,不是将转换应用于单个类型,而是应用于整个程序集。

    所以我最终得到了ITypeTransformation和IAssemblyTranformation。一个作用于组件,也只通过反射和塞西尔组件。 ITypeTransformation传递反射,cecil汇编和反射,cecil类型

    转换的一个例子可能是:

    public class TestTypeTransformation : Attribute, ITypeTransformationAttribute
    {
         public void ApplyTransformation(
                Assembly preTransformationReflectionAssembly, 
                AssemblyDefinition postTransformationCecilAssembly, 
                Type reflectionType, 
                TypeDefinition cecilType)
        {
            // Your custom rewriting here
        }
    }