---
description: New csproj template and solution files for easier customization
---

# Custom Project Rework \[v16+]

WIP article - Clemens Husung - updated: 2024-04-02\
On any questions or feedback, feel free to contact me via mail, Teams or Mattermost.

{% hint style="info" %}
This rework was made for v16 and will apply to all **new** created projects and solutions.\
Existing v16 projects or migrated ones from v15 will not be automatically changed to the new template.
{% endhint %}

## General Info

Why was this change made? Before this change, custom projects had to reference standard DLLs by its absolute path to the install directory. Whenever the runtime was changed, or a project manager with another path was working on it, all csproj files would be changed and updated. This lead to conflicts and confusion.\
In addition, relevant references for projects weren't correctly copied to the custom path by default.

## New Features

* Global `global.props` and `global.targets` files in solution that centralize properties and build actions.\
  Will automatically be updated by Developer if anything changes.
* `user.props` file that stores user-specific settings, like the runtime environment.
* `.gitignore` file created for each customized solution with all needed includes/excludes.
* E3RootPath will be saved inside user.props, and project files will utilize that variable for referencing standard DLLs instead of absolute paths.
* Solution/Project build will now correctly copy over **all** relevant output files to the solution root. No issues with missing Nuget references anymore.\
  It will automatically exclude E3 standard DLLs, so they don't get copied into the custom path.
* "Clean" on solution will now correctly remove all files that were deployed to the root folder as well.\
  (thanks to a hidden ".deployMarkers" folder)
* Optional loading of custom-made `*.pre.props`, `*.post.props`, `*.pre.targets` and `*.post.targets` for solution-specific overriding or custom build tasks, checks etc.

## Solution Files

### user.props for user-specific environment settings

The `user.props` file will be automatically handled and updated by Developer. It should **not** be changed manually, as it will get overwritten.

The file is automatically excluded from version control via the `.gitignore` and should never be checked in. It contains both user-specific settings that don't apply to others and also sensitive data, like the hashed password.

The `user.props` file looks like this:

{% code title="user.props" lineNumbers="true" %}
```xml
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <ServerAddress>localhost</ServerAddress>
    <ServerPort>50560</ServerPort>
    <ServerMandant>Testing 16.0</ServerMandant>
    <Username>dba</Username>
    <Password>xxxxxxxxxxxxxxxxxxxx</Password>
    <E3RuntimeName>Prototype TargetDeploy</E3RuntimeName>
    <E3RootPath>C:\TFS\Prototype\TargetDeploy\TimeLine Enterprise</E3RootPath>
  </PropertyGroup>
</Project>
```
{% endcode %}

### global.props for solution-wide setup

TODO

### global.targets for solution-wide script on build

TODO

## Advanced features

### Override variables and change behavior for specific solutions

TODO

### Utilizing The variables in custom build targets

TODO

## Migration of already existing solutions

All new projects and solutions made with Developer v16 since kit 2024-03-28 will automatically utilize the full features. Upgrading existing projects / customizations can be done in the following ways:

### 1. Recreating the solution and project files

This is the cleanest way, but might lead to a bit more manual work.

1. Move/Rename your whole solution folder
2. Recreate the custom path in Developer and all the project names you had
3. Copy over all `.cs` and `.xaml` files and what you need from the old folder into the same structure
4. Open the solution in Visual Studio, click "Show All Files" in the solution folder
5. Add all the copied files that show up as hidden in the tree
6. Fix all reference issues that might appear
7. Close, and open in Developer again to auto-replace the E3RootPath

### 2. Using the automatic migrator (as of 20 June 2023 kits)

Accept the prompt indicating that the projects require an one-time upgrade. This will change the project structure so it follows the new convention and also upgrade the old runtime path to use a variable.

<figure><img src="https://2522353545-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MXf5GuikRIHooatf_sm%2Fuploads%2Fl6ctfmYK1ND1z2woPSss%2Fimage.png?alt=media&#x26;token=daf19967-5a5d-49f1-a86c-3878eec5b220" alt=""><figcaption><p>Project migration dialog</p></figcaption></figure>

