取消

WPF 中如何创建忽略 DPI 属性的图片

WPF 框架设计为与 DPI 无关,但你依然可能遇到 DPI 问题。尤其是 Image 控件显示的图片会根据图片 EXIF 中的 DPI 信息和屏幕 DPI 自动缩放图片。对于 UI 用图来说这是好事,但对于软件用户随便插入的图片来说就不是了——用户传入的图片可能是各种各样不统一的 DPI。因此这种 DPI 我们应该忽略。 解决方法 直接设置 Image 控件的大小是一个不错的方...

为什么不应该公开用来同步的加锁对象?为什么不应该 lock(this)/lock(string) 或者 lock 任何非私有对象?

如果你编写线程安全代码时为了省事儿直接 lock(this),或者早已听说不应该 lock(this),只是不知道原因,那么阅读本文可以帮助你了解原因。 原因 不应该 lock(this) 是因为你永远不知道别人会如何使用你的对象,永远不知道别人会在哪里加锁。于是稍不注意就可能死锁! 实例 看看下面的两段代码。 第一段是定义好的一个类,其中某个方法为了线程安全加了锁,但加锁...

如何在旧版本的 .NET Core / Framework 中使用 C# 8 的异步流(IAsyncDisposable / IAsyncEnumerable / IAsyncEnumerator)

C# 8.0 为我们带来了异步流,可以使用 async foreach,不过使用此语法需要 IAsyncEnumerable / IAsyncEnumerator 类型。本文介绍如何在旧版本的 .NET Framework 和旧版本的 .NET Core 中获得此类型。 异步流所需版本 异步流需要 .NET Core 3.0 及以上版本才能直接支持。而如果是 .NET Frame...

.NET/C# 解压 Zip 文件时出现异常:System.IO.InvalidDataException: 找不到中央目录结尾记录。

在解压 Zip 文件时出现异常:System.IO.InvalidDataException: 找不到中央目录结尾记录。。 其原因是所解压的文件并非 zip 文件。 异常 在解压 Zip 文件时出现异常: System.IO.InvalidDataException: 找不到中央目录结尾记录。 在 System.IO.Compression.ZipArchive.Rea...

Windows 系统文件资源管理器的命令行参数(如何降权打开程序,如何选择文件)

大多数用户还是习惯使用 Windows 自带的文件资源管理器来管理文件,于是我们可以利用它的命令行参数来帮助我们做一些与之相关的交互。 本文会以实际的例子来说明如何使用 explorer.exe 的命令行参数。 打开文件 在命令行中输入 explorer D:\Services\blog.walterlv.com\test.txt 即可打开 test.txt 文件。不过,这个时...

如何在 MSBuild 中正确使用 % 来引用每一个项(Item)中的元数据

MSBuild 中写在 <ItemGroup /> 中的每一项是一个 Item,Item 除了可以使用 Include/Update/Remove 来增删之外,还可以定义其他的元数据(Metadata)。 使用 % 可以引用 Item 的元数据,本文将介绍如何正确使用 % 来引用每一个项中的元数据。 定义 Item 的元数据 就像下面这样,当引用一个 NuGet 包...

在 MSBuild 编译过程中操作文件和文件夹(检查存在/创建文件夹/读写文件/移动文件/复制文件/删除文件夹)

本文整理 MSBuild 在编译过程中对文件和文件夹处理的各种自带的编译任务(Task)。 Exists 检查文件存在 使用 Exists 可以判断一个文件或者文件夹是否存在。注意无论是文件还是文件夹,只要给定的路径存在就返回 true。可以作为 MSBuild 属性、项和编译任务的执行条件。 <PropertyGroup Condition=" Exists( '$(M...

如何在 .NET/C# 代码中安全地结束掉一个控制台应用程序?通过发送 Ctrl+C 信号来结束

