Porting desktop apps to .NET Core

Olia Gavrysh

Olia

Since I’ve been working with the community on porting desktop applications from .NET Framework to .NET Core, I’ve noticed that there are two camps of folks: some want a very simple and short list of instructions to get their apps ported to .NET Core while others prefer a more principled approach with more background information. Instead of writing up a “Swiss Army knife”-document, we are going to publish two blog posts, one for each camp:

  • This post is the simple case. It’s focused on simple instructions and smaller applications and is the easiest way to move your app to .NET Core.
  • We will publish another post for more complicated cases. This post will focus more on non-trivial applications, such WPF application with dependencies on WCF and third-party UI packages.

If you prefer watching videos instead of reading, here is the video where I do everything that is described below.

Step 0 – Prerequisites

To port your desktop apps to Core, you’ll need .NET Core 3 and Visual Studio 2019.

Step 1 – Run portability analyzer

Before porting, you should check how compatible your application is with .NET Core. To do so, download and run .NET Portability Analyzer.

  • On the first tab, Portability Summary, if you have only 100% in .NET Core column (everything is highlighted in green), your code is fully compatible, go to Step 2.
  • If you have values of less than 100%, first look at all assemblies that aren’t part of you application. For those, check if their authors are providing versions for .NET Core or .NET Standard.
  • Now look at the other part of assemblies that are coming from your code. If you don’t have any of your assemblies listed in the portability report, go to Step 2. If you do, open Details tab, filter the table by clicking on the column Assembly and only focus on the ones that are from your application. Walk the list and refactor your code to stop using the API or replace the API usage with alternatives from .NET Core.

Step 2 – Migrate to SDK-style .csproj

In Solution Explorer right-click on your project (not on the solution!). Do you see Edit Project File? If you do, you already use the SDK-style project file, so you should move to Step 3. If not, do the following.

  • Check in the Solution Explorer if your project contains a packages.config file. If you don’t, no action is needed, if you do, right-click on packages.config and choose Migrate packages.config to PackageReference. Then click OK.
  • Open your project file by right-clicking on the project and choose Unload Project. Then right-click on the project and choose Edit <your project name>.csproj.
  • Copy the content of the project file somewhere, for example into Notepad, so you can search in it later.
  • Delete everything from your project file opened in Visual Studio (I know it sounds aggressive 😊, but we will add only needed content from the copy we’ve just made in a few steps). Instead of the text you’ve just deleted, paste the following code.For a WinForms application:

    For a WPF application:
  • In Notepad, search for PackageReference. If you did not find anything, move on. If you found PackageReference, copy the entire <ItemGroup> that contains PackageReference in your project file, opened in Visual Studio, right below the lines you’ve pasted in the step above. Do it for each occurrence of the PackageReference you have found. The copied block should look like this.
  • Now do the same as above for ProjectReference. If you did not find anything, move on. If you found any ProjectReference items, they would look like this.
  • You can remove lines with <Project> and <Name> properties, since they are not needed in the new project file style. So for each ProjectReference that you have found (if any), copy only ItemGroup and ProjectReference like this.
  • Save everything. Close the .csproj file in Visual Studio. Right-click on your project in the Solution Explorer and select Reload Project. Rebuild and make sure there are no errors.

Great news, you just updated your project file to the new SDK-style! The project is still targeting .NET Framework, but now you’ll be able to retarget it to .NET Core.

Step 3 – Retarget to .NET Core

Open your project file by double-clicking on your project in Solution Explorer. Find the property <TargetFramework> and change the value to netcoreapp3.0. Now your project file should look like this:

Build and run your project. Congratulations, you ported to .NET Core 3!

Fixing errors

If you get errors like

The type or namespace <some name> could not be found

or

The name <some name> does not exist in the current context

and your portability report was green, it should be easy to fix by adding a NuGet package with the corresponding library. If you cannot find the NuGet package with the library that is missing, try referencing Microsoft.Windows.Compatibility. This package adds ~21K .NET APIs from .NET Framework.

