前言
先决条件
- Windows 操作系统
- .NET 6 SDK
- Visual Studio 2022 17.0 或更高版本
.NET 升级助手是一个 .NET 工具,可以使用以下命令进行全局安装:
代码语言:javascript复制dotnet tool install -g upgrade-assistant
运行
代码语言:javascript复制upgrade-assistant upgrade .SchoolClient.sln
目前结论
老项目依赖众多,很多依赖并不支持.net6,因此放弃迁移。 新项目可以考虑使用。
问题处理
打印不显示
打印要替换为
代码语言:javascript复制System.Diagnostics.Trace.WriteLine("WS:用户上线");
依赖不兼容
自动迁移后的包
我们发现自动迁移后有些包是不可用的。
代码语言:javascript复制<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
要找对应支持的版本进行替换
更换后的包
代码语言:javascript复制<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
预生成事件保持不变
代码语言:javascript复制xcopy /Y /i /e $(ProjectDir)wwwroot $(TargetDir)wwwroot
xcopy /Y /d $(ProjectDir)DLLlibwebp.dll $(TargetDir)
程序不包含适合于入口点
报错
程序不包含适合于入口点的静态 “Main” 方法
解决方式
生成操作选择 应用程序定义
自定义工具输入 MSBuild:Compile
appSettings读写
.net framework的读写方式
以前配置在App.config
中的appSettings
下
之前的读写方法
代码语言:javascript复制/// <summary>
/// 配置文件读取
/// </summary>
/// <param name="key">配置文件中key字符串</param>
/// <returns></returns>
public static string GetConfigValue(string key)
{
try
{
Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
//获取AppSettings的节点
AppSettingsSection appsection = (AppSettingsSection)config.GetSection("appSettings");
return appsection.Settings[key].Value;
}
catch
{
return "";
}
}
/// <summary>
/// 配置文件写入
/// </summary>
/// <param name="key">配置文件中key字符串</param>
/// <param name="value">配置文件中value字符串</param>
/// <returns></returns>
public static bool SetConfigValue(string key, string value)
{
try
{
//打开配置文件
Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
//获取AppSettings的节点
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
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();
}
/// <summary>
/// 读取指定节点的字符串
/// </summary>
/// <param name="sessions"></param>
/// <returns></returns>
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方式读写
代码语言:javascript复制using System;
using System.Configuration;
namespace SchoolClient.Utils
{
public static class ZConfigUtil
{
///<summary>
///返回app.config文件中appSettings配置节的value项
///</summary>
///<param name="strKey"></param>
///<returns></returns>
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;
}
///<summary>
///在app.config文件中appSettings配置节增加一对键值对
///</summary>
///<param name="newKey"></param>
///<param name="newValue"></param>
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方式读写
代码语言:javascript复制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;
}
/// <summary>
/// 初始化配置
/// </summary>
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));
}
}
/// <summary>
/// 获取配置文件
/// </summary>
/// <returns></returns>
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();
}
}
/// <summary>
/// 保存配置文件
/// </summary>
/// <param name="config"></param>
public static void configSet(ConfigModel config)
{
string configpath = getconfigpath();
writetxt(configpath, JsonConvert.SerializeObject(config));
}
/// <summary>
/// 设置临时文件存储位置
/// </summary>
/// <param name="value"></param>
public static void setSavepath(string value)
{
ConfigModel config = configGet();
config.savepath = value;
configSet(config);
}
/// <summary>
/// 获取临时文件存储位置
/// </summary>
/// <returns></returns>
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
;
如下所示:
代码语言:javascript复制<PropertyGroup>
<SelfContained>false</SelfContained>
<RuntimeIdentifier>win-x86</RuntimeIdentifier>
</PropertyGroup>
64位的
代码语言:javascript复制<PropertyGroup>
<SelfContained>false</SelfContained>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
</PropertyGroup>
多语言精简
我们没有为项目指定语言, 所以会列出多种语言。
解决方法:
在csproj文件中的PropertyGroup
中,
<PropertyGroup>
<SatelliteResourceLanguages>zh-Hans</SatelliteResourceLanguages>
</PropertyGroup>