前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >WPF项目从.Net Framework迁移到.Net6

WPF项目从.Net Framework迁移到.Net6

作者头像
码客说
发布2022-09-28 19:28:46
7500
发布2022-09-28 19:28:46
举报
文章被收录于专栏:码客码客

前言

先决条件

.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)\DLL\libwebp.dll $(TargetDir)

程序不包含适合于入口点

报错

程序不包含适合于入口点的静态 “Main” 方法

解决方式

生成操作选择 应用程序定义

自定义工具输入 MSBuild:Compile

image-20220902180537990
image-20220902180537990

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

代码语言:javascript
复制
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中,

代码语言:javascript
复制
<PropertyGroup>
  <SatelliteResourceLanguages>zh-Hans</SatelliteResourceLanguages>
</PropertyGroup>
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-09-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 问题处理
    • 打印不显示
      • 依赖不兼容
        • 程序不包含适合于入口点
          • appSettings读写
            • .net framework的读写方式
            • .net6读取appsettings.json
            • XML方式读写
            • JSON方式读写
        • 输出精简
          • 多运行时精简
            • 多语言精简
            相关产品与服务
            文件存储
            文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档