取消

WPF 的 Application.Current.Dispatcher 中,Dispatcher 属性一定不会为 null

在 WPF 程序中,可能会存在 Application.Current.Dispatcher.Xxx 这样的代码让一部分逻辑回到主 UI 线程。因为发现在调用这句代码的时候出现了 NullReferenceException,于是就有三位小伙伴告诉我说 Current 和 Dispatcher 属性都可能为 null。 然而实际上这里只可能 Current 为 null 而此上下文的 Di...

使用 SetParent 跨进程设置父子窗口时的一些问题(小心卡死)

在微软的官方文档中,说 SetParent 可以在进程内设置,也可以跨进程设置。当使用跨进程设置窗口的父子关系时,你需要注意本文提到的一些问题,避免踩坑。 跨进程设置 SetParent 关于 SetParent 函数设置窗口父子关系的文档可以看这个: SetParent function (winuser.h) - Microsoft Docs 在这篇文章的 DPI...

程序员可能会使用的各种命名规则

古老的程序员们有时会纠结命名问题,而现在,程序员们的命名已经开创了数个流派。本文整理了程序员们命名会使用到的各种流派,当然一些编程语言会同时使用数个流派。 PascalCase 有很多个名字,除了 PascalCase 还有 UpperCamelCase, BumpyCase。 所有单词直接连接,连接的每个单词的首字母大写。 WelcomeToReadWalterlvBlog...

System.InvalidOperationException:“BuildWindowCore 无法返回寄宿的子窗口句柄。”

当试图在 WPF 窗口中嵌套显示 Win32 子窗口的时候,你有可能出现错误:“BuildWindowCore 无法返回寄宿的子窗口句柄。”。 这是很典型的 Win32 错误,本文介绍如何修复此错误。 我们在 MainWindow 中嵌入一个其他的窗口来承载新的 WPF 控件。一般情况下我们当然不会这么去做,但是如果我们要跨越进程边界来完成 WPF 渲染内容的融合的时候,就需要嵌...

System.InvalidOperationException:“寄宿 HWND 必须是子窗口。”

当试图在 WPF 窗口中嵌套显示 Win32 子窗口的时候,你有可能出现错误:“System.InvalidOperationException:“寄宿 HWND 必须是子窗口。””。 这是很典型的 Win32 错误,本文介绍如何修复此错误。 一个最简的嵌入其他窗口的例子 我们在 MainWindow 中嵌入一个其他的窗口来承载新的 WPF 控件。一般情况下我们当然不会这么去做...

System.InvalidOperationException:“寄宿的 HWND 必须是指定父级的子窗口。”

当试图在 WPF 窗口中嵌套显示 Win32 子窗口的时候,你有可能出现错误:“寄宿的 HWND 必须是指定父级的子窗口。”。 这是很典型的 Win32 错误,本文介绍如何修复此错误。 我们在 MainWindow 中嵌入一个其他的窗口来承载新的 WPF 控件。一般情况下我们当然不会这么去做,但是如果我们要跨越进程边界来完成 WPF 渲染内容的融合的时候,就需要嵌入一个新的窗口了...

如何创建一个基于 MSBuild Task 的跨平台的 NuGet 工具包

MSBuild 的 Task 为我们扩展项目的编译过程提供了强大的扩展性,它使得我们可以用 C# 语言编写扩展;利用这种扩展性,我们可以为我们的项目定制一部分的编译细节。NuGet 为我们提供了一种自动导入 .props 和 .targets 的方法,同时还是一个 .NET 的包平台;我们可以利用 NuGet 发布我们的工具并自动启用这样的工具。 制作这样的一个跨平台 NuGet 工具,我...

如何创建一个基于命令行工具的跨平台的 NuGet 工具包

命令行可是跨进程通信的一种非常方便的手段呢,只需启动一个进程传入一些参数即可完成一些很复杂的任务。NuGet 为我们提供了一种自动导入 .props 和 .targets 的方法,同时还是一个 .NET 的包平台;我们可以利用 NuGet 发布我们的工具并自动启用这样的工具。 制作这样的一个跨平台 NuGet 工具,我们能够为安装此工具的项目提供自动的但定制化的编译细节——例如自动生成版本...

好的框架需要好的 API 设计 —— API 设计的六个原则

说到框架设计,打心底都会觉得很大很宽泛,而 API 设计是框架设计中的重要组成部分。相比于有很多大佬都认可的面向对象的六大原则、23 种常见的设计模式来说,API 设计确实缺少行业公认的原则或者说设计范式。 不过,没有公认不代表没有。无论是对外提供类库还是提供 url 形式的 API,为了使用者良好的使用体验,依然也是有可以借鉴和参考的经验的。 This post is writte...

通过 mklink 收集本地文件系统的所有 NuGet 包输出目录来快速调试公共组件代码

