Change a project reference based on its configuration - c#

I have two solutions. One is a C# ASP.NET application Foo, the other is a class library Bar. In order for me to debug Bar in Foo, I need to add a reference to it which includes its symbols. All is well.
However, this reference breaks builds when uploading to TeamCity because it will look for a reference outside of the solution. So I need to make my project reference go from:
../../bar/bin/bar.dll
to
../packages/bar.0.2.3/lib/bar.dll
I am able to do this with MSBuild conditionals using the Choose tag.
<Choose>
<When Condition="$(Configuration) == 'Debug'">
<ItemGroup>
<Reference Include="Bar, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>../../bar/bin/bar.dll</HintPath>
<Private>True</Private>
</Reference>
</ItemGroup>
</When>
<Otherwise>
<ItemGroup>
<Reference Include="Bar, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>../packages/bar.0.2.3/lib/bar.dll</HintPath>
<Private>True</Private>
</Reference>
</ItemGroup>
</Otherwise>
</Choose>
This actually works beautifully. There is only one major problem: when I run an update command in Nuget, it will add a reference and overwrite my changes.
What is the easier way to do this? I'm open to any suggestions. Preferably, how can I modify a reference using a pre-build event? I just need to change one XML node based on a configuration.

Related

How to avoid addition of *.g.wxs file in my Wix Sharp setup project?

I have created a wix sharp setup project and it works well. msi is created as desired.
Unfortunately, wix (sharp?) creates a folder called 'wix' in the project and places an autogenerated file in it. I really don't like that. Is there a way to avoid this modification of my source files?
It's possible to remove file again in csproj by adding the 'remove' line. I should however prefer not to have it soiling my source code, so I'm still looking for a better solution!
<ItemGroup>
...
<None Include="wix\$(ProjectName).g.wxs" />
<None Remove="wix\$(ProjectName).g.wxs" />
</ItemGroup>
<Reference Include="WixSharp, Version=1.11.0.0, Culture=neutral, PublicKeyToken=3775edd25acc43c2, processorArchitecture=MSIL">
<HintPath>..\packages\WixSharp.bin.1.11.0\lib\WixSharp.dll</HintPath>
</Reference>
<Reference Include="WixSharp.Msi, Version=1.11.0.0, Culture=neutral, PublicKeyToken=3775edd25acc43c2, processorArchitecture=MSIL">
<HintPath>..\packages\WixSharp.bin.1.11.0\lib\WixSharp.Msi.dll</HintPath>
</Reference>
<Reference Include="WixSharp.UI, Version=1.11.0.0, Culture=neutral, PublicKeyToken=3775edd25acc43c2, processorArchitecture=MSIL">
<HintPath>..\packages\WixSharp.bin.1.11.0\lib\WixSharp.UI.dll</HintPath>
</Reference>
BR, Anders
The answer (for me) was to use nuget wixsharp.bin instead of wixsharp as per (primary wixsharp developer) Oleg Shilo's response here:
https://github.com/oleg-shilo/wixsharp/issues/661
Oleg wrote (in case the link is lost in the malmstroem of the internet):
oleg-shilo commented [2019-08-11]
Yes it is possible. Instead of WixSharp NuGet package use
WixSharp.bin. It will not modify the project. Though then building the
project will simply compile the builder console application
{ProjectName}.exe. And you will need to execute this app from your
project post-build event.
The rest is the same.

Use Project Reference in Debug and Nuget in Release

