How to programmatically create a VC++ project with C#? - visual-studio

I want to to create a VC++ project with C#. I see this MSDN article about creating C# and VB console application projects. But how to do with VC++ project?
ADD 1
I had exactly the same issue as below thread. And its solution is to manipulate the raw XML, which is miserable... Is there some kind of API that I can work with?
How can an Empty Visual C++ project be created programmatically?
ADD 2
And besides creating a .vcxproj fie. I want to programmatically create a solution .sln file. Because my codebase are separated into many projects.

OK. I solved this problem by manipulating the *.sln and *.vcxproj files directly.
Details:
For *.vcxproj file, I created the following template:
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.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>
<ItemGroup>
__SM_C_FILES__
</ItemGroup>
<ItemGroup>
__SM_H_FILES__
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>__SM_PROJECT_GUID__</ProjectGuid>
<RootNamespace>__SM_PROJECT_ROOTNS__</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<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>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>__SM_ADDITIONAL_INCLUDE_DIRS_DEBUG__</AdditionalIncludeDirectories>
</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>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>__SM_ADDITIONAL_INCLUDE_DIRS_RELEASE__</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
The __SM_C_FILES__ contains sub-template like this:
<ClCompile Include="__SM_C_FILE__" />
The __SM_H_FILES__ contains sub-template like this:
<ClInclude Include="__SM_H_FILE__" />
For *.sln file, I created a template as below:
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.40629.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "__SM_PROJ_NAME__", "__SM_PROJ_FILE_PATH__", "__SM_PROJ_GUID__"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{__SM_PROJ_GUID__}.Debug|Win32.ActiveCfg = Debug|Win32
{__SM_PROJ_GUID__}.Debug|Win32.Build.0 = Debug|Win32
{__SM_PROJ_GUID__}.Release|Win32.ActiveCfg = Release|Win32
{__SM_PROJ_GUID__}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
Note the __SM_*__parts, I replace them with the project-specific content using the plain string replacement, which is pretty straight-forward.
And in the *.sln file, if you have multiple projects, you may need to generated multiple parts of the Project sections.
The {8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942} is a well-known GUID that represents the VC++ project type. A comprehensive list can be found here.
Thus, I avoided manipulating the XML.
Unlike this similar thread, I didn't create the *.vcxproj.filters file. Though it looks a bit ugly, but I can live with that for now.

Related

Msbuild : Error: The OutputPath property is not set for this project

I am currently trying to decouple a project and I am getting the following error
The OutputPath property is not set for project 'MyProj.vcxpro j'.
Please check to make sure that you have specified a valid combination
of Configuration and Platform for this project. Configuration=''
Platform='x64'. You may be seeing this message because you a re
trying to build a project without a solution file, and have specified
a non-default Configuration or Platform that doesn't exist for this
project. [D:\Test\MyProj.vcxproj]
I added this to my project but it is not helping
<PropertyGroup Label="Globals">
<Platform Condition="'$(Platform)' == ''">x64</Platform>
<TargetName>MyProj</TargetName>
<ResolveExportedSymbols>true</ResolveExportedSymbols>
<ProjectGuid>{xxxxx-xxxx-xxxx-xxx}</ProjectGuid>
<UsePrecompiledHeader>true</UsePrecompiledHeader>
<OutputPath>D:\MyOutput\out\</OutputPath>
</PropertyGroup>
Any suggestions ?
Please use this:
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform Condition="'$(Platform)' == ''">x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<TargetName>MyProj</TargetName>
<ResolveExportedSymbols>true</ResolveExportedSymbols>
<ProjectGuid>{xxxxx-xxxx-xxxx-xxx}</ProjectGuid>
<OutputPath>D:\MyOutput\out\</OutputPath>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
.....
</ClCompile>
</ItemDefinitionGroup>
.....
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>
Then, delete any output folder like Debug and then rebuild again.

xbuild compiles without errors but dont have .exe files?