Working with designers

Even though it is possible to edit the user interface of your application via code, developers usually prefer using the visual designers. With .NET Core we had to rearchitect the way the designers work with .NET Core projects:

  • The WPF designer is already in preview and we are working on adding more functionality to it.
  • The WinForms designer for .NET Core will be available later, and meanwhile there you can use the .NET Framework WinForms designer as a workaround.

Here is how you can use the .NET Framework WinForms designer:

  1. Copy your .csproj file (let’s say you have MyProject.csproj), give it a different name, for example MyProject.NetFramework.csproj and put it next to your existing project file.
  2. Make sure your project is closed in Visual Studio, open the new project MyProject.NetFramework.csproj.
    In Solution Explorer right-click on your project and select Properties. In the Application tab (should be open by default) set Assembly name and Default namespace to the same values as in your initial project (remove “.NetFramework” from the names).
    Save this solution next to your existing solution.
  3. Open the new project file and change the <TargetFramework> to net472.
  4. Now when you need to use the WinForms designer, load your project with the MyProject.NetFramework.csproj project file and you’ll get the full experience of .NET Framework designer. When you are done with the designer, close and open your project with the .NET Core project file.
  5. This is just a workaround until the WinForms designer for .NET Core is ready.

Why port to .NET Core

Check out the video where Scott Hunter and I are talking about all the new things coming with .NET Core 3 Porting to .NET Core 3.0.

Olia Gavrysh
Olia Gavrysh

Program Manager, .NET

Follow Olia   

