分类 DotNet 下的文章

背景

写了个wpf程序,需要在服务器上运行一下,开发的时候使用的net core 3.1,服务器上未安装,安装需要重启电脑,明显不可以。

解决

将wpf打包成自宿主的程序,包含所有运行环境一块打包出来。

打包方法

在项目目录下执行如下命令:

dotnet publish -r win-x64 -c Release --self-contained

这里配置了程序在Windows 64位下运行。

提示如下表示已经生成完成了,直接拷贝

PS F:\test> dotnet publish -r win-x64 -c Release --self-contained
用于 .NET 的 Microsoft (R) 生成引擎版本 17.0.0-preview-21501-01+bbcce1dff
版权所有(C) Microsoft Corporation。保留所有权利。

  正在确定要还原的项目…
  所有项目均是最新的,无法还原。
  你正在使用 .NET 的预览版。请查看 https://aka.ms/dotnet-core-preview
  test -> F:\test\bin\Release\netcoreapp3.1\win-x64\test.dll
  test -> F:\test\bin\Release\netcoreapp3.1\win-x64\publish\
PS F:\test>

拷贝到服务器上,双击打开直接使用即可,无需再安装运行时。

背景

MAUI版本:preview4
通过VS2019 preview创建了一个MAUI应用程序,设置了MauiApp1.WinUI3为启动项目,在启动时,提示如下错误

System.Reflection.TargetInvocationException:“Exception has been thrown by the target of an invocation.”

COMException: 没有注册类 (0x80040154 (REGDB_E_CLASSNOTREG))

解决

参考https://github.com/dotnet/maui/issues/1127
排查方法:

  1. 安装VS Preview 16.11.0 Preview 1.0。
  2. 安装MAUI Check工具,并通过maui-check命令,检查MAUI环境是否完整且正确。
  3. VS下新建.NET MAUI App项目。
  4. 设置WinUI3 (Package)项目为启动项。
  5. 以“本地计算机”为目标,运行项目。

背景

随着.Net 6 Preview 4的发布,MAUI preview4也随着更新,为了抢先体验一把MAUI,按照https://devblogs.microsoft.com/dotnet/announcing-net-maui-preview-4/ 此说明进行测试。但在执行maui-check时,出现了窗口闪退的情况。如下:
maui-check闪退.gif

原因

使用命令提示符-管理员模式打开,重新执行maui-check,我们可看到具体的错误信息,

? Synchronizing configuration...
Error: The SSL connection could not be established, see inner exception.

如图所示:

maui-check错误.png

很明显,是因为网络问题导致的连接失败。

解决方案

开代理,启用系统代理后,重试可解决。
maui-check正常.png

背景

使用Dapper查询数据时,执行到以下代码是,提示错误。

await DbConnection.QueryAsync<MyDto>(sql);

错误信息为:

Error parsing column 0 (NAME=39fb9af0-7a6f-7b2a-26d6-4fe92a2798fc - Object)
System.Data.DataException: Error parsing column 0 (NAME=39fb9af0-7a6f-7b2a-26d6-4fe92a2798fc - Object)
 ---> System.InvalidCastException: Object must implement IConvertible.

但是调试拿到了sql语句,去Navicat下执行,完全没有问题。起初,百度找到了这篇文章,但发现我的问题并非文章中的原因造成的。

原因

该查询中,只查询了两个字段,其中一个为Char(36)类型,通过Dapper查询后转换为了string,本来char转换为string再正常不过。直到后来查询资料发现,Mysql中对Char(36)默认为Guid,但也就是说,你配置了字段类型为Char(36),它代表的意义就已经不是字符串了,转换需要单独处理。

解决

知道问题原因了,就好办了。只需要在查询是将其转换为字符串即可,或者设置转换的类型为Guid。

SELECT CAST(Uid AS CHAR) Name ...

或修改MyDto中的字段类型

...
public Guid Name { get; set; }
...

步骤

引入Volo.Abp.Emailing 包

并在模块中添加对应的依赖。

    [DependsOn(
        typeof(AbpEmailingModule)
   )]
    public class XXXXModule : AbpModule
    {

添加配置

在appsettings.json中添加如下代码:

"Settings": {
  "Abp.Mailing.Smtp.Host": "127.0.0.1",
  "Abp.Mailing.Smtp.Port": "25",
  "Abp.Mailing.Smtp.UserName": "",
  "Abp.Mailing.Smtp.Password": "",
  "Abp.Mailing.Smtp.Domain": "",
  "Abp.Mailing.Smtp.EnableSsl": "false",
  "Abp.Mailing.Smtp.UseDefaultCredentials": "true",
  "Abp.Mailing.DefaultFromAddress": "noreply@abp.io",
  "Abp.Mailing.DefaultFromDisplayName": "ABP application"
}

这里需要特别注意一下,其中的password项目,不可直接填写,abp要求必须对密码进行加密处理,如果你直接填写密码。在发送邮件时会抛出如下异常:

 The input data is not a complete block.
System.Security.Cryptography.CryptographicException: The input data is not a complete block.
   at Internal.Cryptography.UniversalCryptoDecryptor.UncheckedTransformFinalBlock(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount)
   at Internal.Cryptography.UniversalCryptoTransform.TransformFinalBlock(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount)
   at System.Security.Cryptography.CryptoStream.ReadAsyncCore(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken, Boolean useAsync)

参考官方文档,要么,使用ISettingManager 进行配置。如果使用appsettings.json进行配置,就需要自行加密后,填写密文。

这里说下第二种,如何进行加密呢?我们可自己下一段端代码,对密码进行加密,调试方式获取加密字符串后,再把这段代码删除即可。
代码如下_settingDefinitionManager和_settingEncryptionService注入即可,用完再删除就行。

private readonly ISettingEncryptionService _settingEncryptionService;
private readonly ISettingDefinitionManager _settingDefinitionManager;
public TestAppService(
    ISettingEncryptionService settingEncryptionService,
    ISettingDefinitionManager settingDefinitionManager)
{

    _settingEncryptionService = settingEncryptionService;
    _settingDefinitionManager = settingDefinitionManager;
}

public async Task EncryptPwd()
{

    var setting = _settingDefinitionManager.Get(EmailSettingNames.Smtp.Password);
    var psd = _settingEncryptionService.Encrypt(setting,"密码");
}

这样,得到了加密后的密码,配置上就可了。

使用

使用的时候,也是非常简单,直接依赖注入方式注入IEmailSender,然后执行SendAsync接口。

private readonly IEmailSender _emailSender;
public TestAppService(
    IEmailSender emailSender)
{
    _emailSender= emailSender;
}

public async Task SendTest()
{
    await _emailSender.SendAsync("123456789@qq.com",
        "测试",
        "正文内容.....");
}

当然,实际使用中,可能还会用到模板等内容,这里不再赘述,参考官方文档吧。