I would like to work in my project (A) and a dependent Nuget package (B) at the same time, without the need to release the nuget package on each change.
Is it possible to do a project-reference the Nuget project (B) from the Solution (A) when building Debug. And when building Release use the Nuget package from Source?
One way is to manually edit the csproj file.
If you have currently referenced the NuGet package, you will have a part in the csproj file like this:
....
<ItemGroup>
<Reference Include="log4net, Version=2.0.8.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
<HintPath>..\packages\log4net.2.0.8\lib\net45-full\log4net.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
....
In this example, log4net is used. For your NuGet package, the public key token, version and so on is different.
You can no change it to:
<ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<Reference Include="log4net">
<HintPath>Debug\log4net.dll</HintPath>
<Private>True</Private>
</Reference>
</ItemGroup>
<ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<Reference Include="log4net, Version=2.0.8.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
<HintPath>..\packages\log4net.2.0.8\lib\net45-full\log4net.dll</HintPath>
<Private>True</Private>
</Reference>
</ItemGroup>
The Condition attribute in the ItemGroup element is doing the job between debug and release.
Is it possible to do a project-reference the Nuget project (B) from the Solution (A) when building Debug. And when building Release use the Nuget package from Source?
Certainly, but there are some restrictions you need to know.
First, the ID of the NuGet package should different from the name of the reference project, otherwise, the reference from NuGet will replace the project reference.(For example, TestProjectReferenceForDebug is the name of the project reference, if you want to use project reference and NuGet package at the same time, you could not use this project to create the NuGet package directly, so I created a same project with different name to create the NuGet package "TestNuGetForRelease"):
Second, you should use Condition attribute in the ItemGroup element, otherwise, there is an ambiguous reference between 'TestProjectReferenceForDebug' and 'TestNuGetForRelease', so we need add the Condition attribute in the ItemGroup element
<ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
<Reference Include="TestNuGetForRelease, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL" >
<HintPath>..\packages\TestNuGetForRelease.1.0.0\lib\net462\TestNuGetForRelease.dll</HintPath>
<Private>True</Private>
</Reference>
</ItemGroup>
<ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
<ProjectReference Include="..\TestProjectReferenceForDebug\TestProjectReferenceForDebug.csproj">
<Project>{90424b17-2231-4d7d-997b-608115d9f4d9}</Project>
<Name>TestProjectReferenceForDebug</Name>
</ProjectReference>
</ItemGroup>
Third, after we add the Condition attribute in the ItemGroup element with debug and release, we could use project reference in Debug and Nuget in Release, however, if we use those namespace in one .cs file at same time, we need to add those two namespace, then you will get an error "The referenced component 'xxx' could not be found". That because VS could not find those two namespace only in the "Release" or "Debug" model:
To resolve this error, we have to annotate the namespace which in another configuration model when you change the configuration model from Debug to Release.

SlimDX and Multiple Architectures

I am trying to build a project that can be built in both x64 and x86. I am using SlimDX to be the interop to DirectSound. I cannot change this, as it is part of a bigger application.
I am trying to reference the x86 version of SlimDX when the project is set to build in Win32/x86, and to reference the x64 version of SlimDX when I am building in AnyCPU. Is this possible? I have tried using conditions in the csproj file, but that does not seem to be working.
<ItemGroup>
<Reference Include="SlimDX, Version=4.0.13.43, Culture=neutral, PublicKeyToken=b1b0c32fd1ffe4f9" Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\SlimDX\x86\SlimDX.dll</HintPath>
</Reference>
<Reference Include="SlimDX, Version=4.0.13.43, Culture=neutral, PublicKeyToken=b1b0c32fd1ffe4f9" Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\SlimDX\x64\SlimDX.dll</HintPath>
</Reference>
<ItemGroup>
This is possible, you can also add the platform target directly in the path:
<Reference Include="SlimDX">
<HintPath>..\SlimDX\$(Platform)\SlimDX.dll</HintPath>
</Reference>
Visual studio will send you some architecture mismatch warnings, but in your case they can be safely ignored (as you will boot in 64 bits at the end).

can't open vs2010 csproj file in vs2012

