如何隐藏Visual Studio中自定义工具生成的文件

我想隐藏我的自定义工具生成的文件,但我找不到任何关于如何完成此操作的文档。

我正在寻找的一个例子是文件背后的WPF代码。 这些文件不会显示在Visual Studio项目视图中,而是使用项目进行编译,并且可在IntelliSense中使用。 文件后面的WPF代码(例如,Window1.gics)由自定义工具生成。

解决方案是创建一个Target,将您的文件添加到Compile ItemGroup,而不是在.csproj文件中显式添加它们。 这样,Intellisense将会看到它们并将它们编译到您的可执行文件中,但它们不会显示在Visual Studio中。

简单的例子

您还需要确保将目标添加到CoreCompileDependsOn属性,以便它在编译器运行之前执行。

这是一个非常简单的例子:

  $(CoreCompileDependsOn);AddToolOutput       

如果将其添加到.csproj文件的底部(就在之前),则“HiddenFile.cs”将包含在您的编译中,即使它没有出现在Visual Studio中。

使用单独的.targets文件

您通常将它放在一个单独的.targets文件中,而不是直接将它放在.csproj文件中,该文件包含在:

  ...  

并使用 .csproj。 即使对于一次性案例,也建议使用.targets文件,因为它将自定义代码与Visual Studio维护的.csproj中的内容分开。

构造生成的文件名

如果要创建通用工具和/或使用单独的.targets文件,则可能不希望显式列出每个隐藏文件。 相反,您希望从项目中的其他设置生成隐藏文件名。 例如,如果您希望所有资源文件在“obj”目录中具有相应的工具生成文件,那么您的目标将是:

      

“IntermediateOutputPath”属性是我们所知的“obj”目录,但如果.targets的最终用户已经自定义了这个,那么您的中间文件将会在同一个地方找到。 如果您希望生成的文件位于主项目目录中而不是“obj”目录中,则可以将其保留为关闭状态。

如果您只想要自定义工具处理现有项类型的某些文件? 例如,您可能希望为所有具有“.xyz”扩展名的页面和资源文件生成文件。

   '$(IntermediateOutputPath)%(FileName)%(Extension).g.cs')"/>   

请注意,您不能在顶级ItemGroup中使用%(扩展)等元数据语法,但您可以在Target中执行此操作。

使用自定义项类型(也称为构建操作)

上面的处理文件具有现有的项目类型,如页面,资源或编译(Visual Studio将其称为“构建操作”)。 如果您的商品是新类型的商品,则可以使用自己的自定义商品类型。 例如,如果您的输入文件被称为“Xyz”文件,则您的项目文件可以将“Xyz”定义为有效的项类型:

    

之后,Visual Studio将允许您在文件属性的Build Action中选择“Xyz”,从而将其添加到.csproj中:

    

现在,您可以使用“Xyz”项类型为工具输出创建文件名,就像之前使用“Resource”项类型一样:

      

使用自定义项目类型时,您可以通过将项目映射到另一个项目类型(也称为构建操作)来使您的项目也由内置机制处理。 如果您的“Xyz”文件确实是.cs文件或.xaml,或者需要制作它们,这将非常有用

EmbeddedResources。 例如,您可以编译所有包含Xyz“Build Action”的文件:

    

或者,如果您的“Xyz”源文件应存储为嵌入式资源,您可以这样表达:

    

请注意,如果将其放在Target中,则第二个示例将不起作用,因为直到核心编译之前才对目标进行求值。 要在Target中进行此工作,您必须在PrepareForBuildDependsOn属性中列出目标名称而不是CoreCompileDependsOn。

从MSBuild调用自定义代码生成器

除了创建.targets文件之外,您可以考虑直接从MSBuild调用工具,而不是使用单独的预构建事件或Visual Studio有缺陷的“自定义工具”机制。

去做这个:

  1. 创建一个类库项目,引用Microsoft.Build.Framework
  2. 添加代码以实现自定义代码生成器
  3. 添加一个实现ITask的类,并在Execute方法中调用自定义代码生成器
  4. 在.targets文件中添加一个UsingTask元素,并在目标中添加对新任务的调用

