Visual Studioの拡張性。 パート1:MSBuild

こんにちはHabr、これらの記事では、Microsoft Visual Studio拡張機能(および付随的にMSBuildも)のトピックをカバーしようとします。 この領域は非常に不十分に文書化されており、一般的に何らかの謎のベールで覆われています。







プロローグ



私はかなりの経験を持つプロのC ++開発者であり、Microsoft製品の大ファンであり、まず第一に、私の主な開発ツールであるVisual Studioです。 少し前まで、趣味として、マイクロコントローラーのプログラミングを開始し、マイクロチップ社のマイクロコントローラーを選びました。 私に合わなかった唯一のことは、マイクロチップ自体が提供する開発ツールの使用でした。 これらの製品について何も悪いことは言えません。作業中の(または自宅の)コンピューターにいくつかのIDEをインストールしたくないので、Microchip XC8コンパイラーをMicrosoft Visual Studioに統合するというアイデアが生まれました。 後で、このアイデアにもう1つのプラスを見ました-私の(私のだけではない)プロジェクトの多くは、それらをコンピュータに接続することに直接または間接的に接続されているので、応答ソフトウェア部分を開発する必要があります-それらを1つのソリューション(ソリューション)にファームウェアプロジェクトと組み合わせるのは素晴らしいことです。 長い時間をかけて掘り下げた後、私はVisual Studioに何かを統合するトピックは一種のホワイトスポットであることに気付きました。通常の説明はなく、ブログには乏しい説明があり、最悪なのは実際に例がないことです。 いくつかの情報を少しずつ収集し、説明から何かを理解し、科学的な突破の方法に基づいて、私は得た知識を共有することにしました。 行きましょう。



アクションプラン



さて、サードパーティのコンパイラをねじ込んでVisual Studioの機能を拡張することにしたので、可能な限り拡張しましょう。 これを行うには、やりたいことのリストを定義します。



  1. Visual Studioでプロジェクトのプロパティ(プロジェクトプロパティ)を表示する場合、独自のプロパティがあります。
  2. プロジェクトに含めることができるファイル拡張子のセットを定義します。
  3. コンパイラ、リンカなどが呼び出されるようにビルドシステムを決定するのは自然です。
  4. 独自のプロジェクトを作成して、スタジオが独自の拡張子を持つファイルを開くことができるようにします。
  5. このタイプのプロジェクトを生成するウィザードを作成します。




さて、このリストの要件の少なくとも一部を実装してみましょう。



パート1:MSBuild



理論から始めましょう:





上記を考慮して、スタジオの機能を拡張するには、まずMSBuildと呼ばれるアセンブリシステムデバイスを検討する必要があります。



すぐに予約します。かなり古いVIsual Studio 2010が手元にあったので、全体の説明は彼女のものになりますが、2012年と2013年以降はスタジオですべて同じになると思います。



だから、スタジオを開いて、 空のソリューションを作成し、 空のプロジェクトを追加します (C ++カテゴリのプロジェクトが好きなので、選択しました)





プロジェクトとソリューションの両方を「テスト」と呼び、それらを同じディレクトリに配置しました(これは実験に便利です。後で説明します)-したがって、ファイルtest.slnおよびtest.vcxprojを取得します



次に、スタジオを閉じて、何らかの種類のテキストエディターを使用し(XML構文の強調表示を使用した方がよい-原則として、同じスタジオが適切であり、他のインスタンスのみ)、テキストファイルとしてtest.vcxprojを開きます。



test.vcxprojの中身を見てみましょう:

test.vcxproj
<?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> <ProjectConfiguration Include="Debug|Win32"> <Configuration>Debug</Configuration> <Platform>Win32</Platform> </ProjectConfiguration> <ProjectConfiguration Include="Release|Win32"> <Configuration>Release</Configuration> <Platform>Win32</Platform> </ProjectConfiguration> </ItemGroup> <PropertyGroup Label="Globals"> <ProjectGuid>{E1064D79-B415-4EDC-9FAC-C50E4102268B}</ProjectGuid> <RootNamespace>test</RootNamespace> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> <ConfigurationType>Application</ConfigurationType> <UseDebugLibraries>true</UseDebugLibraries> <CharacterSet>MultiByte</CharacterSet> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <ConfigurationType>Application</ConfigurationType> <UseDebugLibraries>false</UseDebugLibraries> <WholeProgramOptimization>true</WholeProgramOptimization> <CharacterSet>MultiByte</CharacterSet> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <ImportGroup Label="ExtensionSettings"> </ImportGroup> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> </ImportGroup> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> </ImportGroup> <PropertyGroup Label="UserMacros" /> <PropertyGroup /> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ClCompile> <WarningLevel>Level3</WarningLevel> <Optimization>Disabled</Optimization> </ClCompile> <Link> <GenerateDebugInformation>true</GenerateDebugInformation> </Link> </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <ClCompile> <WarningLevel>Level3</WarningLevel> <Optimization>MaxSpeed</Optimization> <FunctionLevelLinking>true</FunctionLevelLinking> <IntrinsicFunctions>true</IntrinsicFunctions> </ClCompile> <Link> <GenerateDebugInformation>true</GenerateDebugInformation> <EnableCOMDATFolding>true</EnableCOMDATFolding> <OptimizeReferences>true</OptimizeReferences> </Link> </ItemDefinitionGroup> <ItemGroup> </ItemGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <ImportGroup Label="ExtensionTargets"> </ImportGroup> </Project>
      
      







