Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Old Format:

The pre visual studio 2017 format that was used by source before 2020 was maintained by ProjectChecker.exe on teamcity (and locally).

The core settings that were maintained were:

...

  • Core projects -> $(RootPath)Output
  • Core Plugin projects -> $(RootPath)Output\Plugins
  • Community Plugin projects -> $(RootPath)Output\Plugins\CommunityPlugins

...

  • Core projects -> $(RootPath)3rdParty
  • Plugins -> $(RootPath)Output;$(RootPath)3rdParty

...

Conversion process

The conversion process can be partially automated using a tool. The process to convert projects are as follows:

  1. Install the tool via dotnet cli:
    1. dotnet tool install -g Project2015To2017.Migrate2019.Tool\
  2. Then to run the conversion:
    1. dotnet migrate-2019 wizard old-output-path  C:\src\rm3\riversystem\Solutions\<solution>.sln
  3. Tidy up using regex:
    1.  <ReferencePath>$(RootPath)3rdParty</ReferencePath><AssemblySearchPaths>$(RootPath)3rdParty;$(AssemblySearchPaths);</AssemblySearchPaths>

  4. Make additional changes as outlined in the New Format section below.
  5. Remove duplicate entries which are often added by removing and collapsing the Release and Debug sections.
  6. Remove old junk which isn't needed anymore.

Table of Contents

Old Format

The pre visual studio 2017 format that was used by source before 2020 was maintained by ProjectChecker.exe on teamcity (and locally).

The core settings that were maintained were:

  • Target Framework - .Net 4.8
  • Tools Version - 15.0
  • LangVersion - C# 7.3, VB 15
  • General settings including WarningLevel 4, Suppress Warnings (1591, 1587), NoWarn, Prefer32Bit, Debug symbols, Optimize, etc.
  • RootPath - the root of our folder structure which all of our repository folders sit in; defined as a relative path from the project file location.
  • Import NormailsePdbBuildRoot targets
  • Output paths
    • Core projects -> $(RootPath)Output
    • Core Plugin projects -> $(RootPath)Output\Plugins
    • Community Plugin projects -> $(RootPath)Output\Plugins\CommunityPlugins
  • ReferencePath (output path isn't needed to be included as it's automatically used)
    • Core projects -> $(RootPath)3rdParty
    • Plugins -> $(RootPath)Output;$(RootPath)3rdParty
  • Project references
    • Convert dll references to project references if within same solution
    • Convert project references to dll references if within different solution (cannot use project references as the the build configuration to use is defined in the solution not the project i.e. debug will be used by default when building release)
    • Set copy local (private) to false
  • Dll references
    • Remove version and PublicKeyToken information
    • Remove HintPath
    • Set specific version to false
    • Set copy local (private) to false if part of .Net framework
    • Source solution
      • Set copy local (private) to true if not part of .Net framework
    • Plugins solution
      • Set copy local (private) to false if project from Source solution
      • Set copy local (private) to false if (directly) referenced by project from Source solution
      • Set copy local (private) to true for everything else (i.e. only referenced by a plugin)