以下是实现ITask所需的全部内容:

 public class GenerateCodeFromXyzFiles : ITask { public IBuildEngine BuildEngine { get; set; } public ITaskHost HostObject { get; set; } public ITaskItem[] InputFiles { get; set; } public ITaskItem[] OutputFiles { get; set; } public bool Execute() { for(int i=0; i 

这里是UsingTask元素和一个调用它的Target:

       

请注意,此目标的Output元素将输出文件列表直接放入Compile中,因此无需使用单独的ItemGroup来执行此操作。

旧的“自定义工具”机制是如何存在缺陷的,为什么不使用它

关于Visual Studio的“自定义工具”机制的注释:在.NET Framework 1.x中,我们没有MSBuild,因此我们不得不依赖Visual Studio来构建我们的项目。 为了在生成的代码上获取Intellisense,Visual Studio有一个名为“自定义工具”的机制,可以在文件的“属性”窗口中进行设置。 该机制在几个方面存在根本缺陷,这就是它被MSBuild目标取代的原因。 “自定义工具”function的一些问题是:

  1. 每当编辑和保存文件时,“自定义工具”都会构造生成的文件,而不是在编译项目时。 这意味着在外部修改文件的任何内容(例如修订控制系统)都不会更新生成的文件,并且您经常会在可执行文件中获得过时的代码。
  2. 除非您的收件人同时拥有Visual Studio和“自定义工具”,否则“自定义工具”的输出必须随源树一起提供。
  3. “自定义工具”必须安装在注册表中,不能简单地从项目文件中引用。
  4. “自定义工具”的输出未存储在“obj”目录中。

如果您使用旧的“自定义工具”function,我强烈建议您切换到使用MSBuild任务。 它可以很好地与Intellisense一起使用,并允许您在不安装Visual Studio的情况下构建项目(您只需要.NET Framework)。

您的自定义构建任务何时运行?

通常,您的自定义构建任务将运行:

  • 在Visual Studio打开解决方案的后台,如果生成的文件不是最新的
  • 在后台随时保存Visual Studio中的一个输入文件
  • 如果生成的文件不是最新的,那么无论何时构建
  • 任何时候你重建

更确切地说:

  1. Visual Studio启动时以及每次在Visual Studio中保存任何文件时都会运行IntelliSense增量构建。 如果输出文件丢失,这将运行您的生成器任何输入文件都比生成器输出更新。
  2. 只要在Visual Studio中使用任何“构建”或“运行”命令(包括菜单选项并按F5),或从命令行运行“MSBuild”,就会运行常规增量构建。 与IntelliSense增量构建一样,如果生成的文件不是最新的,它也将仅运行您的生成器
  3. 只要在Visual Studio中使用任何“重建”命令,或者从命令行运行“MSBuild / t:Rebuild”,就会运行常规完整构建。 如果有任何输入或输出,它将始终运行您的发电机。

您可能希望强制您的生成器在其他时间运行,例如某些环境变量更改时,或强制它在后台同步运行。

  • 要使生成器重新运行,即使没有输入文件已更改,最好的方法通常是向目标添加一个额外的输入,这是一个存储在“obj”目录中的虚拟输入文件。 然后,只要环境变量或某些外部设置发生更改,应该强制生成器工具重新运行,只需触摸此文件(即创建它或更新其修改日期)。

  • 要强制生成器同步运行而不是等待IntelliSense在后台运行它,只需使用MSBuild构建您的特定目标。 这可以像执行“MSBuild / t:GenerateToolOutput”一样简单,或者VSIP可以提供调用自定义构建目标的内置方式。 或者,您只需调用Build命令并等待它完成。

请注意,本节中的“输入文件”是指Target元素的“Inputs”属性中列出的内容。

最后的笔记

您可能会收到来自Visual Studio的警告,它不知道是否信任您的自定义工具.targets文件。 要解决此问题,请将其添加到HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ VisualStudio \ 9.0 \ MSBuild \ SafeImports注册表项。

以下是所有部分的实际.targets文件的概述:

   $(CoreCompileDependsOn);GenerateToolOutput         

如果您有任何问题或者您有任何不明白的地方,请告诉我。

要从Visual Studio隐藏项目,请向项目添加Visible元数据属性。 InProject元数据显然也是这样做的。

可见: http : //msdn.microsoft.com/en-us/library/ms171468(VS.90).aspx

InProject: http : //blogs.msdn.com/b/jomo_fisher/archive/2005/01/25/360302.aspx

    false  false   

我知道这样做的唯一方法是在proj文件中添加生成的文件以依赖于你想要隐藏的文件。

例如:

     test.cs   

如果您删除了DependentUpon元素,那么该文件会显示在另一个文件旁边而不是它后面…您的生成器如何添加文件? 你能告诉我们用例以及你希望它如何工作吗?

我想你想看看这里: http : //msdn.microsoft.com/en-us/library/ms171453.aspx 。

具体来说,“执行期间创建项目”部分。