ここで見るべき最も重要なこと:



その他はすべて安全に削除できます。 また、プロジェクトの仮想ディレクトリが邪魔にならないようにtest.filtersファイルを削除することをお勧めします。

 <?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> <ProjectConfiguration Include="Debug|Win32"> <Configuration>Debug</Configuration> <Platform>Win32</Platform> </ProjectConfiguration> <ProjectConfiguration Include="Release|Win32"> <Configuration>Release</Configuration> <Platform>Win32</Platform> </ProjectConfiguration> </ItemGroup> <PropertyGroup Label="Globals"> <ProjectGuid>{E1064D79-B415-4EDC-9FAC-C50E4102268B}</ProjectGuid> <RootNamespace>test</RootNamespace> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> </Project>
      
      





上記のファイルは、スタジオとMSBuildの観点からは絶対に有効であり、開いたり、組み立てることもできます。



また、コマンドラインからプロジェクトのアセンブリをすぐに処理することをお勧めします。

  1. Microsoft Visual Studioコマンドプロンプトを起動する
  2. test.vcxprojがあるディレクトリに移動します
  3. msbuild test.vcxproj / p:Configuration = Debug / p:Platform = Win32を実行します


このプロセスを自動化するスクリプトを作成して、エラーやその他のことをアセンブリで確認する方が便利です。



ここで、プロジェクトのプロパティの原因、および一般的に、プロジェクトをスタジオプロジェクトにする理由を理解し始めます。 そして、すべての行がこれを行います:

 <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
      
      





インポートしたファイルは、ディレクトリC:\ Program Files \ MSBuild \ Microsoft.Cpp \ v4.0にあります。



もちろん、それらを見てみることができますが、MSBuildを扱ったことのない人は何も理解できないと思います。これを理解したいという欲求はすぐに消えてしまいます。 だから私はまだそこを見ていないことをお勧めします、なぜなら (著者がしたように)多くの時間を費やしても、何も理解できません。



重要!!:vcxprojおよび関連ファイルを編集するたびに、スタジオを完全に再起動する必要があります! Visual Studioが何か(ほとんどの場合* .propsおよび* .targetsファイル)をキャッシュすることが実験的にわかったため、単純なプロジェクトのアンロード/プロジェクトのリロードだけでは不十分です! そのため、もともとvcxprojの横にslnファイルを作成したので、ディレクトリを変更せずに再起動すると便利です。



それでは、 Importタグのある行を削除して、何が起こるか見てみましょう。

ファイルは次のようになります。

test.vcxproj
 <?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> <ProjectConfiguration Include="Debug|Win32"> <Configuration>Debug</Configuration> <Platform>Win32</Platform> </ProjectConfiguration> <ProjectConfiguration Include="Release|Win32"> <Configuration>Release</Configuration> <Platform>Win32</Platform> </ProjectConfiguration> </ItemGroup> <PropertyGroup Label="Globals"> <ProjectGuid>{E1064D79-B415-4EDC-9FAC-C50E4102268B}</ProjectGuid> <RootNamespace>test</RootNamespace> </PropertyGroup> </Project>
      
      







スタジオで開くと、ファイルがまだ有効であることがわかります。 しかし、それを収集することは機能しません、私たちはメッセージを受け取ります:

1>エラー:「ConfigurationGeneral」ルールがプロジェクトにありません。

プロジェクトを収集する必要はありませんが、したがって、注意を払っていません。



プロジェクトのプロパティにあるものを見てみましょう-そして次の図を観察してください:



美人! 余分なものはすべて削除しました。むしろ、一般的なものはすべて削除しました。