Goal:
doing xna with winforms.
Way
getting the code and how from their programmer, Microsoft from this link, which contains a solution with three projects in it, the form project, the Content and the ContentLibrary project.
Projects explanation:
The ContentLibrary project builds a dll which the form project references(but it doesn't seem to have anything and I don't know why).
It references the Content project in a bizzare way I have never seen.
The Content project contains a picture file, nothing else and I don't know what does it build.
Finally the form project which contains the main form which have many controls including user defined ones, one abstract which inherits xna control, and others to implement this control(these will do the drawing).
Problem:
could not open the ContentLibrary project.
the error message I get:
C:\Program Files(x86)\MSBuild\Microsoft\XNA Game Studio\Microsoft.Xna.GameStudio.targets was not found confirm that the path in the declaration is correct and that the file exists on disk
My Try:
opening the ContentLibrary project file(.csproj one) with notepad and here's what I found:
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectGuid>{396ADBE6-FB16-4DBA-8C70-C16A46B448EA}</ProjectGuid>
<ProjectTypeGuids>{6D335F3A-9D43-41b4-9D22-F6F17C4BE596};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} </ProjectTypeGuids>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>ContentLibrary</RootNamespace>
<AssemblyName>ContentLibrary</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkProfile>Client</TargetFrameworkProfile>
<XnaFrameworkVersion>v4.0</XnaFrameworkVersion>
<XnaPlatform>Windows</XnaPlatform>
<XnaProfile>Reach</XnaProfile>
<XnaCrossPlatformGroupID>e0c073d9-a61b-474a-bda0-a8ada2c89669</XnaCrossPlatformGroupID>
<XnaOutputType>Library</XnaOutputType>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\x86\Debug</OutputPath>
<DefineConstants>DEBUG;TRACE;WINDOWS</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<NoStdLib>true</NoStdLib>
<UseVSHostingProcess>false</UseVSHostingProcess>
<PlatformTarget>x86</PlatformTarget>
<XnaCompressContent>false</XnaCompressContent>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\x86\Release</OutputPath>
<DefineConstants>TRACE;WINDOWS</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<NoStdLib>true</NoStdLib>
<UseVSHostingProcess>false</UseVSHostingProcess>
<PlatformTarget>x86</PlatformTarget>
<XnaCompressContent>true</XnaCompressContent>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Xna.Framework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86">
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.Xna.Framework.Game, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86">
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.Xna.Framework.Graphics, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86">
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.Xna.Framework.GamerServices, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86">
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.Xna.Framework.Xact, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86">
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.Xna.Framework.Video, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86">
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.Xna.Framework.Avatar, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86">
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.Xna.Framework.Net, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86">
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.Xna.Framework.Storage, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86">
<Private>False</Private>
</Reference>
<Reference Include="mscorlib">
<Private>False</Private>
</Reference>
<Reference Include="System">
<Private>False</Private>
</Reference>
<Reference Include="System.Xml">
<Private>False</Private>
</Reference>
<Reference Include="System.Core">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
<Private>False</Private>
</Reference>
<Reference Include="System.Xml.Linq">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
<Private>False</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Content\Content.contentproj">
<Project>{618DED89-9BA8-44D7-83A0-163041666FAC}</Project>
<Name>Content</Name>
<XnaReferenceType>Content</XnaReferenceType>
</ProjectReference>
</ItemGroup>
<ItemGroup />
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath)\Microsoft\XNA Game Studio\Microsoft.Xna.GameStudio.targets" />
<!--
To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
Optional information:
in case needed, I'm running Windows 8 x64.
I found a solution here:
https://bitbucket.org/rbwhitaker/xna-beyond-vs-2010/downloads
The link given contains a script file which is launched by PowerShell(similar to command prompt). If you run Windows 7 or later you have PowerShell, if not use this link:
http://www.microsoft.com/en-us/download/details.aspx?id=40855
When you're ready follow these steps:
Open PowerShell.
Navigate to where you put the script by using cd command.
Run the following command: Set-ExecutionPolicy Unrestricted. This is because PowerShell doesn't activate script files by default to protect your computer, you can change it back when finished by typing: Set-ExecutionPolicy Restricted
Run the script using this command: .\XnaFor2013.ps1
Wait, it takes some time, on my computer it took about 15 minutes. It may take longer on slower computers. (I had windows 8 64 bit.)
If you want to know what this script does scroll down to the end of this page:
http://rbwhitaker.wikidot.com/setting-up-xna
Excerpt to prevent link rot:
First, it downloads the XNA installer from Microsoft.
It turns out that the XNA installer is just a self-extracting archive
that contains about seven other installers. So the next thing the
script does is unpack those "internal" installers.
Six of the seven do exactly what you want them to do, out of the box,
so the script runs them each in turn.
The other one is the installer that places files in the right place in
Visual Studio. Unfortunately, it's looking for Visual Studio 2010,
while you've got a newer version (2012 or 2013 both work with the
script). So the script tells this installer to just place the files in
a temporary location.
These files are built for Visual Studio 2010 and require some changes,
so the script makes the changes and places them in the appropriate
place for your version of Visual Studio. (In fact, it does it for all
versions of Visual Studio you've got installed, regardless of whether
it's 2012 or 2013, and regardless of if it's a paid version or Express
for Windows Desktop.)
Unfortunately, Visual Studio doesn't automatically check for new
add-ons. (Actually, that's a good thing because it would take too long
to check all the time, but in this case, it's bad because we need it
to check.) To make it check for new addons, the script deletes the
extension cache and has Visual Studio rebuild it. Rebuilding the cache
takes most of the time that the script runs for. (Several minutes.)
Once it's rebuilt, everything is ready to go, and the script deletes
the temporary files that it created.

