如何通过隐藏在Visual Studio中自定义工具生成的文件 [英] How to hide files generated by custom tool in Visual Studio

查看:787
本文介绍了如何通过隐藏在Visual Studio中自定义工具生成的文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想我的自定义工具生成的文件被隐藏,但我无法找到如何做到这一点的任何文档。

I would like the files generated by my custom tool to be hidden, but I cannot find any documentation on how this is done.

什么我正在寻找一个例子是隐藏文件WPF code。这些文件未在Visual Studio项目视图中显示,但与该项目被编译并在IntelliSense可用。 WPF $隐藏文件C $ C(Window1.g.i.cs,例如),由自定义工具生成的。

An example of what I'm looking for is WPF code behind files. These files are not displayed in the Visual Studio project view, yet are compiled with the project and are available in IntelliSense. WPF code behind files (Window1.g.i.cs, for example), are generated by a custom tool.

推荐答案

解决方案是建立一个目标,增加了您的文件编译的ItemGroup而不是在.csproj的文件中明确添加。这样,智能感知会看到他们,他们会被编译成可执行文件,但他们不会在Visual Studio中显示出来。

The solution is to create a Target that adds your files to the Compile ItemGroup rather than adding them explicitly in your .csproj file. That way Intellisense will see them and they will be compiled into your executable, but they will not show up in Visual Studio.

简单的例子

您还需要确保你的目标是加入 CoreCompileDependsOn 属性,因此它会在编译器运行之前执行。

You also need to make sure your target is added to the CoreCompileDependsOn property so it will execute before the compiler runs.

下面是一个非常简单的例子:

Here is an extremely simple example:

<PropertyGroup>
  <CoreCompileDependsOn>$(CoreCompileDependsOn);AddToolOutput</CoreCompileDependsOn>
</PropertyGroup>

<Target Name="AddToolOutput">
  <ItemGroup>
    <Compile Include="HiddenFile.cs" />
  </ItemGroup>
</Target>

如果您添加到您的.csproj文件的底部(之前&LT; /项目&GT; ),你的HiddenFile.cs将被包含在你的编译即使它不会出现在Visual Studio中

If you add this to the bottom of your .csproj file (just before </Project>), your "HiddenFile.cs" will be included in your compilation even though it doesn't appear in Visual Studio.

使用单独的文件.targets

而不是直接在.csproj的文件放上,你一般会放在它包围一个单独的文件.targets:

Instead of placing this directly in your .csproj file, you would generally placed it in a separate .targets file surrounded by:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  ...
</Project>

和导入与&LT你的.csproj;导入项目=MyTool.targets&GT; 。因为它在.csproj的东西是由Visual Studio保持分开你的自定义code一个.targets文件甚至建议为一次性的情况。

and import into your .csproj with <Import Project="MyTool.targets">. A .targets file is recommended even for one-off cases because it separates your custom code from the stuff in .csproj that is maintained by Visual Studio.

构建生成的文件名(S)

如果你正在创建一个通用工具和/或使用一个单独的文件.targets,你可能不希望明确列出每个隐藏文件。相反,你要生成从项目其他设置隐藏的文件名。例如,如果你希望所有的资源文件都在目标文件目录中相应的工具生成的文件,你的目标将是:

If you are creating a generalized tool and/or using a separate .targets file, you probably don't want to explicitly list each hidden file. Instead you want to generate the hidden file names from other settings in the project. For example if you want all Resource files to have corresponding tool-generated files in the "obj" directory, your Target would be:

<Target Name="AddToolOutput">
  <ItemGroup>
    <Compile Include="@(Resource->'$(IntermediateOutputPath)%(FileName)%(Extension).g.cs')" />
  </ItemGroup>
</Target>

在IntermediateOutputPath属性是我们都知道的目标文件目录,但如果你.targets的最终用户已经定制了这个你中间文件将STIL在相同的地方被发现。如果preFER您生成的文件是在主项目目录,而不是在目标文件的目录,你可以离开这个功能。

The "IntermediateOutputPath" property is what we all know as the "obj" directory, but if the end-user of your .targets has customized this your intermediate files will stil be found in the same place. If you prefer your generated files to be in the main project directory and not in the "obj" directory, you can leave this off.

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