プロジェクトにファイルを追加しようとしても成功しません。スタジオはエラーを返します。





叙情的な余談

読者は質問をするかもしれませんが、スタジオはどのようにしてこれがC ++プロジェクトであると判断しますか?Visual C ++を明示的に指すvcxproj拡張によって基本的です。 おそらく、この質問は読者にはかなり馬鹿げているように思われますが、実際にC ++プロジェクトではなくなったプロジェクトで長時間実験し、スタジオがまだC ++ルールに従って動作しようとすると、ファイル拡張子自体を完全に忘れてしまいます。 。 これは取り除きますが、このストーリーの以下の部分のいずれかでのみです。



プロジェクトは空です。 充填を始めましょう。



読者はおそらく、独自の* .propsおよび* .targetsファイルを作成することをすでに推測しているかもしれませんが、最初は少し理論があります。





ファイル* .targets。



さらにナレーションについては、抽象化から、XC8コンパイラをMicrochipからVisual Studioにねじ込むという特定のタスクに移行することをお勧めします。 XC8コンパイラは、 Microchip Webサイトからダウンロードしてインストールする必要があります。



余談 :一般的に、* .propsのような* .targetsファイルはMSBuild自体の特定のフォルダーにありますが、今はこれを行いません。 これは、新しく作成された拡張機能の配布タスク、および一般にインストーラーのタスクに既に適用されており、私たちの実験では、プロジェクトの隣の1つのディレクトリにすべてを保存することが最も便利です。



test.vcxprojの隣のディレクトリにXC8.targetsファイルを作成します。



XC8.targetsコンテンツ:

 <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <!-- Properties --> <ItemGroup> <PropertyPageSchema Include="XC8.Items.xml"/> </ItemGroup> </Project>
      
      







ファイルから、プロパティページ(PropertyPageSchema)のスキームを決定し、 XC8.Items.xmlファイルをインクルードしようとしていることがわかります。 読者が推測したように、 XC8.Items.xmlファイルでは、プロジェクトに参加するファイルの種類を説明します。 特にXC8コンパイラの場合、これらは* .cファイルです * .h; * .asmなど



プロジェクトのディレクトリにXC8.Items.xmlを配置して作成しましょう。

XC8.Items.xmlコンテンツ:

 <?xml version="1.0" encoding="utf-8"?> <ProjectSchemaDefinitions xmlns="http://schemas.microsoft.com/build/2009/properties"> <ContentType Name="CCode" DisplayName="C Code" ItemType="Compile"> </ContentType> <ContentType Name="AsmCode" DisplayName="Asm Code" ItemType="Compile"> </ContentType> <ContentType Name="Header" DisplayName="C/C++ Header" ItemType="Include"> </ContentType> <ContentType Name="Text" DisplayName="Text file" ItemType="None"> </ContentType> <ItemType Name="Compile" DisplayName="XC8 Compiler"/> <ItemType Name="Include" DisplayName="C header"/> <ItemType Name="None" DisplayName="Does not participate in build"/> <FileExtension Name=".c" ContentType="CCode"/> <FileExtension Name=".cc" ContentType="CCode"/> <FileExtension Name=".s" ContentType="AsmCode"/> <FileExtension Name=".asm" ContentType="AsmCode"/> <FileExtension Name=".h" ContentType="Header"/> <FileExtension Name=".txt" ContentType="Text"/> </ProjectSchemaDefinitions>
      
      





このファイルでわかるように、プロジェクトで必要なファイルの種類を決定しました。 そして、 FileExtensionタグを使用して、これらのファイルの拡張子決定しました。



最後にXC8.targetsをプロジェクトにインポートします。これには、 Importタグを使用します

test.vcxprojの内容:

 <?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> <ProjectConfiguration Include="Debug|Win32"> <Configuration>Debug</Configuration> <Platform>Win32</Platform> </ProjectConfiguration> <ProjectConfiguration Include="Release|Win32"> <Configuration>Release</Configuration> <Platform>Win32</Platform> </ProjectConfiguration> </ItemGroup> <PropertyGroup Label="Globals"> <ProjectGuid>{E1064D79-B415-4EDC-9FAC-C50E4102268B}</ProjectGuid> <RootNamespace>test</RootNamespace> </PropertyGroup> <Import Project="XC8.targets" /> </Project>
      
      







ここでスタジオを開き、最も単純なファイルmain.cを追加してみてください

ファイルの内容:

main.c
 #include <xc.h> int main() { return 0; }
      
      







