Custom MSBuild project that can be "run" from Visual Studio - visual-studio

I created a custom MSBuild project that I can "build" from Visual Studio 2019, as described in https://stackoverflow.com/a/64917535/1536933. That is, I can select the Build menu item in VS and it runs my custom MSBuild task. Is there a way to do the same with "Run" - get VS to run my custom MSBuild task when I "Start" (or "Start without debugging") that project? I worked out that for the Build menu item to appear VS needs to see MSBuild targets named "Build" and "CoreCompile" - there is probably some equivalent for Start, but what?
The custom project file looks like this:
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>(some guid)</ProjectGuid>
<ProjectHome>.</ProjectHome>
<ProjectTypeGuids>{3AF33F2E-1136-4D97-BBB7-1795711AC8B8};{9092AA53-FB77-4645-B42D-1CCCA6BD08BD}</ProjectTypeGuids>
</PropertyGroup>
<!-- These property groups can be empty, but need to be defined for VS -->
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
</PropertyGroup>
<Import Project="My.Build.targets" />
<!-- Define empty standard MSBuild targets, since this project doesn't have them. Doing it this way allows My.Build.targets to also be used in a project that does define them. -->
<Target Name="Build" />
<Target Name="ReBuild" />
<Target Name="Clean" />
<!-- NOTE: a target named "CoreCompile" is needed for VS to display the Build menu item. -->
<Target Name="CoreCompile" />
<!-- Files shown in Visual Studio - adding and removing these in the UI works as expected -->
<ItemGroup>
<Content Include="myfile..." />
</ItemGroup>
</Project>
Note that it's not a C# project or C++ project or any other common type of project - VS treats its as a Node.js project due to the ProjectTypeGuids, but if I can get it working some other way, I'd be happy to.

Related

Visual Studio project with a custom build step only (no default build)