我的电脑上每天会跑一大堆控制台程序,于是管理这些程序的运行就成了一个问题。或者说你可能也在考虑启动一个控制台程序来完成某些特定的任务。 如果我们需要结束掉这个控制台程序怎么做呢?直接杀进程吗?这样很容易出问题。我正在使用的一个控制台程序会写文件,如果直接杀进程可能导致数据没能写入到文件。所以本文介绍如何使用 .NET/C# 代码向控制台程序发送 Ctrl+C 来安全地结束掉程序。 ...

如何将一个 .NET 对象序列化为 HTTP GET 的请求字符串

HTTP GET 请求时携带的参数直接在 URL 中,形式如 ?key1=value&key2=value&key3=value。如果是 POST 请求时,我们可以使用一些库序列化为 json 格式作为 BODY 发送,那么 GET 请求呢?有可以直接将其序列化为 HTTP GET 请求的 query 字符串的吗? HTTP GET 请求 一个典型的 HTTP G...

屏幕边缘上有趣的 1 个像素,看不见、摸不到

如果你的屏幕分辨率是 1920×1080,那么一个全屏的窗口程序尺寸是多少呢?想都不用想,是 1920×1080。 那么输入设备输入的坐标是多少呢?是 X∈[0, 1919] ?还是 X∈[1, 1920] ?还是 X∈[0, 1920] ? 鼠标输入与触摸输入 一个有趣的问题,因为 1920×1080 分辨率的屏幕,其横向只有 1920 个像素,也就是说如果需要区分一个像素,...

使用 MSBuild Target 复制文件的时候如何保持文件夹结构不变

使用 MSBuild 中的 Copy 这个编译目标可以在 .NET 项目编译期间复制一些文件。不过使用默认的参数复制的时候文件夹结构会丢失,所有的文件会保留在同一级文件夹下。 那么如何在复制文件的时候保持文件夹结构与原文件夹结构一样呢? Copy 下面是一个典型的使用 MSBuild 在编译期间复制文件的一个编译目标。 <Target Name="_WalterlvCo...

使用正则表达式尽可能准确匹配域名/网址

你可能需要准确地知道一段字符串是否是域名/网址/URL。虽然可以使用 .、/ 这些来模糊匹配,但会造成误判。 实际上单纯使用正则表达式来精确匹配也是非常复杂的,通过代码来判断会简单很多。不过本文依然从域名的定义出发来尽可能匹配一段字符串是否是域名或者网址,在要求不怎么高的场合,使用本文的正则表达式写的代码会比较简单。 网址 网址实际上是 URL(统一资源定位符),它是由协议、主...

C# 8.0 的可空引用类型,不止是加个问号哦!你还有很多种不同的可空玩法

C# 8.0 引入了可空引用类型,你可以通过 ? 为字段、属性、方法参数、返回值等添加是否可为 null 的特性。 但是如果你真的在把你原有的旧项目迁移到可空类型的时候,你就会发现情况远比你想象当中复杂,因为你写的代码可能只在部分情况下可空,部分情况下不可空;或者传入空时才可为空,传入非空时则不可为空。 C# 8.0 可空特性 在开始迁移你的项目之前,你可能需要了解如何开启项目...

一个简单的方法:截取子类名称中不包含基类后缀的部分

基类是 MenuItem,子类是 WalterlvMenuItem、FooMenuItem。基类是 Configuration,子类是 WalterlvConfiguration、ExtensionConfiguration。在代码中,我们可能会为了能够一眼看清类之间的继承(从属)关系而在子类名称后缀中带上基类的名称。但是由于这种情况下的基类不参与实际的业务,所以对外(文件/网络)的名称通常...

可集成到文件管理器,一句 PowerShell 脚本发布某个版本的所有 NuGet 包

要发布 NuGet 包,只需要执行命令 nuget push xxx.nupkg 即可,或者去 nuget.org 点鼠标上传。 不过,如果你有很多的 NuGet 包并且经常需要推送的话,也可以集成到 Directory Opus 或者 Total Commander 中。 NuGet 推送命令 NuGet 推送命令可直接在微软官方文档中阅读到: NuGet CLI p...