出来上がり-これでファイルが追加されました。 ファイルのプロパティを見てみましょう:



[ アイテムタイプ]ドロップダウンリストに、 XC8.Items.xmlファイルで指定した要素が表示されていることがわかります。



重要!!:XC8.Items.xmlファイル全体のメインタグは、ItemType属性を持つContentTypeです 。 これは、今後メインタイプとして使用するItemType属性の値です。



test.vcxprojをスタジオに保存し、スタジオを閉じて、そのテキストを見てみましょう。

 <?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> <ProjectConfiguration Include="Debug|Win32"> <Configuration>Debug</Configuration> <Platform>Win32</Platform> </ProjectConfiguration> <ProjectConfiguration Include="Release|Win32"> <Configuration>Release</Configuration> <Platform>Win32</Platform> </ProjectConfiguration> </ItemGroup> <PropertyGroup Label="Globals"> <ProjectGuid>{E1064D79-B415-4EDC-9FAC-C50E4102268B}</ProjectGuid> <RootNamespace>test</RootNamespace> </PropertyGroup> <ItemGroup> <Compile Include="main.c" /> </ItemGroup> <Import Project="XC8.targets" /> </Project>
      
      





Compileタグである別のItemGroupタグを内部に追加したことがわかります。 このタグの名前は、 XC8.Items.xmlファイルのContentTypeタグのItemType属性の値として指定したものです。 親愛なる読者がすでに推測したように、このメカニズムを使用して、アセンブリ用の新しいファイルがプロジェクトに含まれています。



次に、プロジェクトのプロパティを扱いましょう。 これを行うには、 XC8.targetsに2つのファイルを含める必要があります。

 <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <!-- Properties --> <ItemGroup> <PropertyPageSchema Include="XC8.Items.xml"/> <PropertyPageSchema Include="XC8.General.xml"> <Context>Project</Context> </PropertyPageSchema> <PropertyPageSchema Include="XC8.General.PS.xml"> <Context>PropertySheet</Context> </PropertyPageSchema> </ItemGroup> </Project>
      
      





そして、いつものように、プロジェクトディレクトリにXC8.General.xmlおよびXC8.General.PS.xmlファイルを作成する必要があります。



すぐに予約します。なぜ2つ目のXC8.General.PS.xmlファイルが必要なのか、最後までわかりませんでした。 彼は私が勉強したすべての資料に出席していました。私たちのプロジェクトに従って命名して、彼を辞めることにしました。 この問題に関する情報がある場合は、共有してください。

内容:

XC8.General.PS.xml
 <?xml version="1.0" encoding="utf-8"?> <Rule Name="ConfigurationGeneral" DisplayName="General" PageTemplate="generic" Description="General" xmlns="http://schemas.microsoft.com/build/2009/properties"> <Rule.Categories> <Category Name="General" DisplayName="General" Description="General" /> </Rule.Categories> <Rule.DataSource> <DataSource Persistence="ProjectFile" Label="Configuration" /> </Rule.DataSource> </Rule>
      
      