Visual Studio Project: How to include a reference for one configuration only?

Env.: VS2008 C# project
I need to build my app for use in 2 different environments. In one of those environments, I need to use a 3rd party DLL assembly.
I could isolate the code that uses this DLL using #if blocks. But how do I conditionally include the reference to the DLL in the CS project file?
Edit: womp has a good point in his comment. I turned into a separate question: Will the referenced DLL be loaded at all if it's never called?
TIA,
Unload the project and open it as .XML
Locate the reference item tag and add a Condition attribute.
For instance:
<ItemGroup>
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data" />
<Reference Include="System.Drawing" />
<Reference Include="System.Xml" />
<Reference Include="MyUtilities.Debug"
Condition="'$(Configuration)'=='Debug'"/>
</ItemGroup>
Notice the last reference now has a condition.
I know this is an old post, but in case anyone else finds it before they find the answer, like I did, it's this: you need to use the "Choose" element in the project file:
link
You can define both conditional references and conditional compilation in one place, so you don't have to use #if's in your code.
It works in SharpDevelop, and since it's MS's documentation I assume it works in Visual Studio.
The following, in the csproj file references itemgroup works in vs 2008 for me:-
<Reference Include="DRLClasses, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL" Condition=" '$(Configuration)' == 'Debug' ">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\Visual Studio User Library\Debug\DRLClasses.dll</HintPath>
</Reference>
<Reference Include="DRLClasses, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL" Condition=" '$(Configuration)' == 'Release' ">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\Visual Studio User Library\Release\DRLClasses.dll</HintPath>
</Reference>
Inspired by the question and answer shown here, you can add <Choose> and <When Condition> commands around the part you want to be conditionally run. For example:
<Choose>
<When Condition="$(USEDLL) == true">
<ItemGroup>
<EmbeddedResource Include="test.dll">
<LogicalName>test.dll</LogicalName>
</EmbeddedResource>
</ItemGroup>
</When>
</Choose>
Then in the CLI, simply use the /p property in MSBuild like this:
MSBuild "C:\myproject\myproject.sln" /p:USEDLL=true
...or if you don't want the DLL, simply:
MSBuild "C:\myproject\myproject.sln" /p:USEDLL=false

Categories