省流:升级: 运行 upgrade-assistant upgrade 命令,传入正在升级的项目或解决方案的名称。
upgrade-assistant upgrade "F:\DouyinBarrageGrab-main\BarrageService.sln"
upgrade-assistant upgrade "路径"
将.NET Framework项目升级为.NET 6
C# 利用.NET 升级助手将.NET Framework项目升级为.NET 6
.NET6 正式版本已经发布有一阵子了,今天我就体验一下如何将.NET Framework的项目升级为.NET 6.
升级条件:
- Windows 操作系统
- .NET 6 SDK
- Visual Studio 2022 17.0 或更高版本
环境准备
①首先是VS2022下载,直接上微软官方网站,下载地址:
https://visualstudio.microsoft.com/zh-hans/downloads/
下载后,在线安装就行,如果之前有vs的其它版本也不用卸载,VS可以多个版本共存,安装的时候.NET 6的运行时默认会勾选安装,
②如果需要单独下载SDK和运行时,可以上微软官网,地址:
.NET SDKs downloads for Visual Studio (microsoft.com)
③安装好以后,可以在window命令窗口确认.NET 6是否安装正常
.NET Portability Analyzer安装和使用
升级前最好先分析下你的项目依赖的类库是否支持最新的.NET平台,这里可以利用扩展工具.NET Portability Analyzer去完成(仅支持.NET 5以下版本):

扩展工具下载安装完成后,重启VS。在工程或者解决方案的右键菜单中,选择:Portability Analyzer Settings。在配置页面,选择要分析的.net 版本即可。
设置完成后,在VS的工程或者解决方案右键菜单中,选择:Analyze Assembly Portability,然后过一会儿就会出现结果。第二个Sheet页面详细的说明了不支持的API信息。
dotnet tool install -g upgrade-assistant
项目升级
①分析 : .NET 升级助手工具包括一种分析模式,它可以提供有关在升级开始之前可能需要进行的更改的见解。在命令窗口 运行 upgrade-assistant analyze 命令,传入正在升级的项目或解决方案的名称。如下图:输出中有很多内部诊断信息,但某些信息非常有用。请注意,分析模式指示升级将建议项目以 net6.0-windows 目标框架名字对象 (net6.0-windows) 为目标。这是因为解决方案引用的项目是 WPF 项目,是一种仅限 Windows 的技术。控制台应用程序可能会获得直接升级到 TFM net6.0 的建议,除非它使用某些特定于 Windows 的库。
如果报告了任何错误或警告,请在开始升级前处理这些错误或警告。
②升级: 运行 upgrade-assistant upgrade 命令,传入正在升级的项目或解决方案的名称。

