前言
先说结论
目前还不建议桌面端应用做迁移。
原因如下
所以还是退回.Net Framework了。
先决条件
.NET 升级助手是一个 .NET 工具,可以使用以下命令进行全局安装:
1
| dotnet tool install -g upgrade-assistant
|
运行
1
| upgrade-assistant upgrade .\SchoolClient.sln
|
目前结论
老项目依赖众多,很多依赖并不支持.net6,因此放弃迁移。
新项目可以考虑使用。
问题处理
打印不显示
打印要替换为
1
| System.Diagnostics.Trace.WriteLine("WS:用户上线");
|
依赖不兼容
自动迁移后的包
我们发现自动迁移后有些包是不可用的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <ItemGroup> <PackageReference Include="Aspose.Words" Version="19.10.0" /> <PackageReference Include="ICSharpCode.SharpZipLib.dll" Version="0.85.4.369" /> <PackageReference Include="ImageProcessor" Version="2.9.1" /> <PackageReference Include="Imazen.WebP" Version="10.0.1" /> <PackageReference Include="LiveCharts.Wpf" Version="0.9.7" /> <PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="5.2.9" /> <PackageReference Include="Microsoft.Office.Interop.Word" Version="15.0.4797.1004" /> <PackageReference Include="Newtonsoft.Json" Version="12.0.3" /> <PackageReference Include="QRCoder" Version="1.3.9" /> <PackageReference Include="SuperWebSocket" Version="0.9.0.2" /> <PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" /> <PackageReference Include="System.Data.DataSetExtensions" Version="4.5.0" /> <PackageReference Include="System.Data.SQLite" Version="1.0.113.7" /> <PackageReference Include="WpfAnimatedGif" Version="2.0.0" /> <PackageReference Include="System.ServiceModel.Federation" Version="4.8.1" /> <PackageReference Include="Microsoft.DotNet.UpgradeAssistant.Extensions.Default.Analyzers" Version="0.4.336902"> <PrivateAssets>all</PrivateAssets> </PackageReference> <PackageReference Include="Microsoft.Windows.Compatibility" Version="6.0.0" /> </ItemGroup>
|
发现很多库不支持.net core
要找对应支持的版本进行替换
更换后的包
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| <ItemGroup> <PackageReference Include="Aspose.Words" Version="19.10.0" /> <PackageReference Include="ImageProcessor.Core" Version="1.1.0" /> <PackageReference Include="LiveCharts.Wpf.Core" Version="0.9.8" /> <PackageReference Include="log4net" Version="2.0.15" /> <PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="5.2.9" /> <PackageReference Include="Microsoft.Extensions.Configuration" Version="6.0.1" /> <PackageReference Include="Microsoft.Office.Interop.Word" Version="15.0.4797.1004" /> <PackageReference Include="Newtonsoft.Json" Version="12.0.3" /> <PackageReference Include="QRCoder" Version="1.3.9" /> <PackageReference Include="SharpZipLib" Version="1.3.3" /> <PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" /> <PackageReference Include="System.Data.DataSetExtensions" Version="4.5.0" /> <PackageReference Include="System.Data.SQLite" Version="1.0.113.7" /> <PackageReference Include="TouchSocket" Version="0.5.2" /> <PackageReference Include="WpfAnimatedGif" Version="2.0.0" /> <PackageReference Include="System.ServiceModel.Federation" Version="4.8.1" /> <PackageReference Include="Microsoft.Windows.Compatibility" Version="6.0.0" /> </ItemGroup>
|
其中有的库要找Core版本的,如
ImageProcessor =>ImageProcessor.Core
LiveCharts.Wpf => ``LiveCharts.Wpf.Core`.
有的库就要换成新的了
SuperWebSocket => TouchSocket
Imazen.WebP => https://github.com/psvmc/Imazen.WebP
预生成事件保持不变
1 2
| xcopy /Y /i /e $(ProjectDir)\wwwroot $(TargetDir)\wwwroot xcopy /Y /d $(ProjectDir)\DLL\libwebp.dll $(TargetDir)
|
程序不包含适合于入口点
报错
程序不包含适合于入口点的静态 “Main” 方法
解决方式
生成操作选择 应用程序定义
自定义工具输入 MSBuild:Compile
配置文件读写
.net framework的读写方式
以前配置在App.config中的appSettings下
之前的读写方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
|
public static string GetConfigValue(string key) { try { Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); AppSettingsSection appsection = (AppSettingsSection)config.GetSection("appSettings"); return appsection.Settings[key].Value; } catch { return ""; } }
public static bool SetConfigValue(string key, string value) { try { Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); AppSettingsSection appsection = (AppSettingsSection)config.GetSection("appSettings"); appsection.Settings[key].Value = value; config.Save();
return true; } catch { return false; } }
|
迁移后就不能用了,原来的配置文件变成了``
相应的读写方法也变了。
.net6读取appsettings.json
Nuget 安装 Microsoft.Extensions.Configuration
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| using Microsoft.Extensions.Configuration;
using System.Linq;
namespace SchoolClient.Utils { public class ZConfigCoreUtil { private static IConfiguration _config;
public static void init() { _config = new ConfigurationBuilder().AddJsonFile("appsettings.json").Build(); }
public static string GetVaule(params string[] sessions) { if (_config == null) { init(); } try { if (sessions.Any()) { return _config[string.Join(":", sessions)]; } } catch { return ""; } return ""; }
public static void test() { System.Diagnostics.Trace.WriteLine("IsDebug:" + GetVaule("IsDebug")); } } }
|
但是只支持读取配置了,不支持写入,所以要把项目运行时读写的字段换一种方式。
其实这也是合理的,我也推荐项目本身的配置和项目运行的配置分开保存,项目的配置只能读取,运行中的配置则可以读写。
下面两种方式任取其一即可。
推荐使用JSON方式。
XML方式读写
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
| using System; using System.Configuration;
namespace SchoolClient.Utils { public static class ZConfigUtil { public static string GetVaule(string strKey) { return GetVaule(strKey, "app.config"); }
public static string GetVaule(string strKey, string filepath) { ExeConfigurationFileMap file = new ExeConfigurationFileMap(); file.ExeConfigFilename = filepath; Configuration config = ConfigurationManager.OpenMappedExeConfiguration(file, ConfigurationUserLevel.None); foreach (string key in config.AppSettings.Settings.AllKeys) { if (key == strKey) { return config.AppSettings.Settings[strKey].Value.ToString(); } } return null; }
public static void SetVaule(string newKey, string newValue) { SetVaule(newKey, newValue, "app.config"); }
public static void SetVaule(string newKey, string newValue, string filepath) { ExeConfigurationFileMap file = new ExeConfigurationFileMap(); file.ExeConfigFilename = filepath; Configuration config = ConfigurationManager.OpenMappedExeConfiguration(file, ConfigurationUserLevel.None); bool exist = false; foreach (string key in config.AppSettings.Settings.AllKeys) { if (key == newKey) { exist = true; } } if (exist) { config.AppSettings.Settings.Remove(newKey); } config.AppSettings.Settings.Add(newKey, newValue); config.Save(ConfigurationSaveMode.Modified); ConfigurationManager.RefreshSection("appSettings"); }
public static void test() { SetVaule("ServerIp", "127.0.0.1"); SetVaule("ServerPort", "8899"); Console.WriteLine("ServerIp:" + GetVaule("ServerIp")); Console.WriteLine("ServerXXX:" + (GetVaule("ServerXXX") == null)); } } }
|
JSON方式读写
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
| using Newtonsoft.Json;
using System; using System.IO;
namespace SchoolClient.Utils { public class ZConfigJsonUtil { private static string readtxt(string filepath) { string config_txt = ""; using (FileStream fs = new FileStream(filepath, FileMode.OpenOrCreate, FileAccess.ReadWrite)) { using (StreamReader sr = new StreamReader(fs)) { config_txt = sr.ReadToEnd(); } }
return config_txt; }
private static void writetxt(string filepath, string txt) { using (FileStream fs = new FileStream(filepath, FileMode.Truncate, FileAccess.ReadWrite)) { using (StreamWriter sw = new StreamWriter(fs)) { sw.Write(txt); } } }
private static string getconfigpath() { string docpath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); string configfolderpath = Path.Combine(docpath, "_XHCLASS"); if (!Directory.Exists(configfolderpath)) { Directory.CreateDirectory(configfolderpath); }
string configpath = Path.Combine(configfolderpath, "config.json"); return configpath; }
public static void init() { string configpath = getconfigpath(); string txt = readtxt(configpath); if (string.IsNullOrEmpty(txt)) { txt = "{}"; ConfigModel jsonobj = JsonConvert.DeserializeObject<ConfigModel>(txt); string docpath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); string configfolderpath = Path.Combine(docpath, "_XHCLASS"); jsonobj.savepath = configfolderpath; writetxt(configpath, JsonConvert.SerializeObject(jsonobj)); } }
public static ConfigModel configGet() { string configpath = getconfigpath(); string txt = readtxt(configpath); if (string.IsNullOrEmpty(txt)) { txt = "{}"; } try { return JsonConvert.DeserializeObject<ConfigModel>(txt); ; } catch (Exception) { return new ConfigModel(); } }
public static void configSet(ConfigModel config) { string configpath = getconfigpath(); writetxt(configpath, JsonConvert.SerializeObject(config)); }
public static void setSavepath(string value) { ConfigModel config = configGet(); config.savepath = value; configSet(config); }
public static string getSavepath() { var config = configGet(); if (string.IsNullOrEmpty(config.savepath)) { string docpath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); string configfolderpath = Path.Combine(docpath, "_XHCLASS"); return configfolderpath; } else { return config.savepath; } } }
public class ConfigModel { public string savepath { get; set; } } }
|
输出精简
多运行时精简
输出目录中创建了一个名为runtime的文件夹,里面有很多与平台相关的dll。
解决方法
在csproj文件中的PropertyGroup中,将SelfContained属性设置为false并指定一个RuntimeIdentifier;
如下所示:
1 2 3 4
| <PropertyGroup> <SelfContained>false</SelfContained> <RuntimeIdentifier>win-x86</RuntimeIdentifier> </PropertyGroup>
|
64位的
1 2 3 4
| <PropertyGroup> <SelfContained>false</SelfContained> <RuntimeIdentifier>win-x64</RuntimeIdentifier> </PropertyGroup>
|
多语言精简
我们没有为项目指定语言, 所以会列出多种语言。
解决方法:
在csproj文件中的PropertyGroup中,
1 2 3
| <PropertyGroup> <SatelliteResourceLanguages>zh-Hans</SatelliteResourceLanguages> </PropertyGroup>
|