I want to create a Visual Studio project that would allow me to see a bunch of JavaScript and other files and edit them as normal, but would also have a build step that can run any custom commands I want (currently some npm commands, possibly more later). Basically I want 3 features combined:
Be able to browse and edit files just like for any VS project (C#, C++, etc.)
Be able to run a custom build step by selecting "Build" in Visual Studio (including building the whole solution).
Be able to run that same custom build step from the command line (MSBuild).
Using a "shared project" (.shproj) allows me to easily see and edit the files, but there is no Build item in the context menu, even if I manually add a Build target:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="Globals">
<ProjectGuid>...</ProjectGuid>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.Default.props" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.props" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.CSharp.targets" />
<Import Project="MyItems.projitems" Label="Shared" />
<PropertyGroup>
<Configuration>Debug</Configuration>
<Platform>Any CPU</Platform>
</PropertyGroup>
<Target Name="Build">
<Exec Command="ECHO My custom build!" />
</Target>
</Project>
I've also tried using a stripped-down VC++ project (since I don't actually want to run the C++ compiler) and this allows a build to be run from VS, but opening the project logs warnings like error MSB4057: The target "GetProjectDirectories" does not exist in the project. and trying to add files to fails with that error or similar ones.
There must be an easier way to do this!
From your current description, I think you want to create a js project in VS IDE.
However, VS IDE has the node js project template by default. And you should install the workload Node.js development under VS_Installer so that you can use it.
After that, you can create such project.
1) Adding js files or other files by right-click on the project-->Add-->Existing Item so that you can modify the files on VS IDE.
2) If you want to execute a custom build step that does not break the whole build, you should make the custom target depends on the default build.
You can use this:
<Target Name="CustomStep" AfterTargets="Build">
<Exec Command="ECHO My custom build!" />
</Target>
or
<Target Name="CustomStep" BeforeTargets="Build">
<Exec Command="ECHO My custom build!" />
</Target>
Note: If you use
<Target Name="Build">
<Exec Command="ECHO My custom build!" />
</Target>
It will overwrite the system build process and instead, run the command, which breaks the whole default build.
3) If you want to execute the custom build on msbuild command, you should specify the name of the custom target:
msbuild xxx\xxx.proj -t: CustomStep(the name of the custom target)
===============================================
Besides, if you still want to use C++ project template, you could create a empty c++ project which does not contain any clcompile files and then do the same steps.
If you do not want to use C++ compiler, you should only remove any xml node on the vcxproj file like these:
<ClCompile Include="xxx.cpp" />
<ClInclude Include="xxx.h" />
When you use the empty C++ project, you do not have to worry about that.
=========================================
Update 1
If you want to build this project on a build sever without VS IDE, I suggest you could install Build Tool for VS2019 which is an independent, lightweight build command line(It is equivalent to dotnet cli).
Build Tool for VS2019
Under All Downloads-->Tools for Visual Studio 2019--> Build Tools for Visual Studio 2019
Then, you have to install the related build workload such as Node.js Build tools and then we can use the command line to build node.js project on build sever.
The entire installation process is fast.
Inspired by Perry Qian-MSFT's answer, I managed to strip down a Node.js project to the bare minimum that I needed to get Visual Studio to load and build it, but without referencing any external files.
The main trick was VS needs a target named "CoreCompile" to be defined to show the Build menu item! (It also needs a "Build" target, but that one is more obvious.)
My project now looks like this:
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>(some guid)</ProjectGuid>
<ProjectHome>.</ProjectHome>
<ProjectTypeGuids>{3AF33F2E-1136-4D97-BBB7-1795711AC8B8};{9092AA53-FB77-4645-B42D-1CCCA6BD08BD}</ProjectTypeGuids>
</PropertyGroup>
<!-- These property groups can be empty, but need to be defined for VS -->
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
</PropertyGroup>
<Import Project="My.Build.targets" />
<!-- Define empty standard MSBuild targets, since this project doesn't have them. Doing it this way allows My.Build.targets to also be used in a project that does define them. -->
<Target Name="Build" />
<Target Name="ReBuild" />
<Target Name="Clean" />
<!-- NOTE: a target named "CoreCompile" is needed for VS to display the Build menu item. -->
<Target Name="CoreCompile" />
<!-- Files shown in Visual Studio - adding and removing these in the UI works as expected -->
<ItemGroup>
<Content Include="myfile..." />
</ItemGroup>
</Project>
And My.Build.targets looks like this:
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="MyBuild" AfterTargets="Build">(build steps)</Target>
<Target Name="MyReBuild" AfterTargets="ReBuild">(re-build steps)</Target>
<Target Name="MyClean" AfterTargets="Clean">(clean steps)</Target>
<!-- This target is needed just to suppress "warning NU1503: Skipping restore for project '...'. The project file may be invalid or missing targets
required for restore." -->
<Target Name="_IsProjectRestoreSupported" Returns="#(_ValidProjectsForRestore)">
<ItemGroup>
<_ValidProjectsForRestore Include="$(MSBuildProjectFullPath)" />
</ItemGroup>
</Target>
</Project>

How to set variables and properties that could be made configurable using the Project Properties' UI in Visual Studio, for a wix setup project?

