取消

When WPF Commands update their CanExecute states?

When writing Command="{Binding WalterlvCommand}" into your XAML code and your button or other controls can automatically execute command and updating the command states, such as enabling or disabli...

程序员与英语:即时聊天中的英语缩写 lol / lmao / idk

经常混迹各大英文开发者社区的你,是否会遇到一些奇怪的英文缩写呢?本文整理一些即时聊天中常用的缩写。 英语部分 lol Laughing out Loud Laugh out Loud Lots of Laughs Laugh Online 缩写可以说来源于上面那些,似乎意思是“好好笑啊”。然而事实可能并不是这样…… 不知是否用“呵呵”,“Interestin...

C#/.NET 如何获取一个异常(Exception)的关键特征,用来判断两个异常是否表示同一个异常

在 .NET / C# 程序中出现异常是很常见的事情,程序出现异常后记录日志或者收集到统一的地方可以便于分析程序中各种各样此前未知的问题。但是,有些异常表示的是同一个异常,只是因为参数不同、状态不同、用户的语言环境不同就分开成多个异常的话,分析起来会有些麻烦。 本文将提供一个方法,将异常的关键信息提取出来,这样可以比较多次抛出的不同的异常实例是否表示的是同一个异常。 Except...

在 CVTE 和广州 .NET 微软技术俱乐部共同举办的 12月8日 广州微软技术沙龙活动

2018 年 12 月 8 日,在 CVTE·视源股份,在广州黄埔区云埔四路 6 号,我们举办了广州微软技术沙龙。现场参与人数 136 人(不含工作人员),线上参与人员 400+ 人。活动完全免费。 这是 CVTE·视源股份 和 广州 .NET 微软技术俱乐部 共同举办的一次技术沙龙,我(吕毅)和林德熙,作为微软 MVP,同时是 CVTE 的一员,同时还是广州 .NET 微软技术俱乐部的一...

C#/.NET 如何在第一次机会异常 FirstChanceException 中获取比较完整的异常堆栈

在 FirstChangeException 事件中,我们通常只能拿到异常堆栈的第一帧,这对于我们捕捉到异常是好的,但对分析第一次机会异常可能并不利。 本文介绍如何在 FirstChangeException 事件中拿到比较完整的异常堆栈,而不只是第一帧。 第一次机会异常 .NET 程序代码中的任何一段代码,在刚刚抛出异常,还没有被任何处理的那一时刻,AppDomain 的实例...

流畅设计 Fluent Design System 中的光照效果 RevealBrush,WPF 也能模拟实现啦!

UWP 才能使用的流畅设计效果好惊艳,写新的 UWP 程序可以做出更漂亮的 UI 啦!然而古老的 WPF 项目也想解解馋怎么办? 于是我动手实现了一个! 迫不及待看效果 ▲ 是不是很像 UWP 中的 RevealBorderBrush? 不止是效果像,连 XAML 写法也像: <Border BorderThickness="1" Margin="50,34,526...

使用 Microsoft.Net.Compilers 在旧版本的 Visual Studio 2013/2015/2017 中开启新的 C# 7.x 和 C# 8 语法

新版本的 C# 特性需要新版本的 Visual Studio 的支持。不过,如果你不介意修改项目的话,你也能在低版本的 Visual Studio 中获得高版本的 C# 语言支持了。 而使用 Microsoft.Net.Compilers 这款 NuGet 包就可以做到。 不同 Visual Studio 原生支持的 C# 版本 Visual Studio 每一次的重大发布都带...

制作一个极简的 .NET 客户端应用自安装或自更新程序

本文主要说的是 .NET 客户端应用,可以是只能在 Windows 端运行的基于 .NET Framework 或基于 .NET Core 的 WPF / Windows Forms 应用,也可以是其他基于 .NET Core 的跨平台应用。但是不是那些更新权限受到严格控制的 UWP / iOS / Android 应用。 本文将编写一个简单的程序,这个程序初次运行的时候会安装自己,如果已...

WPF 同一窗口内的多线程/多进程 UI(使用 SetParent 嵌入另一个窗口)

WPF 的 UI 逻辑只在同一个线程中,这是学习 WPF 开发中大家几乎都会学习到的经验。如果希望做不同线程的 UI,大家也会想到使用另一个窗口来实现,让每个窗口拥有自己的 UI 线程。然而,就不能让同一个窗口内部使用多个 UI 线程吗? 阅读本文将收获一份 Win32 函数 SetParent 及相关函数的使用方法。 WPF 同一个窗口中跨线程访问 UI 有多种方法: 使用...

应用程序清单 Manifest 中各种 UAC 权限级别的含义和效果

如果你的程序对 Windows 运行权限有要求,那么需要设置应用程序清单。本文介绍如何添加应用程序清单,并解释其中各项 UAC 权限设置的实际效果。 阅读本文之前,你可能需要了解如何创建应用程序清单文件。阅读我的另一篇博客可以了解: 如何创建应用程序清单文件 App.Manifest,如何创建不带清单的应用程序 - 吕毅 各种不同的 UAC 清单选项 从默认生成的应用...