配置 legacyUnhandledExceptionPolicy 防止后台线程抛出的异常让程序崩溃退出

如果你的程序抛了异常,你是怎么处理的呢?等待程序崩溃退出?还是进行补救? 如果是做 UI 开发,很容易就找到 Dispatcher.UnhandledException 事件,然后在事件中进行补救。如果补救成功,可以设置 e.Handled = true 来阻止异常继续让程序崩溃退出。但是,如果是后台线程抛出了异常呢?并没有 Dispatcher 可以用。所以我们就束手就擒让程序自己退出吗...

WPF 程序如何跨窗口/跨进程设置控件焦点

WPF 程序提供了 Focus 方法和 TraversalRequest 来在 WPF 焦点范围内转移焦点。但如果 WPF 窗口中嵌入了其他框架的 UI(比如另一个子窗口),那么就需要使用其他的方法来设置焦点了。 一个粗略的设置方法是,使用 Win32 API: SetFocus(hwnd); 传入的是要设置焦点的窗口的句柄。 参考资料 winapi - Win32...

PowerShell 的命令行启动参数(可用于执行命令、传参或进行环境配置)

有一些程序不支持被直接启动,而要求通过命令行启动。这个时候,你就需要使用 PowerShell 或者 PowerShell Core 来启动这样的程序。我们都知道如何在命令行或各种终端中启动一个程序,但是当你需要自动启动这个程序的时候,你就需要知道如何通过 PowerShell 或其他命令行终端来启动一个程序,而不是手工输入然后回车运行了。 本文就介绍 PowerShell 的命令行启动参...

清理 git 仓库太繁琐?试试 bfg!删除敏感信息删除大文件一句命令搞定(比官方文档还详细的使用说明)

你可能接触过 git-filter-branch 来清理 git 仓库,不过同时也能体会到这个命令使用的繁琐,以及其超长的执行时间。 现在,你可以考虑使用 bfg 来解决问题了! 安装 bfg 传统方式安装(不推荐) 下载安装 Java 运行时 下载安装 bfg.jar 这里并不推荐使用传统方式安装,因为传统方式安装后,bfg 不会成为你计算机的命令。在实际使用...

解决关闭模态窗口后,父窗口居然失去焦点跑到了其他窗口的后面的问题

显示一个模态窗口,正常而普遍的操作。然而却一直有一个难缠的 BUG:当关闭模态窗口时,父窗口有时会跑到其他程序窗口的后面! 而最近读到了微软工程师写过的话之后,明白了这个 BUG 的产生缘由以及解决方法。 这是什么 BUG? 弹出一个模态窗口,然后将模态窗口的父窗口设置为自身窗口; 切换到其他程序窗口中(比如 Windows 资源管理器窗口); 切换回此模态窗口,...

C#/.NET 当我们在写事件 += 和 -= 的时候,方法是如何转换成事件处理器的

当我们在写 += 和 -= 事件的时候,我们会在 += 或 -= 的右边写上事件处理函数。我们可以写很多种不同的事件处理函数的形式,那么这些形式都是一样的吗?如果你不注意,可能出现内存泄漏问题。 本文将讲解事件处理函数的不同形式,理解了这些可以避免编写代码的时候出现内存相关的问题。 典型的事件处理函数 事件处理函数本质上是一个委托,比如 FileSystemWatcher 的 ...

如何在 .NET 项目中开启不安全代码(以便启用 unsafe fixed 等关键字)

有小伙伴希望在 .NET 代码中使用指针,操作非托管资源,于是可能使用到 unsafe fixed 关键字。但使用此关键字的前提是需要在项目中开启不安全代码。 本文介绍如何在项目中开启不安全代码。 入门方法 第一步:在你需要启用不安全代码的项目上点击右键,然后选择属性: 第二步:在“生成”标签下,勾选上“允许不安全代码”: 第三步:切换到 Release 配置,再勾...

不要在 C# 代码中写部分命名空间(要么不写,要么写全),否则会有源码兼容性问题