Note: ProjectChecker.exe was only run on Source.sln and SourceCommunityPlugins.sln (i.e. doesn't get run on the Not to be distributed plugins).

Expand
titleOld csproj example
Code Block
languagexml
titleOld TIME.csproj
linenumberstrue
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build" ToolsVersion="15.0">
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
  <PropertyGroup>
    <ProjectGuid>{EEC5CF45-EBEE-4CEB-9335-A383C4749688}</ProjectGuid>
    <OutputType>Library</OutputType>
    <RootNamespace>TIME</RootNamespace>
    <AssemblyName>TIME</AssemblyName>
    <StartupObject />
    <TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
    <LangVersion>7.3</LangVersion>
    <NoWarn>1591,1587</NoWarn>
    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
    <WarningLevel>4</WarningLevel>
    <RootPath>$(MSBuildThisFileDirectory)..\..\</RootPath>
    <ReferencePath>$(RootPath)3rdParty</ReferencePath>
    <OutputPath>$(RootPath)Output</OutputPath>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <OutputPath>$(RootPath)Output</OutputPath>
    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
    <BaseAddress>285212672</BaseAddress>
    <CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <DebugSymbols>true</DebugSymbols>
    <FileAlignment>4096</FileAlignment>
    <NoWarn>1591,1587</NoWarn>
    <Optimize>false</Optimize>
    <RemoveIntegerChecks>false</RemoveIntegerChecks>
    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
    <WarningLevel>4</WarningLevel>
    <DebugType>portable</DebugType>
    <ErrorReport>prompt</ErrorReport>
    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <OutputPath>$(RootPath)Output</OutputPath>
    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
    <BaseAddress>285212672</BaseAddress>
    <CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
    <DefineConstants>TRACE</DefineConstants>
    <DebugSymbols>false</DebugSymbols>
    <FileAlignment>4096</FileAlignment>
    <NoWarn>1591,1587</NoWarn>
    <Optimize>true</Optimize>
    <RemoveIntegerChecks>false</RemoveIntegerChecks>
    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
    <WarningLevel>4</WarningLevel>
    <DebugType>portable</DebugType>
    <ErrorReport>prompt</ErrorReport>
    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="CsvHelper">
      <SpecificVersion>False</SpecificVersion>
      <Private>True</Private>
    </Reference>
    <Reference Include="gdal_csharp">
      <SpecificVersion>False</SpecificVersion>
      <Private>True</Private>
    </Reference>
    <Reference Include="LZ4">
      <SpecificVersion>False</SpecificVersion>
      <Private>True</Private>
    </Reference>
    <Reference Include="MathNet.Numerics">
      <SpecificVersion>False</SpecificVersion>
      <Private>True</Private>
    </Reference>
    <Reference Include="Microsoft.CSharp">
      <SpecificVersion>False</SpecificVersion>
      <Private>False</Private>
    </Reference>
    <Reference Include="Microsoft.Office.Interop.Excel">
      <EmbedInteropTypes>True</EmbedInteropTypes>
      <SpecificVersion>False</SpecificVersion>
      <Private>True</Private>
    </Reference>
    <Reference Include="Microsoft.Practices.EnterpriseLibrary.Common">
      <SpecificVersion>False</SpecificVersion>
      <Private>True</Private>
    </Reference>
    <Reference Include="Microsoft.Practices.EnterpriseLibrary.Validation">
      <SpecificVersion>False</SpecificVersion>
      <Private>True</Private>
    </Reference>
    <Reference Include="Newtonsoft.Json">
      <SpecificVersion>False</SpecificVersion>
      <Private>True</Private>
    </Reference>
    <Reference Include="ogr_csharp">
      <SpecificVersion>False</SpecificVersion>
      <Private>True</Private>
    </Reference>
    <Reference Include="PresentationCore">
      <SpecificVersion>False</SpecificVersion>
      <Private>False</Private>
    </Reference>
    <Reference Include="System">
      <SpecificVersion>False</SpecificVersion>
      <Private>False</Private>
    </Reference>
    <Reference Include="System.Core">
      <RequiredTargetFramework>3.5</RequiredTargetFramework>
      <SpecificVersion>False</SpecificVersion>
      <Private>False</Private>
    </Reference>
    <Reference Include="System.Data">
      <SpecificVersion>False</SpecificVersion>
      <Private>False</Private>
    </Reference>
    <Reference Include="System.Drawing">
      <SpecificVersion>False</SpecificVersion>
      <Private>False</Private>
    </Reference>
    <Reference Include="System.Reactive">
      <SpecificVersion>False</SpecificVersion>
      <Private>True</Private>
    </Reference>
    <Reference Include="System.Runtime.Serialization.Formatters.Soap">
      <SpecificVersion>False</SpecificVersion>
      <Private>False</Private>
    </Reference>
    <Reference Include="System.Xml">
      <SpecificVersion>False</SpecificVersion>
      <Private>False</Private>
    </Reference>
    <ProjectReference Include="..\TIME.NetCDF\TIME.NetCDF.csproj">
      <Project>{D3F02F27-C0B1-4ED9-86D3-AA1733270179}</Project>
      <Name>TIME.NetCDF</Name>
      <SpecificVersion>False</SpecificVersion>
      <Private>False</Private>
    </ProjectReference>
    <Reference Include="PresentationFramework">
      <SpecificVersion>False</SpecificVersion>
      <Private>False</Private>
    </Reference>
    <Reference Include="System.ComponentModel.DataAnnotations">
      <SpecificVersion>False</SpecificVersion>
      <Private>False</Private>
    </Reference>
    <Reference Include="System.IO.Compression">
      <SpecificVersion>False</SpecificVersion>
      <Private>False</Private>
    </Reference>
    <Reference Include="System.Windows.Forms">
      <SpecificVersion>False</SpecificVersion>
      <Private>False</Private>
    </Reference>
    <Reference Include="System.Xaml">
      <SpecificVersion>False</SpecificVersion>
      <Private>False</Private>
    </Reference>
    <Reference Include="WindowsBase">
      <SpecificVersion>False</SpecificVersion>
      <Private>False</Private>
    </Reference>
    <Reference Include="SciChart.Charting">
      <SpecificVersion>False</SpecificVersion>
      <Private>True</Private>
    </Reference>
  </ItemGroup>
  <ItemGroup>
    <Compile Include="BinarySerializer.cs" />
    <!-- Compiles removed for reability --> 
    <Compile Include="Properties\AssemblyInfo.cs" />
    <Compile Include="Properties\Resources.Designer.cs">
      <AutoGen>True</AutoGen>
      <DependentUpon>Resources.resx</DependentUpon>
      <DesignTime>True</DesignTime>
    </Compile>
    <Compile Include="DataTypes\IO\CsvFileIo\GeneralCsvFileIo.Load.cs" />
    <Compile Include="DataTypes\IO\CsvFileIo\TimeSeriesInfo\BigModTimeseriesInfo.cs" />
    <None Include="key.snk" />
    <None Include="Properties\Settings.settings">
      <Generator>SettingsSingleFileGenerator</Generator>
      <LastGenOutput>Settings.Designer.cs</LastGenOutput>
    </None>
    <Compile Include="Properties\Settings.Designer.cs">
      <AutoGen>True</AutoGen>
      <DependentUpon>Settings.settings</DependentUpon>
      <DesignTimeSharedInput>True</DesignTimeSharedInput>
    </Compile>
    <Compile Include="Science\Algebra\Algorithms.cs" />

    <Compile Include="Science\Mathematics\Functions\InterpolatedFunction.cs">
      <SubType>Code</SubType>
    </Compile>
    <Compile Include="Science\Mathematics\Functions\LinearPerPartFunction.cs" />
    <Compile Include="Science\VectorOperations\PolygonTools\Winding.cs" />
    <Compile Include="Science\VectorOperations\UnionGEORegions.cs" />
    <None Include="Science\Statistics\ClassDiagram.cd" />
    <RootContent Include="Resources\GDAL\coordinate_axis.csv" />
    <RootContent Include="Resources\GDAL\datum_shift.csv" />
    <RootContent Include="Resources\GDAL\ellipsoid.csv" />
    <RootContent Include="Resources\GDAL\gcs.csv" />
    <RootContent Include="Resources\GDAL\gcs.override.csv" />
    <RootContent Include="Resources\GDAL\gdal_datum.csv" />
    <RootContent Include="Resources\GDAL\gt_datum.csv" />
    <RootContent Include="Resources\GDAL\gt_ellips.csv" />
    <RootContent Include="Resources\GDAL\pcs.csv" />
    <RootContent Include="Resources\GDAL\pcs.override.csv" />
    <RootContent Include="Resources\GDAL\prime_meridian.csv" />
    <RootContent Include="Resources\GDAL\projop_wparm.csv" />
    <RootContent Include="Resources\GDAL\s57agencies.csv" />
    <RootContent Include="Resources\GDAL\s57attributes.csv" />
    <RootContent Include="Resources\GDAL\s57attributes_aml.csv" />
    <RootContent Include="Resources\GDAL\s57attributes_iw.csv" />
    <RootContent Include="Resources\GDAL\s57expectedinput.csv" />
    <RootContent Include="Resources\GDAL\s57objectclasses.csv" />
    <RootContent Include="Resources\GDAL\s57objectclasses_aml.csv" />
    <RootContent Include="Resources\GDAL\s57objectclasses_iw.csv" />
    <RootContent Include="Resources\GDAL\stateplane.csv" />
    <RootContent Include="Resources\GDAL\unit_of_measure.csv" />
  </ItemGroup>
  <ItemGroup>
    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
    <Service Include="{B4F97281-0DBD-4835-9ED8-7DFB966E87FF}" />
  </ItemGroup>
  <ItemGroup>
    <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
      <Visible>False</Visible>
      <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
      <Install>false</Install>
    </BootstrapperPackage>
    <BootstrapperPackage Include="Microsoft.Net.Framework.2.0">
      <Visible>False</Visible>
      <ProductName>.NET Framework 2.0 %28x86%29</ProductName>
      <Install>false</Install>
    </BootstrapperPackage>
    <BootstrapperPackage Include="Microsoft.Net.Framework.3.0">
      <Visible>False</Visible>
      <ProductName>.NET Framework 3.0 %28x86%29</ProductName>
      <Install>false</Install>
    </BootstrapperPackage>
    <BootstrapperPackage Include="Microsoft.Net.Framework.3.5">
      <Visible>False</Visible>
      <ProductName>.NET Framework 3.5</ProductName>
      <Install>false</Install>
    </BootstrapperPackage>
    <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
      <Visible>False</Visible>
      <ProductName>.NET Framework 3.5 SP1</ProductName>
      <Install>true</Install>
    </BootstrapperPackage>
    <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
      <Visible>False</Visible>
      <ProductName>Windows Installer 3.1</ProductName>
      <Install>true</Install>
    </BootstrapperPackage>
  </ItemGroup>
  <ItemGroup>
    <Folder Include="Resources\Toolkit\" />
  </ItemGroup>
  <ItemGroup>
    <EmbeddedResource Include="Resources\FinderBlackList.txt" />
  </ItemGroup>
  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
  <Import Project="$(RootPath)RiverSystem\Solutions\PostAndPreBuildScript.targets" />
  <Import Project="$(RootPath)RiverSystem\Solutions\IncludeGlobalAssembly.targets" />
  <Target Name="CopyRootContent" AfterTargets="AfterBuild">
    <Copy DestinationFolder="$(OutputPath)" SourceFiles="@(RootContent)" SkipUnchangedFiles="true" />
  </Target>
  <Import Project="$(RootPath)RiverSystem\Solutions\NormalisePdbBuildRoot.targets" />
</Project>


New Format

...

The new format released with Visual Studio 2019.

Main changes are:

...

  • All files within the project folder and child folders are included by default.

...

...

  • setting a resx file to have public accessibility rather then the default private)
  • Default "Debug" and "Release" build configurations no longer need to be defined. Only need to be specified if the settings differ to the defaults.
  • Project references now bring in implicit references of what it references (e.g. A →B and B → C, now A implicitly references C)
    • this includes everything C references as well (e.g. if C reference

...

    • WPF then A will reference

...

    • WPF)
  • Choose/When msbuild constructs don't seem to work the same
  • AssemblySearchPaths is used instead of ReferencePaths