I am working on WiX Setup V3 project in Visual Studio 2019. I have to make this working in Visual Studio as well as from MSBuild (in Jenkins). I have authored custom target file which will be included in this project. Following is the markup of the custom target file. I cannot use the HeatDirectory task, since it lacks some flags like svb6. Hence I am using Exec command for Heat execution.
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<DefineConstants>HeatFldrPath=$(FilePath);ProductVersion=$(PVersion);BuildNumber=$(BldNum)</DefineConstants>
<OutputName>$(MSIName)</OutputName>
<OutputPath>$(MSIPath)</OutputPath>
<SuppressPdbOutput>True</SuppressPdbOutput>
</PropertyGroup>
<PropertyGroup>
<WixBinPath>$(SolutionDir)\Build\wix\</WixBinPath>
<WixToolPath>$(WixBinPath)\</WixToolPath>
<WixTargetsPath>$(WixToolPath)Wix.targets</WixTargetsPath>
<WixTasksPath>$(WixToolPath)wixtasks.dll</WixTasksPath>
</PropertyGroup>
<ItemGroup>
<WixExtension Include="WixUtilExtension">
<HintPath>lib\WixUtilExtension.dll</HintPath>
<Name>WixUtilExtension</Name>
</WixExtension>
<WixExtension Include="WixUIExtension">
<HintPath>lib\WixUIExtension.dll</HintPath>
<Name>WixUIExtension</Name>
</WixExtension>
<WixExtension Include="WixMsmqExtension">
<HintPath>lib\WixMsmqExtension.dll</HintPath>
<Name>WixMsmqExtension</Name>
</WixExtension>
<WixExtension Include="WixIIsExtension">
<HintPath>lib\WixIIsExtension.dll</HintPath>
<Name>WixIIsExtension</Name>
</WixExtension>
</ItemGroup>
<Target Name="HeatTarget" BeforeTargets="Build">
<Exec Command='"$(WixToolPath)\heat.exe" dir $(HeatFldrPath) -cg UserFeatureFiles -dr APP_DIR -gg -g1 -sfrag -sw -svb6 -srd -sreg -ke -var var.HeatFldrPath -out "Content\UserFiles.wxs"' />
</Target>
</Project>
I need to make this configurable for the following parameters:
Product Version (for use in Candle command)
Build Number (This will be added to the Product Version)
Heat Directory Path
MSI Name (This will have Version along with Build Number concatenated
to it)
MSI Path (I don't want this to be bin\$(Configuration)\en-us, rather
a custom directory I specify)
My custom targets file will be imported to the .wixproj file and nothing else will be changed in the .wixproj file.
If I use DefineConstants in my custom targets file, it works with MSBuild, but not with Visual Studio. I am having a hard time passing these as parameters and getting my MSI to build from both Visual Studio and MSBuild. I tried passing $(FilePath), $(PVersion) and $(BldNum) from project properties, but no luck. I cannot hard code these values in .targets or .wixproj file, since they have to be run from both Visual Studio and MSBuild. Also, I am not able to pass OutputName and OutputPath from Visual Studio. Can anyone please help me?
PFB the wixproj file.
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build"
InitialTargets="EnsureWixToolsetInstalled"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == ''
">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>3.10</ProductVersion>
<ProjectGuid>{9ecbe76b-ecc4-4a17-bc8b-f2224421f616}</ProjectGuid>
<SchemaVersion>2.0</SchemaVersion>
<OutputName>My.Custom.MSI</OutputName>
<OutputType>Package</OutputType>
<PublishDir>..\HeatFolder</PublishDir>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' ==
'Debug|x86' ">
<OutputPath>bin\$(Configuration)\</OutputPath>
<IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
<DefineConstants>Debug;HeatFldrPath=$(PublishDir)</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' ==
'Release|x86' ">
<OutputPath>bin\$(Configuration)\</OutputPath>
<IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
<WixVariables>$(FilePath)=$(ProjectDir)HeatFolder;$(PVersion)="1.1.0.1"
</WixVariables>
<DefineConstants>HeatFldrPath=$(FilePath);ProductVersion=1.1.0.1;BuildNumber=$
(BldNum)</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Full-
Release|x86' ">
<OutputPath>bin\$(Configuration)\</OutputPath>
<IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
<DefineConstants>Release;HeatFldrPath=$(PublishDir)</DefineConstants>
</PropertyGroup>
<ItemGroup>
<Compile Include="Content\GlobalCustomActions.wxs" />
<Compile Include="Content\GlobalExitDlg.wxs" />
<Compile Include="Content\GlobalFatalError.wxs" />
<Compile Include="Content\GlobalInstallDlg.wxs" />
<Compile Include="Content\GlobalLicenseAgreementDlg.wxs" />
<Compile Include="Content\GlobalSetupFolderDlg.wxs" />
<Compile Include="Content\GlobalWelcomeDlg.wxs" />
<Compile Include="Content\GlobalWixUI.wxs" />
<Compile Include="Content\Product.wxs" />
<Compile Include="Content\UserFiles.wxs" />
<Compile Include="Content\UserIIS.wxs" />
<Compile Include="Content\UserRegistry.wxs" />
</ItemGroup>
<ItemGroup>
<Folder Include="conf\" />
<Folder Include="Content\" />
<Folder Include="Images\" />
<Folder Include="lib\" />
</ItemGroup>
<ItemGroup>
<Content Include="AppPoolAttrs.xml" />
<Content Include="AppPoolUpgradeChanges.xml" />
<Content Include="conf\default.yml" />
<Content Include="Content\CustomActions.CA.dll" />
<Content Include="Content\GlobalProperties.wxi" />
<Content Include="Content\License.en-us.rtf" />
<Content Include="CustomWix.targets" />
<Content Include="Images\Banner.bmp" />
<Content Include="Images\DEST.ICO" />
<Content Include="Images\dialog.bmp" />
<Content Include="Images\dialog_cust.bmp" />
<Content Include="Images\dialog_template.bmp" />
<Content Include="Images\Exclam.ico" />
<Content Include="Images\folder.ico" />
<Content Include="Images\folderNew.ico" />
<Content Include="Images\New.ico" />
<Content Include="Images\warn.ico" />
<Content Include="lib\WixIIsExtension.dll" />
<Content Include="lib\WixMsmqExtension.dll" />
<Content Include="lib\WixUIExtension.dll" />
<Content Include="lib\WixUtilExtension.dll" />
<Content Include="packages.config" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Content\en-us.wxl" />
</ItemGroup>
<Import Project="CustomWiX.Targets"
Condition="Exists('CustomWiX.targets')" />
<Import Project="$(WixTargetsPath)" Condition=" '$(WixTargetsPath)'
!= '' " />
<Import
Project="$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets"
Condition=" '$(WixTargetsPath)' == '' AND
Exists('$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets')
" />
<Target Name="EnsureWixToolsetInstalled" Condition="
'$(WixTargetsImported)' != 'true' ">
<Error Text="The WiX Toolset v3.11 (or newer) build tools must be
installed to build this project. To download the WiX Toolset, see
http://wixtoolset.org/releases/" />
</Target>
</Project>
I tried passing $(FilePath), $(PVersion) and $(BldNum) from project
properties, but no luck. I cannot hard code these values in .targets
or .wixproj file, since they have to be run from both Visual Studio
and MSBuild. Also, I am not able to pass OutputName and OutputPath
from Visual Studio.
The main issue is that when you set the variables in Project Properties UI, the values can only pass to the variables in the xxx.wixproj rather than CustomWiX.Targets file.
And this approach is local (modify only the properties of the xxx.wixproj file, which still be overridden by the custom target values).
In more detail, when it reloads the xxxx.wixproj which contains the custom target file, MSBuild will load the xml nodes line by line, since MSBuild properties support forward override values. Simply said, if the same value is defined later, the previous value is overwritten. And the same properties are defined in the custom target file which is imported under the those properties, so the properties in the custom targets file will always override the properties.
Besides, when you pass some variables in the project Properties UI, the values will overwrite the values in the xxx.wixprojrather than custom targets file. And then when you build again, the values in custom targets will still override the values you modified in project properties, so it won't work.
Differ from VS IDE, the msbuild command line can override the value with -p: XXX (property name)= XXXXXX, which is global, so this problem does not occur.
Suggestion
1) If you still want to modify those properties by overriding the value of the project properties, remove the same properties from the custom targets file and move them to wixproj so that they can be used directly.
2) Since the custom target file always overwrites the same properties, you can modify the specific properties directly in the custom target file without having to modify the wixproj file directly.
Update1
The wixvariables(Properties-->Build-->Define Variables) does not work in the xxxx.wixproj file but only for wix file like Product.wxsfile. If you define the property $(Filepath) in the Define Variables, it will never be used for MSBuild. So there is no way to set the properties in Property UI for msbuild Properties.
Besides, $ is used to call a property of MSBuild and MSBuild define a property only under PropertyGroup of xxx.xxxproj like <PropertyGroup><FilePath> xxx</FilePath><\PropertyGroup>.
Solution
You can customize your build by using Directory.Build.targets and remember keeping the name as the document said which is designed by that with the effect. Then you should put this file under the solution folder so that it can work for all the projects.xxx.props file will import on the top of the xxxx.xxproj, so it can not override the values and only the Directory.Build.targets which is imported at the bottom of the xx.xxproj file does.
Then you can define the variables in the file like:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<FilePath>xxxxx</FilePath>
</ProperGroup>
.........
</Project>
Hope it could help you.