Windows 系统上使用任务管理器查看进程的各项属性(命令行、DPI、管理员权限等)

Windows 系统上的任务管理器进化到 Windows 10 的 1809 版本后,又新增了几项可以查看的进程属性。 本文介绍可以使用任务管理器查看的各种进程属性。 如何查看进程的各种属性 在任务栏上右键,选择“任务管理器”;或者按下 Ctrl + Shift + Esc 可以打开任务管理器。如果你的电脑死掉了,也可以按 Ctrl + Alt + Del 再选择任务管理器打开...

如何创建一个基于 .NET Core 3 的 WPF 项目

在 Connect(); 2018 大会上,微软发布了 .NET Core 3 Preview,以及基于 .NET Core 3 的 WPF;同时还发布了 Visual Studio 2019 预览版。不过 Visual Studio 2019 的预览版中并没有携带 WPF on .NET Core 3 的模板,于是新建项目的时候并不能快速创建一个基于 .NET Core 3 的 WPF 项...

Windows 的 UAC 设置中的通知等级实际上只有两个档而已

Windows 系统中的 UAC 设置界面有四种不同的选项可以选,但实际上真正有意义的只有两个选项。 本文将介绍 UAC 这四个档设置的区别,帮助你合理的设置你的电脑。 UAC 设置界面 在 Windows 10 任务栏的搜索框中输入 uac 可以直接打开 UAC 设置界面。 下图是“用户账户控制设置”界面,想必小伙伴们应该已经很熟悉了。它有四个档: 始终通知 当...

Windows 中的 UAC 用户账户控制

阅读本文,你可以初步了解 Windows 上的 UAC 用户账户控制机制。本文不会涉及到 UAC 的底层实现原理和安全边界问题。 用户账户 在 Windows 中有多种不同的账户: SYSTEM Administrators 用户组 Administrator 管理员账户 Users 用户组 ...

Windows 下使用 runas 命令以指定的权限启动一个进程(非管理员、管理员)

在默认情况下,Windows 系统中启动一个进程会继承父进程的令牌。如果父进程是管理员权限,那么子进程就是管理员权限;如果父进程是标准用户权限,那么子进程也是标准用户权限。 我们也知道,可以使用一些方法为自己的应用程序提权。但是有没有方法可以任意指定一个权限然后运行呢?本文将介绍 Windows 下指定权限运行的做法。 runas 命令 runas 是 Windows 系统上自...

启用 Windows 审核模式(Audit Mode),以 Administrator 账户来设置电脑的开箱体验

在你刚刚安装完 Windows,在 Windows 开箱体验输入以创建你的用户账户之前,你可以按下 Ctrl + Shift + F3 来进入审核模式。 本文将介绍审核模式。 OOBE OOBE,Out-of-Box Experience,开箱体验。对于 Windows 系统来说,就是当你买下电脑回来,兴奋地打开电脑开机后第一个看到的界面。 具体来说,就是设置你的账号以及各种...

如何创建应用程序清单文件 App.Manifest,如何创建不带清单的应用程序

如果你的程序对 Windows 运行权限有要求,那么需要设置应用程序清单。本文介绍如何添加应用程序清单,并解释其中各项权限设置的实际效果。 嵌入带默认设置的清单 对于 WPF 和 Windows Forms 程序,如果你什么都不做,那么就已经嵌入了一个带有默认设置的清单。 下图可以在 Visual Studio 中的项目上右键属性插件。 新建一个自定义的清单文件 在项目...

在有 UI 线程参与的同步锁(如 AutoResetEvent)内部使用 await 可能导致死锁