Things to look for during dev review:

  • TargetFramework - net48
  • LangVersion - 7.3

...

  • RootPath - depends on csproj and sln location
  • AssemblySearchPaths - includes RootPath/3rdParty
  • OutputPath - RootPath/Output
  • AssemblyTitle - not needed if the same as the csproj file name (minus the extension), which is should be
  • <Import Project="$(RootPath)RiverSystem\Solutions\SDK.build.props" /> is set
  • <Import Project="$(RootPath)RiverSystem\Solutions\SDK.build.targets" /> is set
  • <Import Project="$(RootPath)RiverSystem\Solutions\SDKIncludeGlobalAssembly.targets" /> is set
  • <Import Project="$(RootPath)RiverSystem\Solutions\IncludeGlobalAssembly.targets" /> is

...

Notes:

  • removed
  • <Import Project="$(RootPath)RiverSystem\Solutions\NormalisePdbBuildRoot.targets" /> is set

...

  • private = false
  • specific version = false
  • <Import Project="$(RootPath)RiverSystem\Solutions\UnitTests.props" /> is set for projects containing unit tests
  • <Import Project="$(RootPath)RiverSystem\Solutions\

...

  • UnitTests.

...

  • targets" />

...

  • AppendTargetFrameworkToOutputPath, AppendRuntimeIdentifierToOutputPath and WarningsAsErrors are set by SDK.build.props
    • this is to stop the /win/x64 folders from being generated