Building SSAS 2016 from Visual Studio CLI

SSAS projects can't be built using MSBuild. However, SSAS projects can reportedly be built using Visual Studio or SSAS Helper (description).
Using the Visual Studio GUI (devenv.exe), the build of my SSAS 2016 Tabular project does indeed build fine:
Visual Studio also provides a CLI for non-interactive use: devenv.com . However, although my project builds fine using the GUI, it throws an error when trying to build using the CLI:
How do I build my SSAS 2016 Tabular projects using the CLI? Does devenv.com use another library for building than devenv.exe?
Background / more information / tries:
The SSAS Helper Sample CLI yields the same error.
The internet doesn't seem to know about this problem..
My smproj file looks as follows:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Development</Configuration>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{8CE414BB-95B2-4C99-9E03-51BA72086E22}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>MyRootNamespace</RootNamespace>
<AssemblyName>MyAssemblyName</AssemblyName>
<EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
<OutputPath>bin\</OutputPath>
<Name>ProjectName_Tabular</Name>
<DeploymentServerName>devserver</DeploymentServerName>
<DeploymentServerEdition>Developer</DeploymentServerEdition>
<DeploymentServerVersion>Version_11_0</DeploymentServerVersion>
<DeploymentServerDatabase>ProjectName_Tabular</DeploymentServerDatabase>
<DeploymentServerCubeName>Model</DeploymentServerCubeName>
<DeploymentOptionProcessing>Default</DeploymentOptionProcessing>
<DeploymentOptionTransactionalDeployment>False</DeploymentOptionTransactionalDeployment>
<DeploymentOptionDirectQueryMode>InMemory</DeploymentOptionDirectQueryMode>
<DeploymentOptionQueryImpersonation>Default</DeploymentOptionQueryImpersonation>
<SccProjectName>SAK</SccProjectName>
<SccProvider>SAK</SccProvider>
<SccAuxPath>SAK</SccAuxPath>
<SccLocalPath>SAK</SccLocalPath>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Development' ">
<OutputPath>bin\Development\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<OutputPath>bin\Release\</OutputPath>
<DeploymentServerEdition>Enterprise</DeploymentServerEdition>
<DeploymentOptionProcessing>Full</DeploymentOptionProcessing>
</PropertyGroup>
<ItemGroup>
<Compile Include="ProjectName_Tabular.bim">
<SubType>Code</SubType>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Compile>
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Business Intelligence Semantic Model\1.0\Microsoft.AnalysisServices.VSHostBuilder.targets" />
</Project>
With tabular, you can run msbuild. For example,
msbuild TabularProject8.smproj /verbosity:m /target:Rebuild /property:Configuration=Release