### 3. Manually editing all your csproj files

If you don't want to manually add all files and refrences back again, have nuget references already, etc, you can manually migrate the csproj files yourself.

All that is needed is removing a few parts from the csproj file and adding a few more lines.

Refer to the full template how the file **should** look for migrated csproj files:

{% code title="CustomProject.csproj" lineNumbers="true" %}
```xml
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
  <Import Project="..\global.props" />
  <PropertyGroup>
    <ProjectGuid>$projectguid$</ProjectGuid>
    <OutputType>library</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>$safeitemrootname$</RootNamespace>
    <AssemblyName>$safeitemrootname$</AssemblyName>
    <TargetFrameworkVersion>v$targetframeworkversion$</TargetFrameworkVersion>
    <Deterministic>true</Deterministic>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="PresentationCore" />
    <Reference Include="PresentationFramework" />
    <Reference Include="System" />
    <Reference Include="System.Core" />
    <Reference Include="System.Data" />
    <Reference Include="System.Data.DataSetExtensions" />
    <Reference Include="System.Web.Services" />
    <Reference Include="System.Xaml" />
    <Reference Include="System.Xml" />
    <Reference Include="System.Xml.Linq" />
    <Reference Include="WindowsBase" />
  </ItemGroup>
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
  <Import Project="..\global.targets" />
</Project>
```
{% endcode %}

Make note of the import statements at the top and bottom, and also which main properties are needed.\
The build definitions should be removed, as they are part of the `global.props` now.

#### What you need to remove

Remove all properties at the top of the file that aren't present in the template above. They are not needed.\
This is an example and might not include all values present for you. What is most important is to **keep** the ones that are listed as KEEP.\
Also note that one flag for `<Deterministic>` should be added.

{% code lineNumbers="true" %}
```xml
DEL        <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
DEL        <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
DEL        <ProductVersion>9.0.21022</ProductVersion>
DEL        <SchemaVersion>2.0</SchemaVersion>
     KEEP  <ProjectGuid>aaa5d313-e5a1-4212-911f-aa437d28c474</ProjectGuid>
     KEEP  <OutputType>library</OutputType>
     KEEP  <AppDesignerFolder>Properties</AppDesignerFolder>
     KEEP  <RootNamespace>Test</RootNamespace>
     KEEP  <AssemblyName>Test</AssemblyName>
     KEEP  <TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
     ADD   <Deterministic>true</Deterministic>
DEL        <FileAlignment>512</FileAlignment>
DEL        <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
DEL        <SccProjectName>SAK</SccProjectName>
DEL        <SccLocalPath>SAK</SccLocalPath>
DEL        <SccAuxPath>SAK</SccAuxPath>
DEL        <SccProvider>SAK</SccProvider>
```
{% endcode %}

We have to remove the build targets and their configuration. As mentioned, those are handled by the `global.props` now. So the block like this should be fully deleted:

```xml
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>..\Deploy</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>..\Deploy</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
```

The following block was the _old_ way of deploying the DLL to the root folder. This should be at the bottom of your file and has to be removed:

```xml
  <PropertyGroup>
    <DeployDir Condition="'$(Configuration)' == 'Debug'">$(ProjectDir)..\</DeployDir>
    <DeployDir Condition="'$(Configuration)' == 'Release'">$(ProjectDir)..\release\</DeployDir>
  </PropertyGroup>
  <Target Name="AfterBuild">
    <Copy SourceFiles="$(TargetPath)" DestinationFiles="$(DeployDir)$(TargetFileName)" SkipUnchangedFiles="true" />
  </Target>
```

This should be everything to remove.

#### What you need to add

Update the project ToolsVersion in the first line to:

```xml
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
```

Add the following import statements at the top, right behind the `<Project>` tag:

```xml
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
  <Import Project="..\global.props" />
```

Add the following import statements add the bottom, right before the closing `</Project>` tag:

```xml
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
  <Import Project="..\global.targets" />
```

Make sure that none of the imports are done multiple times.

## In-Depth explanation of how this works

TODO
