Why does Visual Studio respect 'OutputPath', but MSBuild doesn't? - msbuild

I have my filesystem as follows:
Solution Directory
-SolutionFile.sln
-Project One Directory
--ProjectOne.csproj
-Project Two Directory
--ProjectTwo.csproj
If I modify ProjectOne.csproj file to have the following, I get a 'binny' directory under my 'Project One' directory:
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'OCTOPUS|AnyCPU'">
<OutputPath>.\binny</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
When TeamCity runs my build, I don't get a 'binny' directory anywhere, and it looks like 'Project One' gets output to a 'bin' directory under the solution folder. I'm sure the property group condition is correct, if I change 'OCTOPUS|AnyCPU', I get an error.
Why is there no 'binny' directory, do I need to use some other property?

Related

How to stop generating wixpdb file in wix setup project?

Is there any configuration available to stop generation of wixpdb file.
Since we do not require that file during deployment.
Just add as per below in your .wixproj file.
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<OutputPath>bin\$(Configuration)\</OutputPath>
<IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
<-- Just Add below line to avoid generation of wixpdb file -->
<SuppressPdbOutput>true</SuppressPdbOutput>
</PropertyGroup>
See the SuppressPdbOutput setting in the light build task:
Optional boolean parameter.
Specifies that the linker should suppress outputting .wixpdb files. This is
equivalent to the -spdb switch in light.exe.
Right click Wix Project and go to Properties,
Build → Output → (Check) Suppress output of the wixpdb files

Wix on windows 10 with mvs2013 or mvs2014 is not working (making php executable)