Accessing the runtime library property in visual studio 2010

This is basically a follow up question to:
Using Visual Studio project properties effectively for multiple projects and configurations
Our library's target name is currently in this format:
$(ProjectName)-$(PlatformToolset)-$(PlatformShortName)-$(Configuration)
We'd like to add information about the runtime library used by the project to the target name, I tried adding $(RuntimeLibrary), but that doesn't seem to be set. Is there any other way to get the runtime library at the time the target name is resolved?
Thanks,
John.
With this property sheet you can do this. Import it in your property sheet and you will be able to access the RuntimeLibrary this way: $(RuntimeLibrary)
Yes!!! This will work in your propertie sheet =^.~=
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<_IsDebug>$([System.Convert]::ToString($([System.Text.RegularExpressions.Regex]::IsMatch($(Configuration),'[Dd]ebug'))))</_IsDebug>
<_ItemDefinitionGroupRegex><![CDATA[<ItemDefinitionGroup Condition=".*']]>$(Configuration)\|$(Platform)<![CDATA['">((?:.*\n)*?.*)</ItemDefinitionGroup>]]></_ItemDefinitionGroupRegex>
<_RuntimeLibraryRegex><![CDATA[(?:.*\n)*?.*<RuntimeLibrary>(.*)</RuntimeLibrary>(?:.*\n)*?.*]]></_RuntimeLibraryRegex>
<_HasRuntimeLibrary>$([System.Text.RegularExpressions.Regex]::IsMatch($([System.Text.RegularExpressions.Regex]::Match($([System.IO.File]::ReadAllText($(ProjectPath))), $(_ItemDefinitionGroupRegex)).Result('$1')), $(_RuntimeLibraryRegex)))</_HasRuntimeLibrary>
<!--
Fix incremental build (Different results when running msbuild within Visual Studio or from console).
http://connect.microsoft.com/VisualStudio/feedback/details/677499/different-results-when-running-msbuild-within-visual-studio-or-from-console
-->
<DisableFastUpToDateCheck>true</DisableFastUpToDateCheck>
</PropertyGroup>
<Choose>
<When Condition="$([System.Convert]::ToBoolean($(_HasRuntimeLibrary)))">
<!-- Extract runtime library from project file. -->
<PropertyGroup Label="UserMacros">
<_RuntimeLibrary>$([System.Text.RegularExpressions.Regex]::Match($([System.Text.RegularExpressions.Regex]::Match($([System.IO.File]::ReadAllText($(ProjectPath))), $(_ItemDefinitionGroupRegex)).Result('$1')), $(_RuntimeLibraryRegex)).Result('$1'))</_RuntimeLibrary>
</PropertyGroup>
</When>
<Otherwise>
<!-- Set default runtime library -->
<PropertyGroup Label="UserMacros">
<_RuntimeLibrary Condition=" '$(_IsDebug)' == 'True' ">MultiThreadedDebugDLL</_RuntimeLibrary>
<_RuntimeLibrary Condition=" '$(_IsDebug)' == 'False' ">MultiThreadedDLL</_RuntimeLibrary>
</PropertyGroup>
</Otherwise>
</Choose>
<PropertyGroup Label="UserMacros">
<IsDebug>$(_IsDebug)</IsDebug>
<ConfigType Condition=" '$(IsDebug)' == 'True' ">Debug</ConfigType>
<ConfigType Condition=" '$(IsDebug)' == 'False' ">Release</ConfigType>
<Architecture Condition=" '$(Platform)' == 'Win32' ">x86</Architecture>
<Architecture Condition=" '$(Platform)' == 'x64' ">x64</Architecture>
<Toolset Condition=" '$(PlatformToolset)' == 'v110' ">msvc.110</Toolset>
<RuntimeLibrary>$(_RuntimeLibrary)</RuntimeLibrary>
</PropertyGroup>
<ItemGroup>
<BuildMacro Include="IsDebug">
<Value>$(IsDebug)</Value>
</BuildMacro>
<BuildMacro Include="Toolset">
<Value>$(Toolset)</Value>
</BuildMacro>
<BuildMacro Include="Architecture">
<Value>$(Architecture)</Value>
</BuildMacro>
<BuildMacro Include="RuntimeLibrary">
<Value>$(RuntimeLibrary)</Value>
</BuildMacro>
<BuildMacro Include="ConfigType">
<Value>$(ConfigType)</Value>
</BuildMacro>
</ItemGroup>
</Project>

