How to convert a non-core csproj to VS2017 format

There isn't an option built into VS because the cleaner csproj is primarily for .NET Core projects. It does not fully work with all other project types without some effort and futher customizations in the project file. For example, wiring up things like code generators or nesting in Winforms or WPF apps may not work out of the box for a new SDK-style (new style) .csproj. These can usually be worked around by updating metadata as needed:

<ItemGroup>
  <Compile Update="Properties\Resources.Designer.cs">
    <AutoGen>True</AutoGen>
    <DependentUpon>Resources.resx</DependentUpon>
  </Compile>
</ItemGroup>

Note that the Update attribute is key here - you don't want to include the file a second time in the ItemGroup, you just want to update its existing (or lacking) metadata.

There are also some caveats for some project types where targets do not get imported as expected in an SDK-based csproj vs and old one. This depends on how your targets are authored, but one example of this is building VSIX projects (VS extensions) using the VSSDK is really hard to get right in an SDK-based project.

If you want to try the conversion, Nate McMaster's blog post is an excellent resource. He covers both starting from scratch and converting the file in situ. I've found that most of the time it goes pretty smoothly to start with a new clean .csproj and add in any workaround needed.

It's also worth pointing out that a lot of the crap in your normal csproj file is just generated content, and a little hand-editing can go a long way towards cleaning it up. Using globbing patterns, for example, can save hundreds of lines in a large project file. This is part of how SDK-based projects work anyways - they just do the globs in the SDK, so it doesn't show up in the .csproj, but it works nearly the same. For example, if you want to include all the C# files under a folder (recursively), you can do something like this:

<ItemGroup>
  <!-- Include all C# files under the SampleFolder and any child folders -->
  <Compile Include="SampleFolder\**\*.cs" />
  <!-- Include all C# files under this project's root: -->
  <Compile Include="**\*.cs" />
<ItemGroup>

The ** matches any recursive folder path.

There are some differences in Visual Studio behavior, because the new project system for SDK-based projects works very different than the old .csproj project system. For example, SDK-projects will automatically detect when files change on disk and add/remove them in the projects; old-csproj won't update them in VS until the project is reloaded.

If you do use globbing everywhere, you'll run into a similar problem as in SDK-based csproj, where certain files are not hooked up to their code generators or nested correctly. As above, you can use the Update= attribute to fix up specific files (or even more specific globs) to get the metadata back to the same.


It may be worth your time to look at these. It looks like it can't be done for more complex project types but console and libraries appear to be upgradable http://www.natemcmaster.com/blog/2017/03/09/vs2015-to-vs2017-upgrade/

https://github.com/NickCraver/PerfBenchmarks/commit/53c3013b1774056363dcab867bceb1b89ce9592c

And regarding the addition of the more complex sdk types you can watch this github issue.

https://github.com/dotnet/sdk/issues/491