我们做的公共库可能通过 nuget.org 发布,也可能是自己搭建 NuGet 服务器。但是,如果某个包正在开发中,需要快速验证其是否解决掉一些诡异的 bug 的话,除了单元测试这种间接的测试方法,还可以在本地安装未发布的 NuGet 包的方法来快速调试。 本文介绍如何本地打包发布 NuGet 包,然后通过 mklink 收集所有的本地包达到快速调试的目的。 将本地文件夹作为 N...

使用 C# 中的 dynamic 关键字调用类型方法时可能遇到的各种问题

你可以使用 dynamic 来定义一个变量或者字段,随后你可以像弱类型语言一样调用这个实例的各种方法,就像你一开始就知道这个类型的所有属性和方法一样。 但是,使用不当又会遇到各种问题,本文收集使用过程中可能会遇到的各种问题,帮助你解决掉它们。 快速入门 dynamic 可以这么用: dynamic foo = GetSomeInstance(); foo.Run("欢迎访问吕...

设计一个 .NET 可用的弱引用集合(可用来做缓存池使用)

我们有弱引用 WeakReference<T> 可以用来保存可被垃圾回收的对象,也有可以保存键值对的 ConditionalWeakTable。 我们经常会考虑制作缓存池。虽然一般不推荐这么设计,但是你可以使用本文所述的方法和代码作为按垃圾回收缓存的缓存池的设计。 设计思路 既然现有 WeakReference<T> 和 ConditionalWeakT...

如何为非常不确定的行为(如并发)设计安全的 API,使用这些 API 时如何确保安全

.NET 中提供了一些线程安全的类型,如 ConcurrentDictionary<TKey, TValue>,它们的 API 设计与常规设计差异很大。如果你对此觉得奇怪,那么正好阅读本文。本文介绍为这些非常不确定的行为设计 API 时应该考虑的原则,了解这些原则之后你会体会到为什么会有这些 API 设计上的差异,然后指导你设计新的类型。 不确定性 像并发集合一样,如...

通过 AppSwitch 禁用 WPF 内置的触摸让 WPF 程序可以处理 Windows 触摸消息

WPF 框架自己实现了一套触摸机制,但同一窗口只能支持一套触摸机制,于是这会禁用系统的触摸消息(WM_TOUCH)。这能够很大程度提升 WPF 程序的触摸响应速度,但是很多时候又会产生一些 Bug。 如果你有需要,可以考虑禁用 WPF 的内置的实时触摸(RealTimeStylus)。本文介绍禁用方法,使用 AppSwitch,而不是网上广为流传的反射方法。 如何设置 AppSw...

Visual Studio 2019 中使用 .NET Core 预览版 SDK 的全局配置文件在哪里?

本文介绍在使用 Visual Studio 2019 或者命令行执行 MSBuild dotnet build 命令时,决定是否使用 .NET Core SDK 预览版的全局配置文件。 指定是否使用 .NET Core 预览版 SDK 的全局配置文件在: %LocalAppData%\Microsoft\VisualStudio\16.0_xxxxxxxx\sdk.txt ...

The partial same C# namespace may cause source code compatibility issue

You might just add some simple APIs in your library and you’ll not think that will break down your compatibility. But actually, it might, that is – the source-code compatibility. This post is wr...

使用基于 Roslyn 的 Microsoft.CodeAnalysis.PublicApiAnalyzers 来追踪项目的 API 改动,帮助保持库的 API 兼容性

做库的时候,需要一定程度上保持 API 的兼容性 第一步:安装 NuGet 包 首先打开你的库项目,或者如果你希望从零开始也可以直接新建一个项目。这里为了博客阅读的简单,我创建一个全新的项目来演示。 然后,为主要的库项目安装 NuGet 包: NuGet Gallery - Microsoft.CodeAnalysis.PublicApiAnalyzers ...

找出 .NET Core SDK 是否使用预览版的全局配置文件在哪里(探索篇)

你是否好奇 Visual Studio 2019 中的 .NET Core SDK 预览版开关是全局生效的,那个全局的配置在哪里呢? 本文将和你一起探索找到这个全局的配置文件。 使用 Process Monitor 探索 下载 Process Monitor Process Monitor 是微软极品工具箱的一部分,你可以在此页面下载: Process Monitor...

nuget.exe 还原解决方案 NuGet 包的时候出现错误:调用的目标发生了异常。Error parsing the nested project section in solution file.

我这里使用 Visual Studio 2019 能好好编译的一个项目,发现在另一个小伙伴那里却编译不通过,是在 NuGet 还原那里报告了错误: 调用的目标发生了异常。Error parsing the nested project section in solution file. 本文介绍如何解决这样的问题。 原因 此问题的原因可能有多种: 解决方案里面 P...

为 NuGet 指定检测的 MSBuild 路径或版本,解决 MSBuild auto-detection: using msbuild version 自动查找路径不合适的问题

使用 nuget restore 命令还原项目的 NuGet 包的时候,NuGet 会尝试自动检测计算机上已经安装的 MSBuild。不过,如果你同时安装了 Visual Studio 2017 和 Visual Studio 2019,那么 NuGet 有可能找到错误版本的 MSBuild。 本文介绍如何解决自动查找版本错误的问题。 问题 当我们敲下 nuget restor...

解决方案文件 sln 中的项目类型 GUID

Visual Studio 可以通过得知项目类型快速地为项目显示相应的图标、对应的功能等等。 本文整理已收集到的一些项目的 GUID,如果你把你的解决方案文件(sln)改坏了,那么可以修复一下。 8BB2217D-0F2D-49D1-97BC-3654ED321F3B ASP.NET 5 603C0E0B-DB56-11DC-BE95-000D561079B0 ASP.NE...

.NET/C# 使用 #if 和 Conditional 特性来按条件编译代码的不同原理和适用场景

有小伙伴看到我有时写了 #if 有时写了 [Conditional] 问我两个不是一样的吗,何必多此一举。然而实际上两者的编译处理是不同的,因此也有不同的应用场景。 于是我写到这篇文章当中。 条件编译符号和预处理符号 我们有时会使用 #if DEBUG 或者 [Conditional("DEBUG")] 来让我们的代码仅在特定的条件下编译。 而这里的 DEBUG 是什么呢? ...

如何为你的 Windows 应用程序关联 URL 协议,以便在浏览器中也能打开你的应用

移动程序关联 URL 是常态,桌面应用程序其实也早就支持关联 URL 以便在浏览器中打开。当我们的程序关联了一个 URL 协议之后,开发的网站上就可以通过这个 URL 与程序进行互操作,这很互联网。 对于 Windows 桌面应用来说,关联一个 URL 协议是通过修改注册表来实现的。本文介绍如何为你的应用关联一个 URL 协议。 URL 协议 一个常用的 URL 协议是这样子的...

软件界面中一些易混淆/易用错的界面文案,以及一些约定俗成的文案约定

经常有小伙伴跟我撕到底一些常用同音的词语应该使用哪个的问题。于是我将一些常用的软件界面中用错的文案整理出来,为自己和其他开发者提供我 已经整理的结论 和 可以溯源的资料。 词语 下面列举出来的一些词语,有的我写的是 “推荐”,指两者都是正确的,但更应该使用 “推荐” 中的词语;而有的我写的是 “正确”,指只有这一个才是正确的,而其他写法是错误的。 无论哪一种,都说明了理由和可溯...

The VisualBrush of WPF only refresh the visual but not the layout

Now we’ll talk about a behavior of WPF VisualBrush. Maybe it is a bug, but let’s view some details and determine whether it is or not. The reproduction code Let’s make a XAML layout to reprod...

WPF 的 VisualBrush 只刷新显示的视觉效果,不刷新布局范围

WPF 的 VisualBrush 可以帮助我们在一个控件中显示另一个控件的外观。这是非常妙的功能。 但是本文需要说其中的一个 Bug —— 如果使用 VisualBrush 显示另一个控件的外观,那么只会在其显示效果有改变的时候刷新,而不会在目标布局改变的时候刷新布局。 用于复现问题的代码 我们现在做一个可以用于验证此问题的布局。 在一个大的 Grid 容器中有一个 Gri...

WPF 很少人知道的科技

本文介绍不那么常见的 WPF 相关的知识。 在 C# 代码中创建 DataTemplate 大多数时候我们只需要在 XAML 中就可以实现我们想要的各种界面效果。这使得你可能已经不知道如何在 C# 代码中创建同样的内容。 比如在代码中创建 DataTemplate,主要会使用到 FrameworkElementFactory 类型。 可以参考: WPF 后台创建 Da...

如果不用 ReSharper,那么 Visual Studio 2019 能还原 ReSharper 多少功能呢?

本文只谈论 ReSharper 的那些常用功能中,Visual Studio 2019 能还原多少,主要提供给那些正在考虑不使用 ReSharper 插件的 Visual Studio 用户作为参考。毕竟 ReSharper 如此强大的功能是建立在每年缴纳不少的费用以及噩梦般占用 Visual Studio 性能的基础之上的。然而使用 Visual Studio 2019 社区版不搭配 Re...

Roslyn 入门:使用 Visual Studio 的语法可视化(Syntax Visualizer)窗格查看和了解代码的语法树

使用 Visual Studio 提供的 Syntax Visualizer,我们可以实时看到一个代码文件中的语法树。这对我们基于 Roslyn 编写静态分析和修改工具非常有帮助。本文将介绍如何安装它和使用它。 本文是 Roslyn 入门系列之一: Roslyn 入门:使用 Visual Studio 的语法可视化(Syntax Visualizer)窗格查看和了解代码的语法树...

如何安装和准备 Visual Studio 扩展/插件开发环境

因为很多涉及到 Visual Studio 插件开发相关的文章/博客需要以安装 Visual Studio 插件开发环境为基础,所以本文介绍如何安装 Visual Studio 插件开发环境,以简化那些博客中的内容。 启动 Visual Studio 安装程序 请在开始菜单中找到或者搜索 Visual Studio Installer,然后启动它: 安装 Visual Stud...