If you want only some of the files of an existing item type to be processed by your custom tool? For example, you may want to generate files for all Page and Resource files with a ".xyz" extension.

<Target Name="AddToolOutput">
  <ItemGroup>
    <MyToolFiles Include="@(Page);@(Resource)" Condition="'%(Extension)'=='.xyz' />
    <Compile Include="@(MyToolFiles->'$(IntermediateOutputPath)%(FileName)%(Extension).g.cs')"/>
  </ItemGroup>
</Target>

请注意,你不能使用元数据的语法类似%(扩展)在顶层的ItemGroup,但你可以在目标内这样做。

Note that you can't use the metadata syntax like %(Extension) in a top-level ItemGroup but you can do so within a Target.

使用自定义的项目类型(又名生成操作)

这有现成的项目类型以上处理的文件,如页面,资源,编译或(Visual Studio中称此为建设行动)。如果你的项目是一个新的类型的文件,你可以用自己的自定义项目类型。例如,如果你输入的文件被称为XYZ的文件,你的项目文件可以定义XYZ作为一个有效的项目类型:

The above processes files that have an existing item type such as Page, Resource, or Compile (Visual Studio calls this the "Build Action"). If your items are a new kind of file you can use your own custom item type. For example if your input files are called "Xyz" files, your project file can define "Xyz" as a valid item type:

<ItemGroup>
  <AvailableItemName Include="Xyz" />
</ItemGroup>

之后,Visual Studio将让你在文件的属性生成操作选择XYZ,造成这种被添加到您的.csproj:

after which Visual Studio will allow you to select "Xyz" in the Build Action in the file's properties, resulting in this being added to your .csproj:

<ItemGroup>
  <Xyz Include="Something.xyz" />
</ItemGroup>

现在您可以使用XYZ项目类型创建工具的输出文件名,就像我们做了$ P与资源项目类型pviously $:

Now you can use the "Xyz" item type to create the filenames for tool output, just as we did previously with the "Resource" item type:

<Target Name="AddToolOutput">
  <ItemGroup>
    <Compile Include="@(Xyz->'$(IntermediateOutputPath)%(FileName)%(Extension).g.cs')" />
  </ItemGroup>
</Target>

在使用自定义项目类型,你可能会导致你的物品还可以通过内置的机制,将其映射到另一个项目类型(又名生成操作)来处理。如果你的XYZ文件是真的.CS文件或的.xaml或这是有用的,如果他们需要作出

When using a custom item type you can cause your items to also be handled by built-in mechanisms by mapping them to another item type (aka Build Action). This is useful if your "Xyz" files are really .cs files or .xaml or if they need to be made

EmbeddedResources。例如,您可能会导致XYZ的建设行动中的所有文件也被编译:

EmbeddedResources. For example you can cause all files with "Build Action" of Xyz to also be compiled:

<ItemGroup>
  <Compile Include="@(Xyz)" />
</ItemGroup>

或者,如果你的XYZ源文件应该被存储为嵌入的资源,你可以前preSS这种方式:

Or if your "Xyz" source files should be stored as embedded resources, you can express it this way:

<ItemGroup>
  <EmbeddedResource Include="@(Xyz)" />
</ItemGroup>

请注意,第二个示例不会,如果你把它放在目标内部,工作,因为目标没有得到评估,直到核心编译之前。为了使这一工作目标里面,你必须列出prepareForBuildDependsOn属性,而不是CoreCompileDependsOn目标名称。

Note that the second example won't work if you put it inside the Target, since the target isn't evaluated until just before the core compile. To make this work inside a Target you have to list the target name in PrepareForBuildDependsOn property instead of CoreCompileDependsOn.

MSBuild中调用您的自定义code发电机

具有如走得更远,创建.targets文件,你可能会考虑直接从的MSBuild调用你的工具,而不是使用单独的pre-生成事件或Visual Studio的缺陷自定义工具机制。

Having gone as far as creating a .targets file, you might consider invoking your tool directly from MSBuild rather than using a separate pre-build event or Visual Studio's flawed "Custom Tool" mechanism.