MSBuild pre clean customization

I am working with Visual Studio 2010. I have directed project output to a specific folder which will contain all the DLLs and EXEs when built. However when I clean the solution, the folder is not getting cleaned, and the DLLs are still present in it.
Can anyone tell me how to handle the clean solution command to clear out the folders I want to clean? I tried working with MSBuild and handling the BeforeClean and AfterClean targets, but it did not provide the desired result.
The answer from Sergio should work but I think it could be cleaner to override the BeforeClean/AfterClean targets. These are hooks into the build/clean process provided by microsoft. When you do a clean, VS do call the targets : BeforeClean;Clean;AfterClean and by default the first and the last do nothing.
In one of your existing .csproj file you can add the following :
<Target Name="BeforeClean">
<!-- DO YOUR STUFF HERE -->
</Target>
You can add to your VS .sln file special target named let's say BuildCustomAction.csproj:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
</PropertyGroup>
<ItemGroup>
<CleanOutCatalogFiles Include="..\..\bin\$(Configuration)\**\*.dll">
<Visible>false</Visible>
</CleanOutCatalogFiles>
<CleanOutCatalogFiles Include="..\..\bin\$(Configuration)\**\*.exe">
<Visible>false</Visible>
</CleanOutCatalogFiles>
</ItemGroup>
<Target Name="Build">
</Target>
<Target Name="Rebuild"
DependsOnTargets="Clean;Build">
</Target>
<Target Name="Clean"
Condition="'#(CleanOutCatalogFiles)'!=''">
<Message Text="Cleaning Output Dlls and EXEs" Importance="high" />
<Delete Files="#(CleanOutCatalogFiles)" />
</Target>
</Project>
Place it everywhere you want and specify relative path to the output catalog for your binaries. Add in VS this project as existing. That's all. With this you can do own custom actions for three common actions in VS: Build, Rebuild, Clean.
There exists more complex way to customize build process using CustomBeforeMicrosoftCommonTargets and CustomAfterMicrosoftCommonTargets but it requires to be very good in MSBuild.
Hope this helps.

Resources