AutoResetEvent、ManualResetEvent、Monitor、lock 等等这些用来做同步的类,如果在异步上下文(await)中使用,需要非常谨慎。 本文将说一个在同步上下文中非常常见的一种用法,换成异步上下文中会产生死锁的问题。 一段正常的同步上下文的代码 先看看一段非常简单的代码: private void OnLoaded(object sender,...

.NET 中小心嵌套等待的 Task,它可能会耗尽你线程池的现有资源,出现类似死锁的情况

一个简单的 Task 不会消耗多少时间,但如果你不合适地将 Task 转为同步等待,那么也可能很快耗尽线程池的所有资源,出现类似死锁的情况。 本文将以一个最简单的例子说明如何出现以及避免这样的问题。 耗时的 Task.Run 谁都不会认为 Task.Run(() => 1) 这个异步任务执行会消耗多少时间。 但实际上,如果你的代码写得不清真,它真的能消耗大量的时间,这种...

在编写异步方法时,使用 ConfigureAwait(false) 避免使用者死锁

我在 使用 Task.Wait()?立刻死锁(deadlock) 一文中站在类库使用者的角度看 async/await 代码的死锁问题;而本文将站在类库设计者的角度来看死锁问题。 阅读本文,我们将知道如何编写类库代码,来尽可能避免类库使用者出现那篇博客中描述的死锁问题。 可能死锁的代码 现在,我们是类库设计者的身份,我们试图编写一个 RunAsync 方法用以异步执行某些操作。...

将 async/await 异步代码转换为安全的不会死锁的同步代码(使用 PushFrame)

在 async/await 异步模型(即 TAP Task-based Asynchronous Pattern)出现以前,有大量的同步代码存在于代码库中,以至于这些代码全部迁移到 async/await 可能有些困难。这里就免不了将一部分异步代码修改为同步代码。然而传统的迁移方式存在或多或少的问题。本文将总结这些传统方法的坑,并推出一款异步转同步的新方法,解决传统方法的这些坑。 ...

使用 Task.Wait()?立刻死锁(deadlock)

最近读到一篇异步转同步的文章,发现其中没有考虑到异步转同步过程中发生的死锁问题,所以特地在本文说说异步转同步过程中的死锁问题。 文章作者 林德熙 已经修复了描述: win10 uwp 异步转同步 什么情况下会产生死锁? 调用 Task.Wait() 或者 Task.Result 立刻产生死锁的充分条件: 调用 Wait() 或 Result 的代码位于 UI 线程...

不要使用 Dispatcher.Invoke,因为它可能在你的延迟初始化 Lazy 中导致死锁

WPF 中为了 UI 的跨线程访问,提供了 Dispatcher 线程模型。其 Invoke 方法,无论在哪个线程调用,都可以让传入的方法回到 UI 线程。 然而,如果你在 Lazy 上下文中使用了 `Invoke`,那么当这个 `Lazy` 跨线程并发时,极有可能导致死锁。本文将具体说说这个例子。 一段死锁的代码 请先看一段非常简单的 WPF 代码: private Laz...

C#/.NET 如何结束掉一个进程

本文介绍如何结束掉一个进程。 结束掉特定名字的进程 ProcessInfo 中有 Kill 实例方法可以调用,也就是说如果我们能够拿到一个进程的信息,并且对这个进程拥有访问权限,那么我们就能够结束掉它。 使用 Process.GetProcessesByName(processName) 可以按照名字拿到进程信息。于是我们可以使用这个方法杀掉具有特定名称的进程。 privat...

让你的 VSCode 具备调试 C# 语言 .NET Core 程序的能力

如果你是开发个人项目,那就直接用 Visual Studio Community 版本吧,对个人免费,对小团体免费,不需要这么折腾。 如果你是 Mac / Linux 用户,不想用 Visual Studio for Mac 版;或者不想用 Visual Studio for Windows 版那么重磅的 IDE 来开发简单的 .NET Core 程序;或者你就是想像我这么折腾,那我们就开...

手工编辑 tasks.json 和 launch.json,让你的 VSCode 具备调试 .NET Core 程序的能力

如果 C# for Visual Studio Code 没有办法自动为你生成正确的 tasks.json 和 launch.json 文件,那么可以考虑阅读本文手工创建他们。 前期准备 你需要安装 .NET Core Sdk、Visual Studio Code 和 C# for Visual Studio Code,然后打开一个 .NET Core 的项目。如果你没有准备,请...

自然码的形码

使用拼音/双拼输入法,如果你的打字速度还需要继续提升,那么就不应该再不断地看着候选框打字了。使用双拼形码可以规避相当多字词的选字。 本文整理自然码的形码,然后附带一张我自己制作的自然码形码的键盘图。 输入法的选择 目前各种双拼输入法中,辅码最接近自然码形码的,是手心输入法。所以我选用了手心输入法并重新训练了词库。 这款输入法与 360 有点关系,不过很不 360。这让我有点犹...

在 Visual Studio Code 中添加自定义的代码片段

无论是那个编辑器,如果能够添加一些自定义代码片段,能够大大提升代码的输入效率。 本文介绍如何在 Visual Studio Code 中添加自定义代码片段。 Visual Studio Code 的代码片段设置 你可以在 Visual Studio Code 的菜单中找到代码片段的设置入口,在 File -> Preferences -> User Snippets...

解决 mklink 使用中的各种坑(硬链接,软链接/符号链接,目录链接)

通过 mklink 命令可以创建文件或文件夹的链接,而这种链接跟快捷方式是不一样的。然而我们还可能会遇到其使用过程中的一些坑,本文将整理这些坑并提供解决方法。 0x00 背景介绍:mklink mklink 可以像创建快捷方式一样建立文件或文件夹的链接,但不同于快捷方式的是,mklink 创建的链接绝大多数程序都不会认为那是一个链接,而是一个实实在在的文件或文件夹。 例如,为 ...

.NET 中的轻量级线程安全

对线程安全有要求的代码中,通常会使用锁(lock)。自 .NET 诞生以来就有锁,然而从 .NET Framework 4.0 开始,又诞生了 6 个轻量级的线程安全方案:SpinLock, SpinWait, CountdownEvent, SemaphoreSlim, ManualResetEventSlim, Barrier。 类型 SpinLock, SpinWait Sp...