要做到这一点:


  1. 一起Microsoft.Build.Framework参考创建一个类库项目

  2. 添加code来实现自定义的code发电机

  3. 添加一个实现ITask类,并在执行方法调用定制code发电机

  4. UsingTask 元素添加到您的.targets文件,并在你的目标的调用添加到您的新任务

  1. Create a Class Library project with a reference to Microsoft.Build.Framework
  2. Add the code to implement your custom code generator
  3. Add a class that implements ITask, and in the Execute method call your custom code generator
  4. Add a UsingTask element to your .targets file, and in your target add a call to your new task

下面是你需要实现ITask:

Here is all you need to implement 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<InputFiles.Length; i++)
      File.WriteAllText(OutputFiles[i].ItemSpec,
        ProcessXyzFile(
          File.ReadAllText(InputFiles[i].ItemSpec)));
  }

  private string ProcessXyzFile(string xyzFileContents)
  {
    // Process file and return generated code
  }
}

这是调用它的UsingTask元素和目标:

And here is the UsingTask element and a Target that calls it:

<UsingTask TaskName="MyNamespace.GenerateCodeFromXyzFiles" AssemblyFile="MyTaskProject.dll" />


<Target Name="GenerateToolOutput">

  <GenerateCodeFromXyzFiles
      InputFiles="@(Xyz)"
      OutputFiles="@(Xyz->'$(IntermediateOutputPath)%(FileName)%(Extension).g.cs')">

    <Output TaskParameter="OutputFiles" ItemGroup="Compile" />

  </GenerateCodeFromXyzFiles>
</Target>

请注意,这个目标的输出单元输出的文件的列表,直接放入编译,所以没有必要使用单独的ItemGroup做到这一点。

Note that this target's Output element places the list of output files directly into Compile, so there is no need to use a separate ItemGroup to do this.

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

在Visual Studio中的自定义工具机制的注意事项:在.​​NET框架1.x中,我们没有MSBuild的,所以我们不得不依靠的Visual Studio来构建我们的项目。为了得到智能感知上产生code,Visual Studio中有一个名为自定义工具,可以在文件属性窗口中设置机制。该机制是根本性的缺陷在几个方面,这就是为什么它用的MSBuild靶代替。一些与自定义工具功能的问题是:

A note on Visual Studio's "Custom Tool" mechanism: In NET Framework 1.x we didn't have MSBuild, so we had to rely on Visual Studio to build our projects. In order to get Intellisense on generated code, Visual Studio had a mechanism called "Custom Tool" that can be set in the Properties window on a file. The mechanism was fundamentally flawed in several ways, which is why it was replaced with MSBuild targets. Some of the problems with the "Custom Tool" feature were:


  1. 自定义工具构建只要文件被编辑并保存生成的文件,而不是当项目进行编译。这意味着,任何修改文件外(如版本控制系统)不会更新生成的文件,你经常在你的可执行文件会过时code。

  2. 自定义工具的输出必须与你的源代码树被运除非收件人也有Visual Studio和你的自定义工具。

  3. 在自定义工具必须安装在注册表中的,不能简单地从项目文件引用。

  4. 定制工具的输出不被存储在物镜目录中。

如果您使用的是旧的自定义工具功能,我强烈建议您切换到使用MSBuild任务。它具有智能感知运作良好,并让你建立你的项目,甚至没有安装Visual Studio(所有你需要的是.NET框架)。

If you are using the old "Custom Tool" feature, I strongly recommend you switch to using a MSBuild task. It works well with Intellisense and allows you to build your project without even installing Visual Studio (all you need is NET Framework).

当您将自定义生成任务运行?

在一般的自定义生成任务运行:

In general your custom build task will run:


  • 在当Visual Studio中打开该解决方案,如果生成的文件是不是最新的
  • 背景
  • 在后台随时保存在Visual Studio
  • 输入文件之一
  • 您打造,如果生成的文件是不是最新的任何时间

  • 任何时候你重建

  • In the background when Visual Studio opens the solution, if the generated file is not up to date
  • In the background any time you save one of the input files in Visual Studio
  • Any time you build, if the generated file is not up to date
  • Any time you rebuild