31 comments

  • Bradley Uffner
    Bradley Uffner

    Thank you SOOOOO much for providing the content in both Text and video! It is so frustrating that many sites think everyone has time to watch a 20 minute video for something that could be read in under 5 (along with it being indexed and searchable).

      • Avatar
        Frederic Forjan

        because it means people can use vs code for their wpf coding and not require vs community ?note the question should be different : – do you require full wpf designer or just xaml completion?
        personnally only xaml completion (& errors) would be enough, i hate the designer

    • Avatar
      Immo Landwerth

      We’re working as fast as we can. It’s not really a resource problem, it’s hard problem to solve (moving an in-proc designer out-of-proc). We’ve got a bunch of great folks on it, but we can’t assign more people to have them think faster 🙂

  • Avatar
    thomas woelfer

    >> The WinForms designer for .NET Core will be available later
    Do you have a timeframe for that? The “workaround” isn’t practical for a real-world application. My current solution has 100+ projects and 500+ forms…
    Also: What about managed(native) c++ usage? Is this supported already?

    • Avatar
      Immo Landwerth

      We’ll ship the designer as part of .NET Core 3.0. There will likely be some limitations, for example, we probably don’t have support for 3rd party designer extensions yet, but more come on later. We totally understand that the workaround isn’t practical as a long term solution.

  • Avatar
    Catalin Pop

    When Visual Studio is migrated to .Net core then we will know .Net core was “dog fed” enough to make it a stable solid platform. Just like when visual studio moved to WPF, we knew WPF has become a solid state of the art platform. Therefore dear Microsoft, please start moving Visual Studio to .Net Core and WPF on .Net core, then we knoe it’s ready for the most demanding jobs.

    • Avatar
      Immo Landwerth

      As a former customers I can relate. FWIW, we take dog feeding very seriously at Microsoft. At the same time, there is an order to things. Bringing up all of Visual Studio on top of .NET Core is a massive undertaking. As part of .NET 5 (which ships next year) we’re starting with Visual Studio for Mac on .NET Core. VS for Mac is smaller and mostly managed code and thus easier to bring up. So yes, if your app is sa large as VS, the current state of the preview bits wouldn’t be a good starting point. At the same time, very few apps are that big.

  • Avatar
    Ion Sorin Torjo

    Hi,
    Any win2d + xaml islands examples that work out of the box? Thanks!
    (what I mean is: I want to have a WPF app use xaml islands and use win2d through that).

      • Avatar
        Paulo Pinto

        Just like Daniel, we will be waiting.
        Already burned a couple of times as you guys keep changing direction, and we are not keen dealing with workarounds, and manual editing files as those proposed here. 
        Migrating between WinRT, UA, UWP and now WinUI has been a rollercoast ride.
        Plus many of the third parties we depend on are still delivering their libraries on .NET Framework.
        We just moved from .NET Framework 4.6.x to .NET Framework 4.7.x, for green field projects and plan to stay here for the forseable future, even without C# 8.

      • Avatar
        Paul Cohen

        Sorry it took me a while to respond, I have been off-line. For starters VB project files require a lot more entries <RootNamespace></RootNamespace><AssemblyName></AssemblyName>, My.Computer isn’t defined, instructions to Compile Designer files with Update sepcified. <DependantUpon> entries. <Subtypes>
            <Compile Update=”IgnoreFilesWithErrorsListDialog.Designer.vb”>      <DependentUpon>IgnoreFilesWithErrorsListDialog.vb</DependentUpon>      <SubType>Form</SubType>    </Compile>
        and then a bunch of stuff for settings.
          <ItemGroup>    <None Include=”My Project\Settings.settings”>      <Generator>SettingsSingleFileGenerator</Generator>      <CustomToolNamespace>My</CustomToolNamespace>      <LastGenOutput>Settings.Designer.vb</LastGenOutput>    </None>    <Compile Update=”My Project\Settings.Designer.vb”>      <AutoGen>True</AutoGen>      <DependentUpon>Settings.settings</DependentUpon>      <DesignTimeSharedInput>True</DesignTimeSharedInput>    </Compile>    <Compile Update=”My Project\Application.Designer.vb”>      <AutoGen>True</AutoGen>      <DependentUpon>Application.myapp</DependentUpon>    </Compile>    <None Include=”My Project\Application.myapp”>      <Generator>MyApplicationCodeGenerator</Generator>    </None>    <Compile Update=”My Project\Resources.Designer.vb”>      <AutoGen>True</AutoGen>      <DesignTime>True</DesignTime>      <DependentUpon>Resources.resx</DependentUpon>    </Compile>
          </ItemGroup>
        MsgBox is missing and MyApplication doesn’t compile and almost every line has an issue.
                <Global.System.Diagnostics.DebuggerStepThroughAttribute()>  _        Public Sub New()            MyBase.New(Global.Microsoft.VisualBasic.ApplicationServices.AuthenticationMode.Windows)            Me.IsSingleInstance = false            Me.EnableVisualStyles = true            Me.SaveMySettingsOnExit = true            Me.ShutDownStyle = Global.Microsoft.VisualBasic.ApplicationServices.ShutdownMode.AfterMainFormCloses        End Sub                <Global.System.Diagnostics.DebuggerStepThroughAttribute()>  _        Protected Overrides Sub OnCreateMainForm()            Me.MainForm = Global.CSharpToVBApp.Form1        End Sub    End Class

  • Avatar
    Daniel Smith

    This is awesome, can’t wait to port to .NET Core 3.0.  Any news on the ReportViewer control?  Are the SSRS team working on this?

  • Avatar
    Karel Král

    I do not understand why migrating .csproj must be done in Notepad by my hands? Why is not MS creating some tool to migrate .csproj from old format to a new format? Why I cannot upgrade .csproj by right click directly in Visual Studio? 
    We have solutions with 200+ projects. 

    • Avatar
      Chris Martin

      The move to the 2017 SDk / package reference format can be sped up by using tool here (which I think at least one MS migration guide used to recommend):
      https://github.com/hvanbakel/CsprojToVs2017We have >500 projects in one solution I’m working on, and another 200 on one we will come to. We might want unit or integration tests to have a slightly different end result (e.g .Net Core unit tests, and apps, vs Standard for library projects,). There are some custom bits in the old Csproj we also have to retain and some NuGet references we need to swap out as the old one was not .Net Standard compatible, or references we wanted to change to NuGet references, etc. Even references to remove as it causes conflicts (we’re using a package for ValueTuple in framework 4.6.1 for example). There are also some 3rd party projects that are still .Net Framework and even a few projects that we can’t immedialy port because they have Windows Specific code in or use technlogy that didn’t come to .NET Standard/Core. My testing has shown there are errors occurring from just changing the NuGet format and staying on .NEt Framework (an odd one where we had to fully qualify an override of GetHashCode that we had in our own custom extensions library, for example).
      In the end, it can get complex and while i do think Microsoft could have tooling that gets a bit further along (at least as far as the tool above, and on the solution level, not just one project at a time), I can understand why they might be hesitant to release a conversion tool – one size would be unliklely to fit all in this scenario.

  • Avatar
    Thad House

    Will there be any guide on how to update programs that have a `COMReference` block? I’m trying to see if I can shim it in with another library, but it would be nice to have this supported by default. Specifically, I need access to the `IWshRuntimeLibrary` COM API’s to create desktop shortcuts.

  • Yordan .
    Yordan .

    Porting from the good to the junk ?! You are joking right ?!Look – we are not writting 2 rows of code with an absurdly low capabilities. REAL Windows developers is keep looking for more and more power going cross NET-to-NATIVE ( optimized down to assembler level code )..NET CORE on it’s current state is something which I will never, ever touch in order to make anithing for desktop if it keeps to exists in this state.PLEASE DO NOT REPEAT THE MISTAKE OF WINDOWS RT !!!A yeah. Windows 10 is a complete junk in every aspect. Double cross it as a real platform. Deca cross it as the future.It is a completely no-go if peples wanna do complex things with their computers. And NO – we are not looking for 1/2 of the screen big button to click it with our legs. The quality and the point of the calculations and the point of design and elegancy is lost with Windows 8 UI.One platform capable of everything is lost with Windows 10. Please stop making the worse things hapens. Revert back to meanful UI, revert back to expanded capabilities available in Windows 7.

  • Avatar
    Stefan Over

    Can we distribute the WPF applications ported to .NET Core 3.0 using ClickOnce?Could you please go into more details about deploying a .NET Core WPF application, with automatic updates? Thanks 🙂

  • Avatar
    Felipe Pessoto

    I don’t know if it is happening just with me, but when opening a .NET Core 3.0 project I receive this error:

    —————————
    Microsoft Visual Studio
    —————————
    The project file cannot be opened by the project system, because it is missing some critical imports or the referenced SDK cannot be found.

    Detailed Information:
    C:\Program Files\dotnet\sdk\2.2.300\Sdks\Microsoft.NET.Sdk.WindowsDesktop\Sdk not found. Check that a recent enough .NET Core SDK is installed and/or increase the version specified in global.json.

    —————————
    OK
    —————————

    It worked after I created a global.json file to force the targe to the .NET Core 3.0:

    {
    “sdk”: {
    “version”: “3.0.100-preview5-011568”
    }
    }

    But Visual Studio still gives me a warning with a inexistent option, to enable .NET Core Preview in VS:

    Please enable using preview .NET Core SDKs in the Visual Studio Options to open.NET Core 3.0 projects

    • Avatar
      Alexandr Golikov

      Ah. They moved this option )))))
      Tools -> Options -> Environment -> Preview Features
      Check ‘Use previews of the .NET Core SDK’.

  • Avatar
    Frank Peiffer

    Will there be any migration path for mixed language projects such as C#/VB.NET applications calling unmanaged C++ class libraries through C++/CLI wrapper DLLs (i.e. where PInvoke is simply not enough)?

Leave a comment