我只是增加库的一个 API,比如增加几个类而已,应该不会造成兼容性问题吧。对于编译好的二进制文件来说,不会造成兼容性问题;但——可能造成源码不兼容。 本文介绍可能的源码不兼容问题。 This post is written in multiple languages. Please select yours: ...

.NET/C# 在 64 位进程中读取 32 位进程重定向后的注册表

我们知道,32 位程序在读取注册表的时候,会自动将注册表的路径映射到 32 位路径下,即在 Wow6432Node 子节点下。但是 64 位程序不会映射到 32 位路径下。那么 64 位程序如何读取到 32 位程序写入的注册表路径呢? Wow6432Node 对于 32 位程序,读取注册表路径的时候,会读到 Wow6432Node 节点下的项: 这张图读取的就是前面截图...

解决 WPF 嵌套的子窗口在改变窗口大小的时候闪烁的问题

因为 Win32 的窗口句柄是可以跨进程传递的,所以可以用来实现跨进程 UI。不过,本文不会谈论跨进程 UI 的具体实现,只会提及其实现中的一个重要缓解,使用子窗口的方式。 你有可能在使用子窗口之后,发现拖拽改变窗口大小的时候,子窗口中的内容不断闪烁。如果你也遇到了这样的问题,那么正好可以阅读本文来解决。 问题 你可以看一下下面的这张动图,感受一下窗口的闪烁: 实际上在拖...

System.ComponentModel.Win32Exception (0x80004005): 无效的窗口句柄。

在 WPF 获取鼠标当前坐标的时候,可能会得到一个异常:System.ComponentModel.Win32Exception:“无效的窗口句柄。”。 本文解释此异常的原因和解决方法。 异常 获取鼠标当前相对于元素 element 的坐标的代码: var point = Mouse.GetPosition(element); 或者,还有其他的代码: var point1 ...

使用 Direct3D11 的 OpenSharedResource 方法渲染来自其他进程/设备的共享资源(SharedHandle)

如果你得到了一个来自于其他进程或者其他模块的 Direct3D11 的共享资源,即 SharedHandle 句柄,那么可以使用本文提到的方法将其转换成 Direct3D11 的设备和纹理,这样你可以进行后续的其他处理。 SharpDX 本文的代码会使用到 SharpDX 库,因此,你需要在你的项目当中安装这些 NuGet 包: <!-- 基础,必装 --> &lt...

将 Direct3D11 在 GPU 中的纹理(Texture2D)导出到内存(Map)或导出成图片文件

Direct3D11 的使用通常不是应用程序唯一的部分,于是使用 Direct3D11 的代码如何与其他模块正确地组合在一起就是一个需要解决的问题。 本文介绍将 Direct3D11 在 GPU 中绘制的纹理映射到内存中,这样我们可以直接观察到此纹理是否是正确的,而不用担心是否有其他模块影响了最终的渲染过程。 SharpDX 本文的代码会使用到 SharpDX 库,因此,你需要...

.NET 实现 NTFS 文件系统的硬链接 mklink /J(Junction)

我们知道 Windows 系统 NTFS 文件系统提供了硬连接功能,可以通过 mklink 命令开启。如果能够通过代码实现,那么我们能够做更多有趣的事情。 本文提供使用 .NET/C# 代码创建 NTFS 文件系统的硬连接功能(目录联接)。 目录联接 以管理员权限启动 CMD(命令提示符),输入 mklink 命令可以得知 mklink 的用法。 C:\WINDOWS\sys...

WPF 高性能位图渲染 WriteableBitmap 及其高性能用法示例

WPF 渲染框架并没有对外提供多少可以完全控制渲染的部分,目前可以做的有: D3DImage,用来承载使用 DirectX 各个版本渲染内容的控件 WriteableBitmap,通过一段内存空间来指定如何渲染一个位图的图片 HwndHost,通过承载一个子窗口以便能叠加任何种类渲染的控件 本文将解释如何最大程度压榨 WriteableBitmap 在 WPF 下的性能。...