要更precise:


  1. 当Visual Studio的启动和每一次的任何文件被保存在Visual Studio中的一个智能感知增量生成运行。如果输出文件丢失任何输入文件比发生器输出更新这将运行您的发电机。

  2. 当你使用任何生成或运行,在Visual Studio中(包括菜单选项和pressing F5)命令定期增量编译运行时,或者当你在命令行中运行的MSBuild。像智能感知增量生成,它也将只运行您的发电机,如果生成的文件是不是最新的

  3. 当你使用任何重建命令,在Visual Studio中经常全力打造运行时,或者当您运行的MSBuild /吨:重建的命令行。如果有任何输入或输出,它会一直运行发电机。

您可能要强制发电机在其他时间,如当一些环境变量的变化运行,或者强迫它同步运行,而在后台运行。

You may want to force your generator to run at other times, such as when some environment variable changes, or force it to run synchronously rather in the background.


  • 要导致重新运行发电,即使没有输入文件已更改,最好的解决方法通常是一个额外的输入添加到您的目标是保存在目标文件目录中的虚拟输入文件。然后,每当一个环境变量或一些外部设置更改应该强迫你的生成工具来重新运行,只需轻触该文件(即创建或更新其修改日期)。

  • To cause the generator to re-run even when no input files have changed, the best way is usually to add an additional Input to your Target which is a dummy input file stored in the "obj" directory. Then whenever an environment variable or some external setting changes that should force your generator tool to re-run, simply touch this file (ie. create it or update its modified date).

要促使发电机运行同步,而不是等待智能感知在后台运行,只需要使用的MSBuild建立您的特定目标。这可能是由于执行的MSBuild /吨:GenerateToolOutput那样简单,VSIP可以提供一个内置的方式来定制调用编译目标。或者你可以简单地调用Build命令并等待它完成。

To force the generator to run synchronously rather than waiting for IntelliSense to run it in the background, just use MSBuild to build your particular target. This could be as simple as executing "MSBuild /t:GenerateToolOutput", or VSIP may provide a build-in way to call custom build targets. Alternatively you could simply invoke the Build command and wait for it to complete.

请注意,本节输入文件是指无论是在目标单元的输入属性中列出。

Note that "Input files" in this section refers to whatever is listed in the "Inputs" attribute of the Target element.

最后说明

您可能会从Visual Studio的警告,它不知道是否信任你的自定义工具.targets文件。为了解决这个问题,将其添加到HKEY_LOCAL_MACHINE \\ SOFTWARE \\微软\\ VisualStudio的\\ 9.0 \\的MSBuild \\ SafeImports注册表项。

You may get warnings from Visual Studio that it doesn't know whether to trust your custom tool .targets file. To fix this, add it to the HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\9.0\MSBuild\SafeImports registry key.

下面是一个什么样的实际.targets文件看起来像全部到位件摘要:

Here is a summary of what an actual .targets file would look like with all the pieces in place:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

  <PropertyGroup>
    <CoreCompileDependsOn>$(CoreCompileDependsOn);GenerateToolOutput</CoreCompileDependsOn>
  </PropertyGroup>

  <UsingTask TaskName="MyNamespace.GenerateCodeFromXyzFiles" AssemblyFile="MyTaskProject.dll" />


  <Target Name="GenerateToolOutput" Inputs="@(Xyz)" Outputs="@(Xyz->'$(IntermediateOutputPath)%(FileName)%(Extension).g.cs')">

    <GenerateCodeFromXyzFiles
        InputFiles="@(Xyz)"
        OutputFiles="@(Xyz->'$(IntermediateOutputPath)%(FileName)%(Extension).g.cs')">

      <Output TaskParameter="OutputFiles" ItemGroup="Compile" />

    </GenerateCodeFromXyzFiles>
  </Target>

</Project>

请让我知道如果您有任何问题或有什么在这里,你不明白。

Please let me know if you have any questions or there is anything here you didn't understand.

这篇关于如何通过隐藏在Visual Studio中自定义工具生成的文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