Wix on windows 10 with mvs2013 or mvs2014 is not working.
I am getting the error:
Error The "GenerateCompileWithObjectPath" task could not be loaded from the assembly \WixTasks.dll. Could not load file or assembly 'file:///c:\WixTasks.dll' or one of its dependencies. The system cannot find the file specified. Confirm that the <UsingTask> declaration is correct, that the assembly and all its dependencies are available, and that the task contains a public class that implements Microsoft.Build.Framework.ITask. SetupProject5 C:\Program Files (x86)\MSBuild\Microsoft\WiX\v3.x\wix2010.targets
If i try to include WixTasks.dll to the project, when mvs2013 or mvs2014 crashes during the build. I include \WixTasks.dll to the C:\SourceControl\vs2015\SetupProject1\SetupProject1\SetupProject1.wixproj from the unpacked wix binaries folder:
C:\SourceControl
// C:\SourceControl\vs2015\SetupProject1\SetupProject1\SetupProject1.wixproj
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>3.10</ProductVersion>
<ProjectGuid>0adbe89f-e1ce-4345-90e6-64b8304fa42f</ProjectGuid>
<SchemaVersion>2.0</SchemaVersion>
<OutputName>SetupProject1</OutputName>
<OutputType>Package</OutputType>
<WixToolPath>C:\SourceControl</WixToolPath>
<WixTargetsPath>$(WixToolPath)\wix.targets</WixTargetsPath>
<WixTasksPath>$(WixToolPath)\WixTasks.dll</WixTasksPath>
<WixTargetsPath Condition=" '$(WixTargetsPath)' == '' AND '$(MSBuildExtensionsPath32)' != '' ">$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath>
<WixTargetsPath Condition=" '$(WixTargetsPath)' == '' ">$(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<OutputPath>bin\$(Configuration)\</OutputPath>
<IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
<DefineConstants>Debug</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<OutputPath>bin\$(Configuration)\</OutputPath>
<IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
</PropertyGroup>
<ItemGroup>
<Compile Include="Product.wxs" />
</ItemGroup>
<Import Project="$(WixTargetsPath)" />
<!--
To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Wix.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
I was reading different online forums and examples the last two days. Also Pact books on wix by Nick Ramirez. Nothing is working.
Define the following MSBuild variables and everything should work.
<WixRootPath Condition=" '$(WixRootPath)' == '' ">$(MSBuildThisFileDirectory)Tools\wix\$(WixTargetVersion)\</WixRootPath>
<WixToolPath Condition=" '$(WixToolPath)' == '' ">$(WixRootPath)</WixToolPath>
<WixTargetsPath Condition=" '$(WixTargetsPath)' == '' ">$(WixRootPath)Wix.targets</WixTargetsPath>
<WixCATargetsPath Condition=" '$(WixCATargetsPath)' == '' ">$(WixRootPath)sdk\Wix.CA.targets</WixCATargetsPath>
<WixTasksPath Condition=" '$(WixTasksPath)' == '' ">$(WixToolPath)WixTasks.dll</WixTasksPath>
<WixSdkPath Condition=" '$(WixSdkPath)' == '' ">$(WixRootPath)sdk\</WixSdkPath>
Just make sure the paths are right. These paths are for the wix 3.10.2 binaries which I checkout for my builds on the build machine.
I think the build tasks should be looking in the path defined by the WIX environment variable but I'm not 100% sure about that.
I think defining all the variables with the path you set should fix everything since the error mentions looking in C:\WixTasks.dll normally the path it looks for is something like $(WixInstallPath)WixTasks.dll but if $(WixInstallPath) isn't properly defined it will just be empty and default to C:\WixTasks.dll. You do define $(WixTasksPath) but I think it's getting overwritten for somereason...
Regardless, there's something wrong on your system right now but you can work around it this way probably.
EDIT: If the above doesn't work, download the wix binaries from here and extract them into a folder called "Wix" or whatever you want to call it. Then set your WixRootPath to be equal to that location.
I encountered this when using VS2015 and working on git branches that use different versions of Wix. (I'm upgrading to the latest Wix version but not all branches are there yet.)
You must terminate and restart VS if you switch between git branches that use different versions if Wix. VS holds some Wix files open, files that won't work under any other version of Wix. If you forget to do this your VS build will fail with the (quite cryptic) message of "The "GenerateCompileWithObjectPath" task could not be loaded from the assembly C:\Program Files (x86)\WiX Toolset v3.10\bin\WixTasks.dll"
The working solution from WiX Cookbook by Nick Ramirez, 2015, Chapter1 "Building a WiX installer from the command line", Example 4 "BuildMachineInstaller"
Download and unzip wix binaries file, for example from here.
1. Create some folder for your project, for example C:\SourceControl\own\box1 with file Product.wxs
2. Extract binaries to some folder, for example to C:\SourceControl\own\box1\tools\wix
3. start windows command line tool cmd and change to your project folder. Execute candle and light commands as folows:
C:\SourceControl\own\box1>C:\SourceControl\own\box1\tools\wix\candle *.wxs -o obj\
C:\SourceControl\own\box1>C:\SourceControl\own\box1\tools\wix\light obj\*.wixobj -o bin\CommandLineInstaller.msi
Anyway, if somebody could give some working example files and description how to make *.exe or *.msi with MSBuild or Visual Studio Build and wix, i would appreciate a lot. The other examples in Pact books are not working by pure copying, although are very useful for general understanding.
I've just come across this issue and found that at the top of the wix2010.targets file was the following property group.
<PropertyGroup>
<WixInstallPath Condition=" '$(WixInstallPath)' == ''">$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Installer XML\3.11#InstallRoot)</WixInstallPath>
<WixInstallPath Condition=" '$(WixInstallPath)' == ''">$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows Installer XML\3.11#InstallRoot)</WixInstallPath>
When checking the referenced registry path there was no entry for 3.11 but there was one there for 3.10. and the installed version was reported as 3.10. So updating the property group to the following corrected the issue for me.
<PropertyGroup>
<WixInstallPath Condition=" '$(WixInstallPath)' == ''">$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Installer XML\3.10#InstallRoot)</WixInstallPath>
<WixInstallPath Condition=" '$(WixInstallPath)' == ''">$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows Installer XML\3.10#InstallRoot)</WixInstallPath>
Hope this helps.
I solved the problem by following these instructions:
Download WIX311.exe from https://github.com/wixtoolset/wix3/releases/tag/wix3111rtm
Download Votive2017.vsix from https://marketplace.visualstudio.com/items?itemName=RobMensching.WixToolsetVisualStudio2017Extension
Remove any old WiX nuget packets from your solution/project
Follow these instructions (you can omit /quiet).
http://packagingstuffs.blogspot.com/2017/11/wix-toolset-311-silent-install-method.html
Content from the website above;
To Install:
Step1: Download the source from web and get the installer wix311.exe.
Step2: Run following command:wix311.exe /install /quiet /norestart
Step 3: Copy the Votive2017.vsix file (provided by vendor) to the local machine (e.g. %TEMP%)
Step 4: Run VSIXinstaller from its stored location
"%ProgramFiles(x86)%\Microsoft Visual Studio\2017\Professional\Common7\IDE\VSIXInstaller.exe" /quiet
Good luck and best regards

Conditionally build Post-Deploy in SSDT SQLPROJ

I want to conditionally build the post-deploy script in my SSDT project, but i don't understand how to do that. So normally the post-deploy script is built, but I want a way to NOT build or run the post-deploy script when doing a Debug build. I am running the build from the command-line, so i could pass in properties, but how could i use a property to not run the post-deploy script?
The options i see are SQLCMD, or editing the SQLPROJ file, or passing in properties, but I can't find any reference for what the available properties are and what not for SQLPROJ files.
The file i want to conditionally build is located here:
<ItemGroup>
<PostDeploy Include="PostDeploymentScripts\Script.PostDeployment1.sql" />
</ItemGroup>
My Debug build block looks like this:
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<OutputPath>bin\Debug\</OutputPath>
<BuildScriptName>$(MSBuildProjectName).sql</BuildScriptName>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<DefineDebug>true</DefineDebug>
<DefineTrace>true</DefineTrace>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
And my command-line looks like this:
msbuild $sqlprojFilePath /p:Configuration="Debug"
In your .sqlproj, add this line to occur after the import on Microsoft.Data.Tools.Schema.SqlTasks.targets
Find this line in your project file after the import on *SqlTasks.targets.
<Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(MSBuildToolsVersion)\SSDT\Microsoft.Data.Tools.Schema.SqlTasks.targets" />
<PropertyGroup Condition="'$(Configuration)'=='debug'">
<DeployDependsOn />
<SqlDeployDependsOn />
</PropertyGroup>
This removes the deployment projects from the dependency chain and can be modified to use an alternate property.
<PropertyGroup Condition="'$(SkipDeployment)'=='true'">
<DeployDependsOn />
<SqlDeployDependsOn />
</PropertyGroup>
Command line:
msbuild.exe mydb.sqlproj /p:SkipDeployment=true
Big Edit:
Or you can take this:
<ItemGroup>
<PostDeploy Include="PostDeploymentScripts\Script.PostDeployment1.sql" />
</ItemGroup>
and change it to read like so:
<ItemGroup Condition="'$(Configuration)'=='debug'">
<PostDeploy Include="PostDeploymentScripts\Script.PostDeployment1.sql" />
</ItemGroup>
You can do this with a SQLCMD variable. Set one up in the project and check the value of that variable when publishing the project. I blogged about something like this here:
http://schottsql.blogspot.com/2013/05/trick-to-not-run-prepost-sql-on-publish.html
Not sure about the msbuild command-line as I've normally used sqlpackage.exe to push the changes.

Azure Web Sites - publishing from on premises TFS ignores the publishing profile

I have successfully been able to publish to Windows Azure web sites by running MSBuild from the command line.
The command I execute is:
msbuild.exe /p:DeployOnBuild=true /p:PublishProfile=azure /p:Password=thepassword /p:PublishDir=\\filesvr\DropLocation\ /p:VisualStudioVersion=12.0
When I run this command from my local machine from the command line it pushes the deployment to a windows azure web site. I can also run the command from the command line of the build machine and it works correctly. In both cases I am running the command from the directory of the web site project.
However when I create a build (based on the default template) and add the parameters
/p:DeployOnBuild=true /p:PublishProfile=azure /p:Password=thepassword /p:PublishDir=\\filesvr\DropLocation\ /p:VisualStudioVersion=12.0
as MSBuild arguments of the TFS build, then the build completes successfully but does not publish to Azure. It does a standard web package and publish to the local file system. It does not seem to reference the publish profile at all.
The reason this was not working was related to some left over stuff in the csproj file namely:
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PublishDatabases>false</PublishDatabases>
<PackageAsSingleFile>true</PackageAsSingleFile>
<FilesToIncludeForPublish>OnlyFilesToRunTheApp</FilesToIncludeForPublish>
<DeployOnBuild>true</DeployOnBuild>
<DeployTarget>Package</DeployTarget>
</PropertyGroup>
should have been
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PublishDatabases>false</PublishDatabases>
</PropertyGroup>
The packaging information probably got added when right clicking on the project and choosing publish. I assume it was causing the build to not deploy correctly as it was giving separate instructions to msdeploy.
The reason the publish was working locally was that it was building for the debug configuration that did not have these settings.

Checking if a Property 'Starts/Ends With' in a csproj

I'm setting up some configurations in my csproj files that will target different framework versions. Ideally I want configurations of 'Debug - 3.5', 'Debug - 4.0', 'Release - 3.5' and 'Release - 4.0'.
In my csproj file I want to do something like the following:
<PropertyGroup Condition=" '${Configuration}' ends with '3.5' ">
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
</PropertyGroup
<PropertyGroup Condition=" '${Configuration}' ends with '4.0' ">
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
</PropertyGroup
... check for "starts with Debug" to define Optimize etc.
However, I don't know how to go about checking that ${Configuration} starts/ends with a particular string. Is there an easy way to do this?
Edit: Marked answer below for pointing me in the right direction, which lead me to go with:
<PropertyGroup Condition="$(Configuration.Contains('Debug'))">
... setup pdb, optimize etc.
</PropertyGroup>
<PropertyGroup Condition="$(Configuration.Contains('3.5'))">
... set target framework to 3.5
</PropertyGroup>
... and so on for Release and 4.0 variations
An MSBuild property is just a .NET String and has property functions available.
Condition="$(Configuration.EndsWith('3.5'))"
Should work