[英]How to hide files generated by custom tool in Visual Studio
我想隱藏我的自定義工具生成的文件,但我找不到任何關於如何完成此操作的文檔。
我正在尋找的一個例子是文件背后的WPF代碼。 這些文件不會顯示在Visual Studio項目視圖中,而是使用項目進行編譯,並在IntelliSense中可用。 文件后面的WPF代碼(例如,Window1.gics)由自定義工具生成。
解決方案是創建一個Target,將您的文件添加到Compile ItemGroup,而不是在.csproj文件中顯式添加它們。 這樣,Intellisense將會看到它們並將它們編譯到您的可執行文件中,但它們不會顯示在Visual Studio中。
簡單的例子
您還需要確保將目標添加到CoreCompileDependsOn
屬性,以便它在編譯器運行之前執行。
這是一個非常簡單的例子:
<PropertyGroup>
<CoreCompileDependsOn>$(CoreCompileDependsOn);AddToolOutput</CoreCompileDependsOn>
</PropertyGroup>
<Target Name="AddToolOutput">
<ItemGroup>
<Compile Include="HiddenFile.cs" />
</ItemGroup>
</Target>
如果將其添加到.csproj文件的底部(就在</Project>
之前),則“HiddenFile.cs”將包含在您的編譯中,即使它沒有出現在Visual Studio中。
使用單獨的.targets文件
您通常將它放在單獨的.targets文件中,而不是直接將其放在.csproj文件中,該文件包含在:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
...
</Project>
並使用<Import Project="MyTool.targets">
.csproj。 即使是一次性案例,也建議使用.targets文件,因為它將自定義代碼與Visual Studio維護的.csproj中的內容分開。
構造生成的文件名
如果要創建通用工具和/或使用單獨的.targets文件,則可能不希望顯式列出每個隱藏文件。 相反,您希望從項目中的其他設置生成隱藏文件名。 例如,如果您希望所有資源文件在“obj”目錄中具有相應的工具生成文件,那么您的目標將是:
<Target Name="AddToolOutput">
<ItemGroup>
<Compile Include="@(Resource->'$(IntermediateOutputPath)%(FileName)%(Extension).g.cs')" />
</ItemGroup>
</Target>
“IntermediateOutputPath”屬性是我們所知的“obj”目錄,但如果.targets的最終用戶已經自定義了這個,那么您的中間文件將在同一個地方找到。 如果您希望生成的文件位於主項目目錄中而不是“obj”目錄中,則可以將其保留為關閉狀態。
如果您只想要自定義工具處理現有項類型的某些文件? 例如,您可能希望為所有具有“.xyz”擴展名的頁面和資源文件生成文件。
<Target Name="AddToolOutput">
<ItemGroup>
<MyToolFiles Include="@(Page);@(Resource)" Condition="'%(Extension)'=='.xyz' />
<Compile Include="@(MyToolFiles->'$(IntermediateOutputPath)%(FileName)%(Extension).g.cs')"/>
</ItemGroup>
</Target>
請注意,您不能在頂級ItemGroup中使用%(擴展)等元數據語法,但您可以在Target中執行此操作。
使用自定義項類型(又名構建操作)
上面的處理文件具有現有的項目類型,如頁面,資源或編譯(Visual Studio將其稱為“構建操作”)。 如果您的商品是新類型的商品,則可以使用自己的自定義商品類型。 例如,如果您的輸入文件被稱為“Xyz”文件,則您的項目文件可以將“Xyz”定義為有效的項類型:
<ItemGroup>
<AvailableItemName Include="Xyz" />
</ItemGroup>
之后,Visual Studio將允許您在文件屬性的Build Action中選擇“Xyz”,從而將其添加到.csproj中:
<ItemGroup>
<Xyz Include="Something.xyz" />
</ItemGroup>
現在,您可以使用“Xyz”項類型為工具輸出創建文件名,就像之前使用“Resource”項類型一樣:
<Target Name="AddToolOutput">
<ItemGroup>
<Compile Include="@(Xyz->'$(IntermediateOutputPath)%(FileName)%(Extension).g.cs')" />
</ItemGroup>
</Target>
使用自定義項目類型時,您可以通過將項目映射到另一個項目類型(也稱為構建操作)來使您的項目也由內置機制處理。 如果您的“Xyz”文件確實是.cs文件或.xaml,或者如果需要它們,則此選項非常有用
EmbeddedResources。 例如,您可以編譯具有Xyz“Build Action”的所有文件:
<ItemGroup>
<Compile Include="@(Xyz)" />
</ItemGroup>
或者,如果您的“Xyz”源文件應存儲為嵌入式資源,您可以這樣表達:
<ItemGroup>
<EmbeddedResource Include="@(Xyz)" />
</ItemGroup>
請注意,如果將其放在Target中,則第二個示例將不起作用,因為直到核心編譯之前才對目標進行求值。 要在Target中進行此工作,您必須在PrepareForBuildDependsOn屬性中列出目標名稱而不是CoreCompileDependsOn。
從MSBuild調用自定義代碼生成器
除了創建.targets文件之外,您可以考慮直接從MSBuild調用工具,而不是使用單獨的預構建事件或Visual Studio有缺陷的“自定義工具”機制。
去做這個:
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<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元素和一個調用它的Target:
<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>
請注意,此目標的Output元素將輸出文件列表直接放入Compile中,因此無需使用單獨的ItemGroup來執行此操作。
舊的“自定義工具”機制是如何存在缺陷的,為什么不使用它
關於Visual Studio的“自定義工具”機制的注釋:在.NET Framework 1.x中,我們沒有MSBuild,因此我們不得不依賴Visual Studio來構建我們的項目。 為了在生成的代碼上獲取Intellisense,Visual Studio有一個名為“自定義工具”的機制,可以在文件的“屬性”窗口中進行設置。 該機制在幾個方面存在根本缺陷,這就是它被MSBuild目標取代的原因。 “自定義工具”功能的一些問題是:
如果您使用舊的“自定義工具”功能,我強烈建議您切換到使用MSBuild任務。 它可以很好地與Intellisense一起使用,並允許您在不安裝Visual Studio的情況下構建項目(您只需要.NET Framework)。
您的自定義構建任務何時運行?
通常,您的自定義構建任務將運行:
更確切地說:
您可能希望強制您的生成器在其他時間運行,例如某些環境變量更改時,或強制它在后台同步運行。
要使生成器重新運行,即使沒有輸入文件已更改,最好的方法通常是向目標添加一個額外的輸入,這是一個存儲在“obj”目錄中的虛擬輸入文件。 然后,每當環境變量或某些外部設置發生變化時,應該強制生成器工具重新運行,只需觸摸此文件(即創建它或更新其修改日期)。
要強制生成器同步運行而不是等待IntelliSense在后台運行它,只需使用MSBuild構建您的特定目標。 這可以像執行“MSBuild / t:GenerateToolOutput”一樣簡單,或者VSIP可以提供調用自定義構建目標的內置方式。 或者,您只需調用Build命令並等待它完成。
請注意,本節中的“輸入文件”是指Target元素的“Inputs”屬性中列出的內容。
最后的筆記
您可能會收到來自Visual Studio的警告,它不知道是否信任您的自定義工具.targets文件。 要解決此問題,請將其添加到HKEY_LOCAL_MACHINE \\ SOFTWARE \\ Microsoft \\ VisualStudio \\ 9.0 \\ MSBuild \\ SafeImports注冊表項。
以下是所有部分的實際.targets文件的概述:
<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>
如果您有任何問題或者您有任何不明白的地方,請告訴我。
要從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
<ItemGroup>
<Compile Include="$(AssemblyInfoPath)">
<!-- either: -->
<InProject>false</InProject>
<!-- or: -->
<Visible>false</Visible>
</Compile>
</ItemGroup>
我知道這樣做的唯一方法是在proj文件中添加生成的文件以依賴於您希望它隱藏在后面的文件。
例如:
<ItemGroup>
<Compile Include="test.cs" />
<Compile Include="test.g.i.cs">
<DependentUpon>test.cs</DependentUpon>
</Compile>
</ItemGroup>
如果您刪除了DependentUpon元素,那么該文件會顯示在另一個文件旁邊而不是它后面...您的生成器如何添加文件? 你能告訴我們用例以及你希望它如何工作嗎?
我想你想看看這里: http : //msdn.microsoft.com/en-us/library/ms171453.aspx 。
具體來說,“執行期間創建項目”部分。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.