C# csproj file "Choose" element for assembly HintPaths - c#

Is it possible to use the Choose/When/Otherwise elements on a reference hintpath?
Something like this:
<ItemGroup>
<Reference Include="SharedLib...">
<SpecificVersion>False</SpecificVersion>
<Choose>
<When Condition="Exists('..\..\SharedLib\bin\Debug')">
<HintPath>..\..\SharedLib\bin\Debug\SharedLib.dll</HintPath>
</When>
<Otherwise>
<HintPath>.\SharedLib.dll</HintPath>
</Otherwise>
</Choose>
</Reference>
</ItemGroup>
But I get errors like ...required attribute "Include" is empty or missing from element "ItemGroup"
Other attempts/version have yielded similar errors such as ...The "Choose" item metadata name is reserved and cannot be used.
This makes me think I canNOT use the "Choose" element INSIDE of an ItemGroup element.
I welcome clarification. See attached samples of the errors.
Visual Studio csproj Errors when loading project

I don't think you can put just the HintPath in the Choose. You have to put the entire ItemGroup within the When and Otherwise. Like this:
<Choose>
<When Condition="Exists('..\..\SharedLib\bin\Debug')">
<ItemGroup>
<Reference Include="SharedLib...">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\SharedLib\bin\Debug\SharedLib.dll</HintPath>
</Reference>
</ItemGroup>
</When>
<Otherwise>
<ItemGroup>
<Reference Include="SharedLib...">
<SpecificVersion>False</SpecificVersion>
<HintPath>.\SharedLib.dll</HintPath>
</Reference>
</ItemGroup>
</Otherwise>
</Choose>

Related

How can I specify exact output path for new .csproj file format? [duplicate]

This question already has answers here:
How do I set `OutputPath` in a Visual Studio 2017 project (new .csproj file format) without the target framework cluttering the resolved path?
(2 answers)
Closed 5 years ago.
I'm playing around with using the new .csproj file format.
I want my project to build to:
C:\Development\Source\DotNet\bin\x64\Debug\
But it seems to be implicitly adding to the path and building it at:
C:\Development\Source\DotNet\bin\x64\Debug\net46
Is there a way to prevent it from doing that?
My project is:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net46</TargetFramework>
<Platforms>x64</Platforms>
<ApplicationIcon />
<OutputType>Exe</OutputType>
<StartupObject />
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutputPath>C:\Development\Source\DotNet\bin\x64\Debug\</OutputPath>
</PropertyGroup>
<ItemGroup>
<Reference Include="AssetManagement_Gen">
<HintPath>..\..\Development\Source\DotNet\bin\x64\Debug\AssetManagement_Gen.dll</HintPath>
</Reference>
<Reference Include="EXPLink">
<HintPath>..\..\Development\Source\DotNet\bin\x64\Debug\EXPLink.dll</HintPath>
</Reference>
<Reference Include="IvaraCommon">
<HintPath>..\..\Development\Source\DotNet\bin\x64\Debug\IvaraCommon.dll</HintPath>
</Reference>
<Reference Include="NLog">
<HintPath>..\..\Development\Source\DotNet\bin\x64\Debug\NLog.dll</HintPath>
</Reference>
<Reference Include="System.Windows.Forms" />
</ItemGroup>
</Project>
If I open it in visual studio it also shows up with the "net46" appended to the output path.
For my posterity, the combination of <OutputPath> and <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath> lets you get a completely custom path.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net46</TargetFramework>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<Platforms>x64</Platforms>
<ApplicationIcon />
<OutputType>Exe</OutputType>
<StartupObject />
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutputPath>..\..\..\bin\$(Platform)\$(Configuration)</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutputPath>..\..\..\bin\$(Platform)\$(Configuration)</OutputPath>
</PropertyGroup>
<ItemGroup>
<Reference Include="AssetManagement_Gen">
<HintPath>$(OutDir)\AssetManagement_Gen.dll</HintPath>
</Reference>
<Reference Include="EXPLink">
<HintPath>$(OutDir)\EXPLink.dll</HintPath>
</Reference>
<Reference Include="IvaraCommon">
<HintPath>$(OutDir)\IvaraCommon.dll</HintPath>
</Reference>
<Reference Include="NLog">
<HintPath>$(OutDir)\NLog.dll</HintPath>
</Reference>
<Reference Include="System.Windows.Forms" />
</ItemGroup>
</Project>
I found the following post:
https://compiledexperience.com/blog/posts/multi-targeting-output-path
If you want to disable this automatic appending, for instance you’re only going to be using one target framework or you’re defining a different output path per framework then you can use AppendTargetFrameworkToOutputPath.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard1.4</TargetFramework>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
</PropertyGroup>
</Project>

Visual Studio does not display references from targets in Solution Explorer

Here is a part of my .csproj:
<Project DefaultTargets="Build" InitialTargets="MyTarget" xmlns="...">
<Target Name="MyTarget" DependsOnTargets="Include_Ver1;Include_Ver2"/>
<Target Name="Include_Ver1" Condition="...">
<ItemGroup>
<COMReference Include="Ref">
1st_Version
</COMReference>
</ItemGroup>
</Target>
<Target Name="Include_Ver2" Condition="...">
<ItemGroup>
<COMReference Include="Ref">
2nd_Version
</COMReference>
</ItemGroup>
</Target>
I can use library functions and project builds correctly, but reference does not appear in "References" block inside visual studio solution explorer. How can I force Intellisense parse references in Targets?
Try with different References and below hintpath ,specific version node elements.Make sure the *.csproj is not write only under any Version control system like SVN etc.
<ItemGroup>
<Reference Include="Microsoft.CSharp" />
<Reference Include="Microsoft.Owin, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Microsoft.Owin.dll</HintPath>
</Reference>
</ItemGroup>
VS doesn't display them because the solution explorer basically shows what it gets after parsing the project file. Parsing != executing, so the reference added in a target is not seen as it never executed - which makes sense, VS cannot guess if the target will even be executed or not and it cannot just start executing random builds to figure out if the reference will be added.
Do you really need a target? ItemGroups can have conditions too, maybe this is sufficient for you?
<ItemGroup Condition="...">
<COMReference Include="Ref">
1st_Version
</COMReference>
</ItemGroup>

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.

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