2013-07-16 41 views
1

我使用单声道的Mono.Cecil能包和我快到时,我所说的问题,从一个自定义的MSBuild任务如下:压倒一切的MSBuild我PDB

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,但事实并非如此。

任何建议都会有所帮助。

+0

通常情况下,编译器会生成PDB。所以CSC的电话会生成它。 – jessehouwing

+0

嗨,是的,我已经在[http://msdn.microsoft.com/en-us/library/ms171479%28v=vs.90%29.aspx](http://msdn.microsoft.com /en-us/library/ms171479%28v=vs.90%29.aspx)。在我看来,它发生在构建目标中。但是,当我将值“DependsOnTargets”更改为Build时,我仍然遇到同样的问题。编辑我正在修改它建成后的DLL。 –

+0

仅供参考,您可能想了解PostSharp如何设置它的构建目标,因为它也可以编织。您也可以打开详细或诊断版本输出以查看pdbs何时被写入/覆盖。 –

回答

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. 检查类型使用反射:
    • 负荷引用的您的输出组件的ssemblies
    • 滤波器属性类型继承ITransformation接口
    • 具有这些属性类型施加
  6. 负载查找类型的使用丝丝从柱的匹配组件和类型变换DIR
  7. 执行变换(reflectionDeclaringType,cecilDeclaringTypeDefinition)方法对你反映的类型的属性;这是您的自定义cecil代码应用使用ITransformation接口进行重写的地方

我还创建了另一个接口,以将转换应用于单个类型而不是整个程序集。

所以我结束了ITypeTransformation和IAssemblyTranformation。一个范围到组件,也只是通过反射和塞西尔组装。所述ITypeTransformation经过反射,丝丝组件和反射,丝丝型

一种用于转换例如可以是:

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