...

  • to set the global assembly - no AssemblyInfo.cs is required anymore - these properties are set in the csproj file now

...

  • Copy 3rdParty to output is done via the SDK.build.targets
    • this is done since the Choose/When directives don't seem to work when running the builds via cake/msbuild (they work ok with visual studio 2017/2019)

...

  • to configure the normalization of pdb build paths

...

  • Change the SDK from "Microsoft.NET.Sdk" to "MSBuild.Sdk.Extras/3.0.38" (from https://www.nuget.org/packages/MSBuild.Sdk.Extras)
  • For WPF add <UseWPF>true</UseWPF> to the PropertyGroup
  • For WinForms add <UseWindowsForms>true</UseWindowsForms> to the PropertyGroup
  • Remove EmbeddedResource entreies for ".resx" files and the associated Compile of ".designer.resx" files
  • Remove Compile entries of ".cs" UserControl, Form and Component files and associated ".designer.cs" files
  • Remove Compile entries of ".xaml.cs" files and associated ".xaml" Page files

Add entries using wildcards for resources if they exist similar to the following:

Code Block
languagexml
  <ItemGroup>
    <EmbeddedResource Include="Persistence\Mappings\*.hbm.xml" />
    <EmbeddedResource Include="Persistence\SchemaUpgrades\*.sql" />
    <Resource Include="Resources\**\*">
      <Pack>True</Pack>
    </Resource>
  </ItemGroup>
  • Remove individual entries for resources

Example:

Expand
titleNew csproj example
Code Block
languagexml
linenumberstrue
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net48</TargetFramework>
    <LangVersion>7.3</LangVersion>
    <NoWarn>1591,1587</NoWarn>
    <RootPath>$(MSBuildThisFileDirectory)..\..\</RootPath>
    <AssemblySearchPaths>$(RootPath)3rdParty;$(AssemblySearchPaths);</AssemblySearchPaths>
    <OutputPath>$(RootPath)Output</OutputPath>
    <AssemblyTitle>TIME.RainfallRunoff</AssemblyTitle>
    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
    <RemoveIntegerChecks>false</RemoveIntegerChecks>
    <FileAlignment>4096</FileAlignment>
    <NoWarn>1591,1587</NoWarn>
    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
    <OutputPath>$(RootPath)Output</OutputPath>
    <BaseAddress>285212672</BaseAddress>
  </PropertyGroup>
  <Import Project="$(RootPath)RiverSystem\Solutions\SDK.build.props" />
  <Import Project="$(RootPath)RiverSystem\Solutions\SDKIncludeGlobalAssembly.targets" />
  <Import Project="$(RootPath)RiverSystem\Solutions\NormalisePdbBuildRoot.targets" />
  <ItemGroup>
    <Reference Include="Microsoft.Practices.EnterpriseLibrary.Validation">
      <Private>True</Private>
      <SpecificVersion>False</SpecificVersion>
    </Reference>
    <Reference Include="System.ComponentModel.DataAnnotations">
      <Private>False</Private>
      <SpecificVersion>False</SpecificVersion>
    </Reference>
  </ItemGroup>
  <ItemGroup>
    <ProjectReference Include="..\TIME\TIME.csproj" />
    <ProjectReference Include="..\TIME.Tools\TIME.Tools.csproj" />
  </ItemGroup>
  <ItemGroup>
    <None Include="AWRA\AWRA.cd" />
  </ItemGroup>
</Project>

Conversion process:

The conversion is made far easier using:

...

  1. dotnet tool install -g Project2015To2017.Migrate2019.Tool\

...

  1. dotnet migrate-2019 wizard old-output-path  C:\src\rm3\riversystem\Solutions\<solution>.sln

...

  1.  <ReferencePath>$(RootPath)3rdParty</ReferencePath><AssemblySearchPaths>$(RootPath)3rdParty;$(AssemblySearchPaths);</AssemblySearchPaths>

...

  • is set for projects containing unit tests
  • <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" /> is removed (will have been added in unit test projects by old versions of Visual Studio)
  • <Reference Include="nunit.framework"> is removed
  • All properties from the project imports are not set in the csproj file also, should only be set if overriding a setting from the import
  • References to projects within the same solution are set using ProjectReference entires e.g. <ProjectReference Include="..\TIME\TIME.csproj" />
  • Core framework dll references are set with
    • private = false
    • specific version = false
  • Other 3rd party dll references are set with (unless the project is a plugin project and the dll is referenced by a core Source project, see ProjectCheck replacement below)
    • private = false
    • specific version = false

Additional Notes:

  • <Import Project="$(RootPath)RiverSystem\Solutions\SDK.build.props" />
    • AppendTargetFrameworkToOutputPath, AppendRuntimeIdentifierToOutputPath and WarningsAsErrors are set by SDK.build.props
      • this is to stop the /win/x64 folders from being generated
  • <Import Project="$(RootPath)RiverSystem\Solutions\SDKIncludeGlobalAssembly.targets" />
    • to set the global assembly - no AssemblyInfo.cs is required anymore - these properties are set in the csproj file now
  • <Import Project="$(RootPath)RiverSystem\Solutions\SDK.build.targets" />
    • Copy 3rdParty to output is done via the SDK.build.targets
      • this is done since the Choose/When directives don't seem to work when running the builds via cake/msbuild (they work ok with visual studio 2017/2019)
  • <Import Project="$(RootPath)RiverSystem\Solutions\NormalisePdbBuildRoot.targets" />
    • to configure the normalization of pdb build paths
  • For unit test projects
    • Add <Import Project="$(RootPath)RiverSystem\Solutions\UnitTests.props" />
    • Add <Import Project="$(RootPath)RiverSystem\Solutions\UnitTests.targets" />
    • Remove <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
    • Remove <Reference Include="nunit.framework">
  • Compile Remove="file.cs" should be deleted and the "file.cs" should be deleted from the git repo as well.
  • For projects containing WPF or WinForms controls, or resources in resx files, make the the following changes:
    • Change the SDK from "Microsoft.NET.Sdk" to "MSBuild.Sdk.Extras/3.0.38" (from https://www.nuget.org/packages/MSBuild.Sdk.Extras)
    • For WPF add <UseWPF>true</UseWPF> to the PropertyGroup
    • For WinForms add <UseWindowsForms>true</UseWindowsForms> to the PropertyGroup
    • Remove EmbeddedResource entreies for ".resx" files and the associated Compile of ".designer.resx" files
    • Remove Compile entries of ".cs" UserControl, Form and Component files and associated ".designer.cs" files
    • Remove Compile entries of ".xaml.cs" files and associated ".xaml" Page files
  • Add entries using wildcards for resources if they exist similar to the following:

    Code Block
    languagexml
      <ItemGroup>
        <EmbeddedResource Include="Persistence\Mappings\*.hbm.xml" />
        <EmbeddedResource Include="Persistence\SchemaUpgrades\*.sql" />
        <Resource Include="Resources\**\*">
          <Pack>True</Pack>
        </Resource>
      </ItemGroup>


    • Remove individual entries for resources
  • An AssemblyInfo file won't be needed anymore but the GlobalAssemblyInfo.cs file will be included
    • Assembly attributes can be set inside the csproj file instead of in the AssemblyInfo.cs file, for example:

      Code Block
      languagexml
        <ItemGroup>
          <AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
            <_Parameter1>TIME.Tests</_Parameter1>
          </AssemblyAttribute>
        </ItemGroup>

Example:

Expand
titleNew csproj example
Code Block
languagexml
linenumberstrue
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net48</TargetFramework>
    <LangVersion>7.3</LangVersion>
    <RootPath>$(MSBuildThisFileDirectory)..\..\</RootPath>
    <AssemblySearchPaths>$(RootPath)3rdParty;$(AssemblySearchPaths);</AssemblySearchPaths>
    <OutputPath>$(RootPath)Output</OutputPath>
    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
    <RemoveIntegerChecks>false</RemoveIntegerChecks>
    <FileAlignment>4096</FileAlignment>
    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
    <BaseAddress>285212672</BaseAddress>
  </PropertyGroup>
  <Import Project="$(RootPath)RiverSystem\Solutions\SDK.build.props" />
  <Import Project="$(RootPath)RiverSystem\Solutions\SDK.build.targets" />
  <Import Project="$(RootPath)RiverSystem\Solutions\SDKIncludeGlobalAssembly.targets" />
  <Import Project="$(RootPath)RiverSystem\Solutions\NormalisePdbBuildRoot.targets" />
  <ItemGroup>
    <Reference Include="Microsoft.Practices.EnterpriseLibrary.Validation">
      <Private>True</Private>
      <SpecificVersion>False</SpecificVersion>
    </Reference>
    <Reference Include="System.ComponentModel.DataAnnotations">
      <Private>False</Private>
      <SpecificVersion>False</SpecificVersion>
    </Reference>
  </ItemGroup>
  <ItemGroup>
    <ProjectReference Include="..\TIME\TIME.csproj" />
    <ProjectReference Include="..\TIME.Tools\TIME.Tools.csproj" />
  </ItemGroup>
  <ItemGroup>
    <None Include="AWRA\AWRA.cd" />
  </ItemGroup>
</Project>

Gotchas

A few gotchas have been identified which should be checked for during conversion, and in day to day use of the SDK format:

  • Visual Studio will sometimes add entries to csproj files when it doesn't need to. When committing changes make sure any changes to csproj files are reviewed and that changes are added only if absolutely needed (actions differing from defaults)
  • Visual Studio may occasionally regenerate .designer.cs files used for resx resource files and WinForms controls. Often this will break the compile. If this happens then you should be able to revert the changes through Git and build again. Also note to remove the entries that may have been added to the csproj file when this happens.
  • Resources may not be found by WinForms controls if the namespaces used by the controls do not match the folder structure. This is because the new SDK will generate the resources using the folder structure instead of the namespace specified in the control's cs file. You should always have classes use namespaces which match the folder structure. To fix this issue right click the project in Visual Studio and use ReSharper to "Refactor → Adjust Namespaces". This may also require updating references to these controls in other projects (including plugins) which will generally be automatically done by ReSharper within the same solution.
  • When using wild cards for resources it may require the resources to be classified into different types of resources (embedded versus normal) and the files moves to different folders. As this will change the path also take care that any resx files and xaml files which reference these resources are updated accordingly.
  • When merging changes from a branch which doesn't use the new SDK format into a branch which does (e.g. release → beta → prep → master), changes to any csproj files may cause a conflict. Most regular changes (such as adding or deleting a file) should be discarded as they will no longer be needed.
  • When changing the branch you are on, builds may fail in Visual Studio or with Cake. Clean all "obj" folders and try and build again. Doing a "clean" of the solution in Visual Studio will not delete the obj folders. It is also recommended to not have Visual Studio open when changing branches as this has been known to cause issues.

ProjectChecker replacement

ProjectChecker has been modifed to skip SDK format projects. This means that incorrect settings are no longer going to be reported in the TeamCity ProjectChecker build. In particular this means that copy local setting errors will not be reported. ProjectChecker wasn't able to properly handle secondary / indirect references so the copy local settings didn't always work properly anyway. As a replacement there is a build task in the RiverSystem\Build\Scripts\SourceTargets.cake file, "__CleanDuplicatesFromPluginFolders". This task will delete files from the plugin output folders which are also in the base output folder. Any files deleted will be reported in the build log but there won't be a warning or error when this occurs. We could change this to report a build warning on TeamCity. Unneeded references can be checked by doing a local cake build (using PowerShell in the RiverSystem\Build\Scripts folder):


Code Block
languagepowershell
.\SourceTargets.ps1 --target=BuildSourceAndPlugins --configuration=Debug