ここで、 XC8.General.xmlファイルを参照して、プロジェクトのプロパティ、つまり[ 全般 ]プロパティページについて説明します。 思い出してください。プロジェクトをビルドするときにVisual Studioからリクエストされたのはこのページでした。 プロジェクトのプロパティページは、 Ruleタグによって記述されます。 苦労せずに、 XC8.General.xmlファイルを指定して、その構造を説明します。

 <?xml version="1.0" encoding="utf-8"?> <Rule Name="ConfigurationGeneral" DisplayName="General" PageTemplate="generic" Description="General" SwitchPrefix="-" xmlns="http://schemas.microsoft.com/build/2009/properties"> <Rule.Categories> <Category Name="General" DisplayName="General" Description="General" /> <Category Name="ProjectDefaults" DisplayName="Project Defaults" Description="Project Defaults" /> </Rule.Categories> <Rule.DataSource> <DataSource Persistence="ProjectFile" Label="Configuration" /> </Rule.DataSource> <!-- General --> <StringProperty Name="OutDir" DisplayName="Output Directory" Description="Specifies a relative path to the output file directory; can include environment variables." Category="General" Default="$(SolutionDir)$(Configuration)\" Subtype="folder" F1Keyword="VC.Project.VCConfiguration.OutputDirectory"> <StringProperty.DataSource> <DataSource Persistence="ProjectFile" Label="" /> </StringProperty.DataSource> </StringProperty> <StringProperty Name="IntDir" DisplayName="Intermediate Directory" Description="Specifies a relative path to the intermediate file directory; can include environment variables." Category="General" Default="$(Configuration)\" Subtype="folder" F1Keyword="VC.Project.VCConfiguration.IntermediateDirectory"> <StringProperty.DataSource> <DataSource Persistence="ProjectFile" Label="" /> </StringProperty.DataSource> </StringProperty> <StringProperty Name="TargetName" DisplayName="Target Name" Description="Specifies a file name that this project will generate." F1Keyword="VC.Project.VCConfiguration.TargetName" Category="General" Default="$(ProjectName)" > <StringProperty.DataSource> <DataSource Persistence="ProjectFile" Label="" /> </StringProperty.DataSource> </StringProperty> <StringListProperty Name="ExtensionsToDeleteOnClean" DisplayName="Extensions to Delete on Clean" Description="Semi-colon delimited wildcard specification for which files in the intermediate directory to delete on clean or rebuild." Category="General" Separator=";" F1Keyword="VC.Project.VCConfiguration.DeleteExtensionsOnClean"> <StringListProperty.DataSource> <DataSource Persistence="ProjectFile" Label="" /> </StringListProperty.DataSource> </StringListProperty> <StringProperty Name="BuildLogFile" DisplayName="Build Log File" Description="Specifies the build log file to write to when build logging is enabled." F1Keyword="VC.Project.VCConfiguration.BuildLogFile" Category="General" Default="$(ProjectDir)\$(MSBuildProjectName).log" Subtype="file"> <StringProperty.DataSource> <DataSource Persistence="ProjectFile" ItemType="BuildLog" PersistedName="Path" /> </StringProperty.DataSource> </StringProperty> <StringProperty Name="Chip" DisplayName="Select Processor" Description="This option selects the processor target for compilation. A list of available processors can be obtained by using the chipinfo option." Category="ProjectDefaults" Switch="-chip="/> <BoolProperty Name="QuietMode" DisplayName="Quiet Mode" Description="This option suppresses the Microchip copyright message, and any summary information usually printed by the compiler." Category="ProjectDefaults" Default="false" Switch="Q"/> <BoolProperty Name="VerboseMode" DisplayName="Verbose Mode" Description="This option is used to display the command lines used to invoke each of the compiler passes." Category="ProjectDefaults" Default="false" Switch="V"/> </Rule>
      
      





ファイルは非常に膨大ですが、私はまだスポイラーの下に入れたくありませんでした。 彼は重要です。



そのため、 Ruleタグにはいくつかの重要な属性があります。



Rule.Categoriesタグは、プロパティページ内のカテゴリを定義するために使用されます。 次の2つのカテゴリがあります。



必要に応じてこのようなカテゴリを定義できることは明らかです。



Rule.DataSourceタグは、プロパティ値が保存される場所を決定します。 ProjectFileを指定しました-つまり プロジェクトファイル内。 Persistence属性を変更しなかったのは、 このプロジェクト自体のファイル(この場合はtest.vcxproj)にない場合、プロジェクト設定をどこに保存できるか想像できません。



ご想像のとおり、プロパティの最後のタグは、プロジェクトのプロパティウィンドウに表示されるプロパティです。





プロパティの基本的な属性を考慮してください。





プロパティとルールには多くの属性があります-読者は、 Microsoft.Build.Framework.XamlTypes Namespaceリンクでそれらに精通することができます。 ただし、わかりやすい説明が見つからないように準備してください。このドキュメントは、説明なしで、何らかのジェネレーターによって自動的に作成されたようです。 良いニュースは、多くの属性の目的が名前から明らかであることです。



スタジオでプロジェクトを開き、プロジェクトのプロパティウィンドウを確認します



プロジェクトをビルドしようとすると、別のエラーが表示されます。 エラーMSB4057:ターゲットの「ビルド」はプロジェクトに存在しません。 は、 buildというTargetタグがないことを示しています。



これで、物語の最初の部分、私は終わり、特定の結果を達成しました。 次回は、 TargetTaskを作成し、デフォルト値とスタジオマクロを定義する方法を説明します。



プロジェクトファイルはここからダウンロードできます。



問題を研究することを可能にした資料:



MSDN: Microsoft.Build.Framework.XamlTypes名前空間

プロジェクト: vs-android

Habréに関する記事:MsBuild の最小プロジェクト

MSDN: チュートリアル。 MSBuildプロジェクトファイルをゼロから作成する

また、Cの科学的な突く方法:\ Program Files \ MSBuild \ Microsoft.Cpp \ v4.0 \ディレクトリ



All Articles