.NET Core 3.0
.NET Core 3.0 is a new incarnation for .NET Framework with upgrades, launched on 9/23/2019. .NET Core 3.0 has compatibility with several distros of Linux and runs on macOS too. .NET Core 3.0 has support for WinForms, but you will not be able to run it on Linux and macOS. The output of the conversion will be a single EXE file.
Upgrading
I upgraded a big WinForms App to .NET Core 3.0. It took me one day, but not because it was hard but because the online resources available are confusing.
The first step was to create a new Solution, and one by one project from the original solution, I did from a scratch.
After that, I copied all project files and the folders Resources and Properties, on the folder Properties just delete AssemblyInfo.cs file and *.licx if there are some.
While upgrading probably you will get some assemblies that are missing or not compatible.
Look on NuGet and search for the namespace, if it is from Microsoft, or try a search for a replacement in .NET Core 3.0. In my case two assemblies were not crucial so I disabled code with:
Configuring the project to Run with a Single EXE
This sample is for Windows, deployed for win-x86, that runs both on 32bits and 64bits Windows OS.
While configuring to publish, I found a bug in this process. The fix: to add a singular key: RuntimeIdentifier because an error occurred NETSDK1097, that I followed to https://github.com/dotnet/core/issues/2851 with no solution.
So I interpreted literally the message and presumed that it was a mistake from the designer.
To make it work, add these keys to .csproj,
- <PropertyGroup>
- <OutputType>WinExe</OutputType>
- <TargetFramework>netcoreapp3.0</TargetFramework>
- <UseWindowsForms>true</UseWindowsForms>
-
- <PublishSingleFile>true</PublishSingleFile>
- <PublishTrimmed>true</PublishTrimmed>
- <TieredCompilationQuickJit>true</TieredCompilationQuickJit>
- <PublishReadyToRun>true</PublishReadyToRun>
- <RuntimeIdentifier>win-x86</RuntimeIdentifier>
- <RuntimeIdentifiers>win-x86</RuntimeIdentifiers>
- </PropertyGroup>
Note that the this singular key is needed to avoid the error, although duplicated in plural:
- <RuntimeIdentifier>win-x86</RuntimeIdentifier>
Publish error
*It is not supported to publish an application to a single-file without specifying a RuntimeIndentifier. Please either specify a RuntimeIdentifier or set PublishSingleFile to false.
Internal message error on .tmp file:
- System.AggregateException: One or more errors occurred. ---> System.Exception: Publishing failed.
- --- End of inner exception stack trace ---
- at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
- at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
- at Microsoft.Publish.Framework.Model.DefaultPublishSteps.<>c__DisplayClass26_0.<IsBuildCompletedSuccessfully>b__2()
- at System.Threading.Tasks.Task`1.InnerInvoke()
- at System.Threading.Tasks.Task.Execute()
- --- End of stack trace from previous location where exception was thrown ---
- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
- at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
- at Microsoft.Publish.Framework.Model.DefaultPublishSteps.<DefaultCorePublishStep>d__23.MoveNext()
- --- End of stack trace from previous location where exception was thrown ---
- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
- at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
- at Microsoft.Publish.Framework.ViewModel.ProfileSelectorViewModel.<RunPublishTaskAsync>d__202.MoveNext()
- ---> (Inner Exception #0) System.Exception: Publishing failed.<---
-
- System.Exception: Publishing failed.
-
- ===================
Publising
Now you need to create a profile for this,
If your application will run only in process x64, you can select another runtime target.
Conclusion
My app started very fast as a single exe file. But the size was about 300MB and takes more time to build and generate this file.
I hope this post helps you deliver a better and faster solution for your end-user.
UPDATE 10/05/2019:
If you are using:
SqlConnection.GetSchema Method
you will get run time error: "Column requires a valid datatype."
To fix it set PublishTrimmed to false: <PublishTrimmed>false</PublishTrimmed>
See the end of this message for details on invoking
just-in-time (JIT) debugging instead of this dialog box.
************** Exception Text **************
System.ArgumentException: Column requires a valid DataType.
at System.Data.DataColumn.set_DataType(Type value)
at System.Data.XSDSchema.SetProperties(Object instance, XmlAttribute[] attrs)
at System.Data.XSDSchema.HandleElementColumn(XmlSchemaElement elem, DataTable table, Boolean isBase)
at System.Data.XSDSchema.HandleParticle(XmlSchemaParticle pt, DataTable table, ArrayList tableChildren, Boolean isBase)
at System.Data.XSDSchema.HandleComplexType(XmlSchemaComplexType ct, DataTable table, ArrayList tableChildren, Boolean isNillable)
at System.Data.XSDSchema.InstantiateTable(XmlSchemaElement node, XmlSchemaComplexType typeNode, Boolean isRef)
at System.Data.XSDSchema.HandleTable(XmlSchemaElement node)
at System.Data.XSDSchema.HandleDataSet(XmlSchemaElement node, Boolean isNewDataSet)
at System.Data.XSDSchema.LoadSchema(XmlSchemaSet schemaSet, DataSet ds)
at System.Data.DataSet.ReadXSDSchema(XmlReader reader, Boolean denyResolving)
at System.Data.DataSet.ReadXml(XmlReader reader, Boolean denyResolving)
at System.Data.DataSet.ReadXml(Stream stream)
at System.Data.ProviderBase.DbMetaDataFactory.LoadDataSetFromXml(Stream XmlStream)
at System.Data.ProviderBase.DbMetaDataFactory..ctor(Stream xmlStream, String serverVersion, String normalizedServerVersion)
at System.Data.SqlClient.SqlConnectionFactory.CreateMetaDataFactory(DbConnectionInternal internalConnection, Boolean& cacheMetaDataFactory)
at System.Data.ProviderBase.DbConnectionFactory.GetMetaDataFactory(DbConnectionPoolGroup connectionPoolGroup, DbConnectionInternal internalConnection)
at System.Data.ProviderBase.DbConnectionInternal.GetSchema(DbConnectionFactory factory, DbConnectionPoolGroup poolGroup, DbConnection outerConnection, String collectionName, String[] restrictions)
at System.Data.SqlClient.SqlConnection.GetSchema(String collectionName, String[] restrictionValues)
at System.Data.SqlClient.SqlConnection.GetSchema(String collectionName)