该工具将运行并显示它将执行的步骤列表。完成每个步骤后,该工具将提供一组命令,让用户应用或跳过下一步或其他选项。按 Enter 而不选择数字会选择列表中的第一项。
详细步骤可参考官网文档--链接地址:
https://docs.microsoft.com/zh-cn/dotnet/core/porting/upgrade-assistant-wpf-framework
打开项目
升级完成后,选择VS2022打开项目,我旧项目依赖的Caliburn.Micro版本是3.2的不支持.NET 6,它已经自动升级到最高版本
变更项:
①packages.config被迁移到项目.csproj文件
升级助手介绍和安装
我们之前的应用在 .NET Framework 上运行,现在想将它们移植到 .NET 6。 当然你可以选择手动移植,但是更方便的方法是利用微软提供的升级助手去完成这个操作.
首先是升级助手安装,方法很简单,在命令窗口执行:
把这个app.config转成<?xml version="1.0" encoding="utf-8"?>
<configuration>
<!--配置更改后重启才能生效-->
<appSettings>
<!--过滤Websocket数据源进程,可用','进行分隔,程序将会监听以下进程的弹幕信息-->
<add key="processFilter" value="直播伴侣,douyin,chrome,msedge,QQBrowser,360se,firefox,2345explorer,iexplore" />
<!--Websocket监听端口-->
<add key="wsListenPort" value="8888" />
<!--true:监听在0.0.0.0,接受任意Ip连接,false:监听在127.0.0.1,仅接受本机连接-->
<add key="listenAny" value="true" />
<!--系统代理端口-->
<add key="proxyPort" value="8827" />
<!--上游代理地址,例如开启了系统代理,但是需要将其他无关请求转发到VPN工具中,例如:127.0.0.1:11223,不要带http://-->
<add key="upstreamProxy" value="" />
<!--在控制台输出弹幕-->
<add key="printBarrage" value="true" />
<!--要在控制台打印的弹幕类型,多个使用','分隔,(空代表不过滤) 1[普通弹幕],2[点赞消息],3[进入直播间],4[关注消息],5[礼物消息],6[统计消息],7[粉丝团消息],8[直播间分享],9[下播]-->
<add key="printFilter" value="" />
<!--要推送的弹幕消息类型,多个使用','分隔,同上-->
<add key="pushFilter" value="" />
<!--要日志记录的弹幕消息类型,多个使用','分隔,同上-->
<add key="logFilter" value="1,2,4,5,6,7,8" />
<!--要进行过滤的Web房间ID,多个使用','分隔,根据缓存来过滤的,直播伴侣不支持 -->
<add key="webRoomIds" value="" />
<!--是否启用系统代理,若设置为false 则需要在程序手动指定代理地址 -->
<add key="usedProxy" value="true" />
<!--开启内置的域名过滤,设置为false会解包所有https请求,cpu占用很高,建议在无法获取弹幕数据时调整 -->
<add key="filterHostName" value="true" />
<!--已知的弹幕域名列表 ','分隔 用作过滤规则中,凡是webcast开头的域名程序都会自动列入白名单-->
<add key="hostNameFilter" value="" />
<!--隐藏控制台-->
<add key="hideConsole" value="false" />
<!--弹幕文件日志-->
<add key="barrageFileLog" value="false" />
<!--显示窗体-->
<add key="showWindow" value="false" />
<!--进入直播间自动暂停播放-->
<add key="autoPause" value="true" />
<!--强制启用轮询模式获取弹幕 (对于容易断开连接或者更加追求稳定的直播间,可以启用这个开关,虽然响应速度不如WebSocket,但是绝对稳定!)-->
<add key="forcePolling" value="false" />
<!--弹幕轮询间隔,当 forcePolling 为 true 时生效 (毫秒,1000毫秒=1秒,不建议小于1000毫秒,太小可能会被封IP,值越小,弹幕流越丝滑,对于观众多的直播间可以改小)-->
<add key="pollingInterval" value="3000" />
<!--禁用直播页浏览器脚本缓存 (如果需要确保脚本每次能够正常匹配替换,则启用它,可能会损失一定的页面加载速度)-->
<add key="disableLivePageScriptCache" value="true" />
<!--指定要发送的COM串口 格式:'COM1:9600' 代表用COM1发送,波特率9600,若不需要使用串口抄送服务请留空 -->
<add key="comPort" value="" />
<!--启用自定义消息过滤,启用后可去程序根目录 Scripts/engine/comPortFilter.js 调整过滤规则 -->
<add key="useComPortFilter" value="true" />
</appSettings>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.2" newVersion="4.0.1.2" />
</dependentAssembly>
</assemblyBinding>
</runtime>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2" />
</startup>
<system.web>
<membership defaultProvider="ClientAuthenticationMembershipProvider">
<providers>
<add name="ClientAuthenticationMembershipProvider" type="System.Web.ClientServices.Providers.ClientFormsAuthenticationMembershipProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="" />
</providers>
</membership>
<roleManager defaultProvider="ClientRoleProvider" enabled="true">
<providers>
<add name="ClientRoleProvider" type="System.Web.ClientServices.Providers.ClientRoleProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="" cacheTimeout="86400" />
</providers>
</roleManager>
</system.web>
</configuration>appsettings.json格式,如下
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*"
}
然后在这读取替换成读取appsettings.json
public AppSetting()
{
try
{
ProcessFilter = AppSettings["processFilter"].Trim().Split(',');
//string processFilter = System.Configuration.ConfigurationManager.AppSettings["processFilter"];
WsProt = int.Parse(AppSettings["wsListenPort"]);
PrintBarrage = AppSettings["printBarrage"].ToLower() == "true";
ProxyPort = int.Parse(AppSettings["proxyPort"]);
PrintFilter = Enum.GetValues(typeof(PackMsgType)).Cast<int>().Where(w => w > 0).ToArray();
PushFilter = Enum.GetValues(typeof(PackMsgType)).Cast<int>().Where(w => w > 0).ToArray();
LogFilter = Enum.GetValues(typeof(PackMsgType)).Cast<int>().Where(w => w > 0).ToArray();
FilterHostName = bool.Parse(AppSettings["filterHostName"].Trim());
HostNameFilter = AppSettings["hostNameFilter"].Trim().Split(',').Where(w => !string.IsNullOrWhiteSpace(w)).ToArray();
UsedProxy = bool.Parse(AppSettings["usedProxy"].Trim());
ListenAny = bool.Parse(AppSettings["listenAny"].Trim());
UpstreamProxy = AppSettings["upstreamProxy"].Trim();
HideConsole = bool.Parse(AppSettings["hideConsole"].Trim());
BarrageLog = bool.Parse(AppSettings["barrageFileLog"].Trim());
ShowWindow = bool.Parse(AppSettings["showWindow"].Trim());
AutoPause = bool.Parse(AppSettings["autoPause"].Trim());
ForcePolling = bool.Parse(AppSettings["forcePolling"].Trim());
PollingInterval = int.Parse(AppSettings["pollingInterval"].Trim());
DisableLivePageScriptCache = bool.Parse(AppSettings["disableLivePageScriptCache"].Trim());
WebRoomIds = AppSettings["webRoomIds"].Trim().Split(',').Where(w => !string.IsNullOrWhiteSpace(w)).ToArray();
ConfigComPort();
ConfigFilter();
}
catch (Exception ex)
{
Logger.PrintColor("配置文件读取失败,请检查配置文件是否正确");
throw ex;
}
}
升级后 有些不兼容 比如app.config 已经不能正常读取,需要重新构建代码
private readonly string _configFilePath = "app.config"; // Replace with your actual file path
private static readonly AppSetting ins = new AppSetting();
public static AppSetting Current { get { return ins; } }
public AppSetting()
{
try
{
var xmlDoc = new XmlDocument();
xmlDoc.Load(_configFilePath);
XmlNodeList appSettingsNodes = xmlDoc.SelectNodes("/configuration/appSettings/add");
if (appSettingsNodes != null)
{
foreach (XmlNode node in appSettingsNodes)
{
string key = node.Attributes["key"].Value;
string value = node.Attributes["value"].Value;
// Process each key-value pair according to your needs
// Process each key-value pair according to your needs
switch (key)
{
case "processFilter":
ProcessFilter = value.Trim().Split(',');
break;
case "wsListenPort":
WsProt = int.Parse(value.Trim());
break;
case "printBarrage":
PrintBarrage = bool.Parse(value.Trim().ToLower());
break;
case "proxyPort":
ProxyPort = int.Parse(value.Trim());
break;
case "printFilter":
PrintFilter = Enum.GetValues(typeof(PackMsgType)).Cast<int>().Where(w => w > 0).ToArray();
break;
case "pushFilter":
PushFilter = Enum.GetValues(typeof(PackMsgType)).Cast<int>().Where(w => w > 0).ToArray();
break;
case "logFilter":
LogFilter = Enum.GetValues(typeof(PackMsgType)).Cast<int>().Where(w => w > 0).ToArray();
break;
case "filterHostName":
FilterHostName = bool.Parse(value.Trim());
break;
case "hostNameFilter":
HostNameFilter = value.Trim().Split(',').Where(w => !string.IsNullOrWhiteSpace(w)).ToArray();
break;
case "usedProxy":
UsedProxy = bool.Parse(value.Trim());
break;
case "listenAny":
ListenAny = bool.Parse(value.Trim());
break;
case "upstreamProxy":
UpstreamProxy = value.Trim();
break;
case "hideConsole":
HideConsole = bool.Parse(value.Trim());
break;
case "barrageFileLog":
BarrageLog = bool.Parse(value.Trim());
break;
case "showWindow":
ShowWindow = bool.Parse(value.Trim());
break;
case "autoPause":
AutoPause = bool.Parse(value.Trim());
break;
case "forcePolling":
ForcePolling = bool.Parse(value.Trim());
break;
case "pollingInterval":
PollingInterval = int.Parse(value.Trim());
break;
case "disableLivePageScriptCache":
DisableLivePageScriptCache = bool.Parse(value.Trim());
break;
case "webRoomIds":
WebRoomIds = value.Trim().Split(',').Where(w => !string.IsNullOrWhiteSpace(w)).ToArray();
break;
default:
// Handle unrecognized keys if needed
break;
}
}
}
// ProcessFilter = AppSettings["processFilter"].Trim().Split(',');
//WsProt = int.Parse(AppSettings["wsListenPort"]);
//PrintBarrage = AppSettings["printBarrage"].ToLower() == "true";
//ProxyPort = int.Parse(AppSettings["proxyPort"]);
//PrintFilter = Enum.GetValues(typeof(PackMsgType)).Cast<int>().Where(w => w > 0).ToArray();
//PushFilter = Enum.GetValues(typeof(PackMsgType)).Cast<int>().Where(w => w > 0).ToArray();
//LogFilter = Enum.GetValues(typeof(PackMsgType)).Cast<int>().Where(w => w > 0).ToArray();
//FilterHostName = bool.Parse(AppSettings["filterHostName"].Trim());
//HostNameFilter = AppSettings["hostNameFilter"].Trim().Split(',').Where(w => !string.IsNullOrWhiteSpace(w)).ToArray();
//UsedProxy = bool.Parse(AppSettings["usedProxy"].Trim());
//ListenAny = bool.Parse(AppSettings["listenAny"].Trim());
//UpstreamProxy = AppSettings["upstreamProxy"].Trim();
//HideConsole = bool.Parse(AppSettings["hideConsole"].Trim());
//BarrageLog = bool.Parse(AppSettings["barrageFileLog"].Trim());
//ShowWindow = bool.Parse(AppSettings["showWindow"].Trim());
//AutoPause = bool.Parse(AppSettings["autoPause"].Trim());
//ForcePolling = bool.Parse(AppSettings["forcePolling"].Trim());
//PollingInterval = int.Parse(AppSettings["pollingInterval"].Trim());
//DisableLivePageScriptCache = bool.Parse(AppSettings["disableLivePageScriptCache"].Trim());
//WebRoomIds = AppSettings["webRoomIds"].Trim().Split(',').Where(w => !string.IsNullOrWhiteSpace(w)).ToArray();