Only For educational purposes.
Basically I am trying to compile Juicy Potato exploit. I found a visual studio project from github and Now I am trying to compile it using mono xbuild, Although it compiles without any errors but I can't find the binary or .exe files.
see below:
>>>> xbuild tool is deprecated and will be removed in future updates, use msbuild instead <<<<
XBuild Engine Version 14.0
Mono, Version 5.18.0.240
Copyright (C) 2005-2013 Various Mono authors
Build started 2019-10-10 3:30:02 PM.
__________________________________________________
/home/HTB/Json/10.10.10.158/nmap/juicy_potato/juicy-potato/JuicyPotato/JuicyPotato.sln: warning : Ignoring vcproj 'JuicyPotato'.
/home/HTB/Json/10.10.10.158/nmap/juicy_potato/juicy-potato/JuicyPotato/JuicyPotato.sln: warning : Failed to find project 4164003e-ba47-4a95-8586-d5aac399c050
/home/HTB/Json/10.10.10.158/nmap/juicy_potato/juicy-potato/JuicyPotato/JuicyPotato.sln: warning : Don't know how to handle GlobalSection ExtensibilityGlobals, Ignoring.
Project "/home/HTB/Json/10.10.10.158/nmap/juicy_potato/juicy-potato/JuicyPotato/JuicyPotato.sln" (default target(s)):
Target ValidateSolutionConfiguration:
Building solution configuration "Debug|x64".
Done building project "/home/HTB/Json/10.10.10.158/nmap/juicy_potato/juicy- potato/JuicyPotato/JuicyPotato.sln".
Build succeeded.
Warnings:
/home/HTB/Json/10.10.10.158/nmap/juicy_potato/juicy-potato/JuicyPotato/JuicyPotato.sln: warning : Ignoring vcproj 'JuicyPotato'.
/home/HTB/Json/10.10.10.158/nmap/juicy_potato/juicy-potato/JuicyPotato/JuicyPotato.sln: warning : Failed to find project 4164003e-ba47-4a95-8586-d5aac399c050
/home/HTB/Json/10.10.10.158/nmap/juicy_potato/juicy-potato/JuicyPotato/JuicyPotato.sln: warning : Don't know how to handle GlobalSection ExtensibilityGlobals, Ignoring.
3 Warning(s)
0 Error(s)
Time Elapsed 00:00:00.1375220
root#kali:/home/HTB/Json/10.10.10.158/nmap/juicy_potato/juicy-potato/JuicyPotato# ls
JuicyPotato JuicyPotato.sdf JuicyPotato.sln
root#kali:/home/HTB/Json/10.10.10.158/nmap/juicy_potato/juicy-potato/JuicyPotato# uname -a
Linux kali 4.19.0-kali3-amd64 #1 SMP Debian 4.19.20-1kali1 (2019-02-14) x86_64 GNU/Linux
my .vcxproj
<Project DefaultTargets="Build" ToolsVersion="15.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>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{4164003E-BA47-4A95-8586-D5AAC399C050}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>JuicyPotato</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
<ProjectName>JuicyPotato</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>```
Bottom:
```<PreprocessorDefinitions>NDEBUG;_WINDOWS;_USRDLL;MSFROTTENPOTATO_EXPORTS;_CRT_SECURE_NO_WARNINGS;% (PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>secur32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<BuildLog>
<Path>$(SolutionDir)$(Configuration)\$(Platform)\$(MSBuildProjectName).log</Path>
</BuildLog>
</ItemDefinitionGroup>
<ItemGroup>
<Text Include="ReadMe.txt" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="BlockingQueue.h" />
<ClInclude Include="IStorageTrigger.h" />
<ClInclude Include="LocalNegotiator.h" />
<ClInclude Include="MSFRottenPotato.h" />
<ClInclude Include="stdafx.h" />
<ClInclude Include="targetver.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllmain.cpp">
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</CompileAsManaged>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
</PrecompiledHeader>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</CompileAsManaged>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
</PrecompiledHeader>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</CompileAsManaged>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
</PrecompiledHeader>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</CompileAsManaged>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
</PrecompiledHeader>
</ClCompile>
<ClCompile Include="IStorageTrigger.cpp" />
<ClCompile Include="LocalNegotiator.cpp" />
<ClCompile Include="JuicyPotato.cpp" />
<ClCompile Include="stdafx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>```
Architecture:
Linux kali 4.19.0-kali3-amd64 #1 SMP Debian 4.19.20-1kali1 (2019-02-14) x86_64 GNU/Linux

Directory.Build.targets for project files without targets in Visual Studio

If my project file doesn't have any targets, and I have Directory.Build.targets file (with appropriate targets) in appropriate directory, Visual Studio cannot build project. Version of VS is 2019RC, but I don't think this is problem of particular version
Is that expected behavior, and why?
UPDATE - the full structure of the project. In general, this is modified project from "Data Connector Project" template of "Power Query SDK" - https://marketplace.visualstudio.com/items?itemName=Dakahn.PowerQuerySDK
The project name is PQExtensionTest. It has typical folder structure - PQExtensionTest solution directory, inside PQExtensionTest.sln file and PQExtensionTest project directory with PQExtensionTest.mroj and Directory.build.targets files.
PQExtensionTest.sln file:
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.28010.2046
MinimumVisualStudioVersion = 10.0.40219.1
Project("{4DF76451-A46A-4C0B-BE03-459FAAFA07E6}") = "PQExtensionTest", "PQExtensionTest\PQExtensionTest.mproj", "{6DEC2A2E-C380-4701-AA12-5052284223E4}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x86 = Debug|x86
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{6DEC2A2E-C380-4701-AA12-5052284223E4}.Debug|x86.ActiveCfg = Debug|x86
{6DEC2A2E-C380-4701-AA12-5052284223E4}.Debug|x86.Build.0 = Debug|x86
{6DEC2A2E-C380-4701-AA12-5052284223E4}.Release|x86.ActiveCfg = Release|x86
{6DEC2A2E-C380-4701-AA12-5052284223E4}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {50EB6857-946A-4D05-B65C-B99E4D39BEDD}
EndGlobalSection
EndGlobal
PQExtensionTest.mroj file:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectGuid>{6dec2a2e-c380-4701-aa12-5052284223e4}</ProjectGuid>
</PropertyGroup>
<ItemGroup>
<Compile Include="PQExtensionTest.pq">
<SubType>Code</SubType>
</Compile>
<Content Include="PQExtensionTest.query.pq">
<SubType>Code</SubType>
</Content>
</ItemGroup>
</Project>
Directory.Build.targets file:
<Project DefaultTargets="BuildExtension" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{a9cd1ca9-92e5-493d-8065-377910605c30}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>MyRootNamespace</RootNamespace>
<AssemblyName>MyAssemblyName</AssemblyName>
<EnableUnmanagedDebugging>False</EnableUnmanagedDebugging>
<AllowNativeQuery>False</AllowNativeQuery>
<AsAction>False</AsAction>
<FastCombine>False</FastCombine>
<ClearLog>False</ClearLog>
<ShowEngineTraces>False</ShowEngineTraces>
<ShowUserTraces>False</ShowUserTraces>
<LegacyRedirects>False</LegacyRedirects>
<SuppressRowErrors>False</SuppressRowErrors>
<SuppressCellErrors>False</SuppressCellErrors>
<MaxRows>1000</MaxRows>
<ExtensionProject>Yes</ExtensionProject>
<Name>PQExtensionTest</Name>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<DebugSymbols>false</DebugSymbols>
<!--Should be true, fix this when the debugger is implemented -->
<OutputPath>bin\Debug\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<DebugSymbols>false</DebugSymbols>
<OutputPath>bin\Release\</OutputPath>
</PropertyGroup>
<ItemGroup>
<Reference Include="mscorlib" />
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<UsingTask TaskName="BuildExtension" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v12.0.dll">
<ParameterGroup>
<InputDirectory ParameterType="System.String" Required="true" />
<OutputFile ParameterType="System.String" Required="true" />
</ParameterGroup>
<Task>
<Reference Include="System.IO.Compression" />
<Reference Include="System.IO.Compression.FileSystem" />
<Using Namespace="System.Globalization" />
<Using Namespace="System.IO.Compression " />
<Code Type="Fragment" Language="cs"><![CDATA[
using(FileStream fileStream = File.Create(OutputFile))
using(ZipArchive archiveOut = new ZipArchive(fileStream, ZipArchiveMode.Create, false))
{
foreach(string fullPath in Directory.EnumerateFiles(InputDirectory))
{
string filename = Path.GetFileName(fullPath);
archiveOut.CreateEntryFromFile(fullPath, filename, CompressionLevel.Optimal);
}
}
]]></Code>
</Task>
</UsingTask>
<Target Name="BuildExtension" DependsOnTargets="ExtensionClean">
<ItemGroup>
<PQFiles Include="#(Compile)" Condition="'%(Extension)' == '.pq'" />
</ItemGroup>
<ItemGroup>
<NonPQFiles Include="#(Compile)" Condition="'%(Extension)' != '.pq'" />
</ItemGroup>
<MakeDir Directories="$(IntermediateOutputPath)" />
<MakeDir Directories="$(OutputPath)" />
<Copy SourceFiles="#(NonPQFiles)" DestinationFolder="$(IntermediateOutputPath)" />
<Copy SourceFiles="#(PQFiles)" DestinationFiles="#(PQFiles->'$(IntermediateOutputPath)%(RecursiveDir)%(FileName).m')" />
<BuildExtension InputDirectory="$(IntermediateOutputPath)" OutputFile="$(OutputPath)\$(ProjectName).mez" />
</Target>
<Target Name="ExtensionClean">
<!-- Remove obj folder -->
<RemoveDir Directories="$(BaseIntermediateOutputPath)" />
<!-- Remove bin folder -->
<RemoveDir Directories="$(OutputPath)" />
<Message Text="MyM: $(aProperty)" />
</Target>
Is that expected behavior, and why?
It depends.
1. First, according to this doc,the Directory.Build.targets only works after the Microsoft.Common.props calls it.
So if you haven't imported the Microsoft.Common.props (or .targets) in a project file, the build will fail.
In this situation,it's a expected behavior that we can't build project with no targets in project file.
2. As you mentioned "I have Directory.Build.targets file (with appropriate targets)", please make sure you have <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> in your project file. Without it, the build can't work for your situation (with no custom targets in project file).
Make sure you've imported Microsoft.CSharp.targets in project file. And for your targets in Directory.Build.targets, add an attribute <Target BeforeTargets="..."> or <Target AfterTargets="..."> to make it work.
Example for my Directory.Build.targets:
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
...
</PropertyGroup>
<Target Name="Test" AfterTargets="build">
<Message Text="..."/>
</Target>
</Project>
Only when you've met these points can you build successfully in your situation.So please check it.
Update:
For a custom .proj file. We must have a target defined directly in .proj file or have a target imported with other targets files.
Since there is no targets in your proj file, and no targets in your Imported targets will be run, MSBuild will throw the error MSB4040 (There is no target in Project). Because if no target runs, then it doesn't make sense for the MSBuild process. This is the feature by design.
Update2
In a test.sln, I have a Directory.build.props in the solution directory:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="Today">
<Message Text="JustForTest"/>
</Target>
</Project>
And a quite simple .csproj file in project dir:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
</Project>
If I build the test.csproj, the build can succeed and run the Today Target to output "JustForTest". And if I comment out the Import Microsoft.Common.Props, the build will fail with MSB4040. Cause in .NET, the Directory.build.props can not be imported implicitly without the Microsoft.Common.Props.
Update3
I've checked the content of microsoft.common.props and microsoft.Csharp.targets.
In M.C.P file, there has definition and calls about Directory.build.props. While in M.C.T file, it defines the standard build process of C#. So I agree that there must be something in your project file which calls Directory.build.props, but that can't be microsoft.Csharp.targets or microsoft.VB.targets.

Passing properties to MSBUILD Task

I am trying to call msbuild task for all the project files with properties. I call the msbuild task four times with hardcoded configurations and platform combination. Something like
<MSBuild Projects="$(MSBuildProjectFile)" Targets="Build" Properties="Configuration=Debug;Platform=Win32" BuildInParallel="true"/>
<MSBuild Projects="$(MSBuildProjectFile)" Targets="Build" Properties="Configuration=Debug;Platform=x64" BuildInParallel="true"/>
<MSBuild Projects="$(MSBuildProjectFile)" Targets="Build" Properties="Configuration=Release;Platform=Win32" BuildInParallel="true"/>
<MSBuild Projects="$(MSBuildProjectFile)" Targets="Build" Properties="Configuration=Release;Platform=x64" BuildInParallel="true"/>
But I want to provide this property as ItemGroup something like this
Configuration=%(BUILD_CONFIG.Identity);Platform=%(BUILD_PLATFORM.Identity)
Code sample
MyProject.vcxproj
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="BuildAll" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="BuildAllConfiguration.vcxproj"/>
<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>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{E6B6F967-3BE3-428F-9288-3F838B8E726A}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>MyProject</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
...
Similar Configuration Details for release and Platforms x64
This project file includes BuildAllConfiguration.vcxproj
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<BUILD_PLATFORMS>Win32;x64</BUILD_PLATFORMS>
<BUILD_CONFIGURATION>Debug;Release</BUILD_CONFIGURATION>
</PropertyGroup>
<Target Name="BuildAll">
<ItemGroup>
<CONFIGURATION Include="$(BUILD_CONFIGURATION.Split(';'))"/>
<PLATFORM Include="$(BUILD_PLATFORMS.Split(';'))"/>
<ProjectToBuild Include="$(MSBuildProjectFile)">
<Properties>Configuration=%(CONFIGURATION.Identity);Platform=%(PLATFORM.Identity)</Properties>
<Targets>Build</Targets>
</ProjectToBuild>
</ItemGroup>
<Message Text="MSBUILD TASK input #(ProjectToBuild)"/>
<MSBuild Projects="#(ProjectToBuild)" />
</Target>
</Project>
This project will call MyProject.vcxproj with Target Build and Properties which is not getting wellformed. My expectation is that the properties goes as following
Properties=Configuration=Debug;Platform=Win32
Properties=Configuration=Release;Platform=Win32
Properties=Configuration=Debug;Platform=x64
Properties=Configuration=Release;Platform=x64
Instead the properties are passed as following
Properties=Configuration=Debug;Platform=
Properties=Configuration=Release;Platform=
Properties=Configuration=;Platform=Win32
Properties=Configuration=;Platform=x64
You need a cross-product here, if you search for that you should find plenty of answers, though I reckon if you don't know it's called that it might be hard to find. Something like this:
<Target Name="BuildAll">
<ItemGroup>
<CONFIGURATION Include="$(BUILD_CONFIGURATION.Split(';'))"/>
<PLATFORM Include="$(BUILD_PLATFORMS.Split(';'))"/>
<!-- cross product of both -->
<ConfigAndPlatform Include="#(CONFIGURATION)">
<Platform>%(PLATFORM.Identity)</Platform>
</ConfigAndPlatform>
<ProjectToBuild Include="$(MSBuildProjectFile)"/>
</ItemGroup>
<MSBuild Projects="#(ProjectToBuild)" Properties="Configuration=%(ConfigAndPlatform.Identity);Platform=%(ConfigAndPlatform.Platform)" />
</Target>
Some notes: capitals make things harder to read, maybe don't use them? Also if you put your configurations/platforms in an ItemGroup instead of a PropertyGroup you don't need extra splitting logic:
<ItemGroup>
<Configuration Include="Debug;Release"/>
<Platform Include="Win32;x64"/>
<ItemGroup>

VS not honoring PropertyGroup Configuration Settings

I'm trying to compact a XML project file. The project compiles a single source file but its over 11 KB in size because of a penchant for duplicating the same settings multiple times. I'm trying to move per-source-file settings and hoisting them up into Configuration PropertyGroup with different condition statements or expressions (what does XML call them?).
If I am parsing A guide to .vcxproj and .props file structure from MSDN Blogs correctly, we can place the settings iin the property group:
<PropertyGroup Label=“Configuration“ />
<!– This property sheet (directly or via imports) defines the
default values for many tool-specific properties such as the
compiler’s Optimization, WarningLevel properties, Midl tool’s
TypeLibraryName property, etc...
However, when I check my modifications by closing VS and then re-opening it with the modified project file, none of the settings are picked up. Visual Studio appears to be using its own settings.
I have a few questions:
Is there a Visual Studio setting to tell it to stop sraying every setting into every source file? There's no reason to duplicate a setting 175x4 times for each source file crossed into each configuration.
Does Visual Studio have a compaction utility so I don't have to do this by hand? Its very tedious work.
Why is Visual Studio not picking up the settings? How do I fix it?
Here's a screen capture of a property page which includes Preprocessor Macros. The modified XML has the following, which is not reflected in Visual Studio. I've tried with and without the ClCompile.
<!-- Debug Configurations -->
<PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Release Configuration">
<ClCompile>
<PreprocessorDefinitions>CRYPTOPP_DLL_ONLY;%(PreprocessorDefinitions)</PreprocessorDefinitions>
...
</ClCompile>
</PropertyGroup>
Here's the compacted project file. The original can be found here. The project compiles 1 source file, and its over 11KB in size un-compacted.
My mods start at <!-- All Configurations -->, and ends at <!-- Back to Visual Studio boilerplate -->. I have not finished hoisting all the settings, but the ones that have been done, like Preprocessor Macros and Runtime Library, are not reflected under Visual Studio.
<?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="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{1974a53a-9863-41c9-886d-b2b8c2fc3c8b}</ProjectGuid>
<RootNamespace>dlltest</RootNamespace>
<PlatformToolset>v100</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<!-- All Configurations -->
<PropertyGroup Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
<OutDir>$(Platform)\DLL_Output\$(Configuration)\</OutDir>
<IntDir>$(Platform)\$(ProjectName)\$(Configuration)\</IntDir>
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<CallingConvention>StdCall</CallingConvention>
<SuppressStartupBanner>true</SuppressStartupBanner>
</ClCompile>
</PropertyGroup>
<!-- Debug Configurations -->
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Debug Configuration">
<ClCompile>
<PreprocessorDefinitions>CRYPTOPP_DLL_ONLY;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Optimization>Disabled</Optimization>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<IntrinsicFunctions>true</IntrinsicFunctions>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
</PropertyGroup>
<!-- Release Configurations -->
<PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Release Configuration">
<ClCompile>
<PreprocessorDefinitions>NDEBUG;CRYPTOPP_DLL_ONLY;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<OmitFramePointers>true</OmitFramePointers>
<IntrinsicFunctions>true</IntrinsicFunctions>
<FunctionLevelLinking>true</FunctionLevelLinking>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
</PropertyGroup>
<!-- X86 Configurations -->
<PropertyGroup Condition="'$(Platform)'=='Win32'" Label="X86 Configuration">
<ClCompile>
<EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
</ClCompile>
</PropertyGroup>
<!-- X64 Configurations -->
<PropertyGroup Condition="'$(Platform)'=='x64'" Label="X64 Configuration">
<ClCompile>
<!-- <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet> -->
<EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
</ClCompile>
</PropertyGroup>
<!-- Back to Visual Studio boilerplate -->
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<StringPooling>true</StringPooling>
<PrecompiledHeader />
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Culture>0x0409</Culture>
</ResourceCompile>
<Link>
<AdditionalDependencies>cryptopp.lib;Ws2_32.lib</AdditionalDependencies>
<AdditionalLibraryDirectories>$(Platform)\DLL_Output\$(Configuration)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<StringPooling>true</StringPooling>
<PrecompiledHeader />
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Culture>0x0409</Culture>
</ResourceCompile>
<Link>
<AdditionalDependencies>cryptopp.lib;Ws2_32.lib</AdditionalDependencies>
<AdditionalLibraryDirectories>$(Platform)\DLL_Output\$(Configuration)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader />
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Culture>0x0409</Culture>
</ResourceCompile>
<Link>
<AdditionalDependencies>cryptopp.lib;Ws2_32.lib</AdditionalDependencies>
<AdditionalLibraryDirectories>$(Platform)\DLL_Output\$(Configuration)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader />
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Culture>0x0409</Culture>
</ResourceCompile>
<Link>
<AdditionalDependencies>cryptopp.lib;Ws2_32.lib</AdditionalDependencies>
<AdditionalLibraryDirectories>$(Platform)\DLL_Output\$(Configuration)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="dlltest.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
Your settings are overwritten because you put them too early in the file. Do as VS does, and put them after the <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />.
update my mistake; on second sight, your settings don't have any effect whatsoever since you are defining them as properties. Do as VS does, and define them in an ItemDefinitionGroup instead of a PropertyGroup (again, in the correct location as per msbuild evaluation rules)
As for the compacting: store your settings in seperate property sheets and import those. If organized wisely this will allow you to never have to edit the project file settings itself anymore (and hence the VS populated ItemDefinitionGroups will be empty), but you'll just add/remove property sheets as needed and the project file is just a container for source/header files and property sheets. If you do the importing in the VS gui (called 'Property Manager') they will automatically end up in the correct location mentioned before, and the order will also be ok. They can also be edited in VS via the same options dialog as for the project.
Note you can create whole hierarchies of property sheets importing others, which is useful to avoid repetition. E.g. instead of manually adding Ws2_32.lib to each config/platform combo you just import a property sheet which does just that. Especially handy for libraries which have different names depending on platform/configuration etc. And suppose you have created some standard property sheets seperate for compiler/linker/... you can add them to a 'master' one. Sample:

Resources