两个Win 7 CMD的bug

短文。

这两个月内遇到的问题,虽然Win 7已经退环境了也不指望修复,但是这俩问题都是我搜了半天也几乎完全搜不到任何信息的,觉得有必要稍微记录下。

Bug 1:输入和terminal宽度相等的字符数,会莫名换行

可以用以下脚本测试:

Python:

import shutil
columns, rows = shutil.get_terminal_size(fallback=(80, 24))
print('Columns:', columns)
print('-------------------')
print('a'*(columns)) # line breaks
print('-------------------')
print('a'*(columns-1)) # works fine
print('-------------------')

Node.js:

console.log('-------------------------------start-------------------------------');
var col = process.stdout.columns;
console.log("a".repeat(col))
console.log('--------------------------------end--------------------------------');

在CMD、PowerShell甚至VS Code里调用都会出现换行bug,无论column是多少:

Image
cmd.exe
Image
In VS Code

这个Bug是在使用https://github.com/Last-Order/Erii这个框架时发现的。它调用了一个叫clui的库,里面有条fill()命令就是把整行用空白字符给填满(便于overwrite已有内容),结果就导致多出很多空行。

Bug 2: 用C#的Process启动cmd的bug

标题太长了写不下,这个behavior是这样的:

Process myProcess = new Process();
myProcess.StartInfo.FileName = @"cmd.exe";
myProcess.StartInfo.UseShellExecute = false;
myProcess.StartInfo.RedirectStandardInput = true;
myProcess.StartInfo.RedirectStandardOutput = false;

myProcess.Start();
myProcess.StandardInput.WriteLine("echo test > 1.txt");

如果你用Process()来启动cmd.exe,并且重定向stdin,但是不重定向stdout,会出现以下奇怪现象:

  1. 在VS里debug时,会发现stdout也被重定向(弹出的cmd.exe里没文字),但是功能好像还基本都正常(比如上述的范例,会真的执行echo test到1.txt)。
  2. 如果编译好的程序直接双击运行,则cmd会显示一瞬间立刻crash。自然也不会执行任何你WriteLine进stdin的东西。
  3. 据说这个问题似乎只有WinForms程序会有,Console程序不会。(未测试)

这个问题其实我N年前还在用C#的时候就发现了,只不过今天碰巧又在别人写的程序里遇到(作者肯定是用Win 10的,所以没碰到)。介于这个bug在N年前Win 7还是主流的时候就有了,我寻思应该很多人问过才对;但是我找了好久,虽然找到一万个workaround,但是从来没人正式提到这个bug,直到看到这个贴(发表于2010年)。这里,作者很完整的描述了这个现象,但是很显然,依然没有人修复,仅有的几个回复也是牛头不对马嘴(顺便吐槽,这也算是网上问技术问题回答者的通病了)。

Win 10资源管理器几个不爽之处

Win 10我已经持续不断黑了几年,不过居然好像没在Blog里提过。姑且先让我罗列几个比较大的黑点:

输入法。这个我真的不想再赘述了,懂的都懂。一言以蔽之,Win 10默认做不到(以下是AND的关系):

  1. 同时有美式键盘,搜狗,日文输入法
  2. 默认是美式键盘
  3. 单一组合键(无论是什么,当然最好是ctrl+space)在美式键盘和搜狗之间切换(即:不会切换到日文)

Workaround就是通过注册表或者第三方的输入法管理器(例如搜狗带的)添加一个中文-美式键盘然后改用ctrl+shift切换两者(切换到日文还是和以前一样用alt+shift这点没区别)。这个解决方法不完美,有时候会卡住,但是也算在咬牙能用的范围内。

设置混乱,settings和控制面板共存,settings的界面远不如控制面板好用。

这个算是小问题,但是很烦:任务栏右键菜单巨卡无比——Win 7就已经比XP卡多了,没想到Win 10更卡,很多时候居然要右键之后5秒才能出菜单。虽然知道现在右键菜单的功能越来越丰富,但是好歹优化下啊喂。

当然Win 10也是有不少优点,其中大多数是看不见的内核、性能相关的,比如Win 10上用MTP比起Win 7就流畅许多(Win 7 MTP真的无力吐槽),奇怪的小BUG修了不少(上次提过的自动限制音量不知道还有人记得不)。而且Win 10的UI比起Win 8还是有比较明显的进步,比如开始菜单就make sense多了。所以,如果真的要让我改用Win 10,我也不至于无法忍受;但是因为这些蛋疼的改动让我暂时没有主动去换Win 10的欲望。

好了,这些都不是本文的重点,这次是专门来黑Win 10的资源管理器的。由于新笔记本预装Win 10,家里是Win 7,正好有机会可以仔细对比两者的差异。Win 10对资源管理器的改动不多,但是几乎每个改动都让我有几分蛋疼。先说点好的:Win 10在navigation panel左上角的Quick access添加了“自动显示最近用过的目录”功能,这个非常实用。Win 7年代只有一个“最近访问的位置”,结果点进去有几十个,还不能按照“最近使用”的顺序排序,非常难用。

好的说完,我们来说说其他改动是什么以及为什么我不喜欢。先来个Win 10资源管理器的样子:

2017-07-07

首先第一个黑点:Folders。Folders和之前Win 7微软力推的Library略有不同(后者我这里隐藏了,你可以在左侧navigation panel空白处右键调出来):就拿文档Library来说,其实他是link了诸如公用用户的Documents(XP时期叫My documents)、你当前账户下的Documents等在一起的一个虚拟文件夹,你自然也可以添加别的文件夹进去:

2017-07-07 (1)

其实Library本身就很鸡肋了:虽然MS的想法是好的,但是实际去用的人非常少,用起来也非常不方便,因为这个虚拟文件夹的统合度略差,不但看上去和一般的文件夹一点都不一样,操作起来也有区别(譬如,如果我想回到上级目录(C:\Users\[我的用户名]),在这里是做不到的)。

估计微软自己也意识到了Library的问题,搞出了这Folder出来。Folder一般对应的就是一个单独的、当前用户的文件夹,默认就是C:\Users\[你的用户名]\Documents之类的,不过如果你装了OneNote,Documents和照片会被改成C:\Users\[你的用户名]\OneDrive\[文档或照片文件夹]。当然,你也可以修改Location(右键属性即可)为其他文件夹。

可以看到,比起library那个非常难受的统合,这个好歹是单一文件夹,用起来没那么别扭。但是问题在于,对于我这种主力用Google Drive的,还是完全没用。而且,如果我真的要访问One Drive,左边导航窗格里已经有一个链接了,无非就是多点一下展开的问题。

一般而言,用不着不是问题,隐藏就好了。但是,这个Folders完全无法关闭:不但要在根目录下占据一大排(见图一),更无法接受的是要在导航窗格里居然不是单独的一个分支,而是全部堆在“Thic PC”节点下面占一大列,把本地磁盘都挤到下面。我在Win 7进行根目录跳转时,基本完全是靠左侧的导航窗格进行:有一个我的电脑的根节点下面全是盘符,非常清晰好找;结果加了这坨目录后,每次找C:\找半天。当年Library我不用,好歹可以折叠,而且不会和“我的电脑”根节点混在一起。

这里有一篇教程教你如何通过注册表移除这些Folders快捷方式(实际folder自然还在)。我没有用这个,因为我一会儿会用另外一款软件来实现。

第二个黑点:取消了右上角的View Layout选项。在Win 7时代,于右上角有一个切换View Layout的滑块,可以快速在诸如大图标、列表、详细等显示方式中切换:

heh

结果,到了Win 10中,该滑块移除,从而你只能使用以下四种方式进行切换:1:打开菜单栏View,然后从里面选;2. 右键->View->选;3. ctrl+滚轮切;4. 可以用ctrl+shift+数字的方法切换各个Layout。其中2和3是Win 7就有的。

你可能会说,明明还有高达四种的方式可以切,这也能喷?殊不知这个小细节正是我从用Win 10的第一天就觉得难受,坚持了一个月终于忍不住装第三方插件的导火索。

首先,这个功能用得非常多。尤其是在整理带略缩图的文件夹时(我装了各种shell插件,基本视频、图片、音频、乃至压缩包全部有略缩图,再加上常见的PDF等,几乎大部分文件都有略缩图),经常要在大图标乃至超大图标(便于浏览内容)、列表(便于浏览文件名)和详细(便于排序以及浏览文件大小)中来回切换。所以哪怕每次操作能节省一秒,也是非常重要的。

那回到上面那三种方式,都有什么缺点?第一种方式不用说了,那个View菜单默认是隐藏的(除非你Pin起来,蛋那就要占一大坨宝贵的纵向空间,更不现实),点开之后还要在那个横竖混杂排序的8个选项里找对应的找半天;第三种的问题在于一次只能切一格(而且还不止选项里那8种,略缩图又多了N种尺寸),所以用来从诸如略缩图到详细之间的切换根本不现实。方法四那快捷键……你试试就知道有多难按了。

第二种看似是最合理的,事实上确实也比其他三种方便许多,但是有两个因素决定了它用起来依然很难受:1. Windows右键菜单的动画效果(别忘了你还得Hover展开到第二级)。虽然这个效果绝对不算慢,但是用多了还是很抓狂;2. 这个更重要——在一个全是略缩图的、大图标Layout的文件夹里,找到空白处点出右键菜单其实非常痛苦——需要鼠标瞄准半天。

当然,我们黑也要客观:除了上面四种方式,Win 10确实还在右下角添加了(前提是你没隐藏状态栏)两个小按钮,可以在详细和略缩图两个比较常用的按钮中切换。但是对我来说只有两档真的不够用。

最后一个黑点,实话说是我最近才发现的,但是一旦发现就无法直视了。在Win 7中,最下方有一条可以调整高度的“details pane”的东西。这条能显示一些文件的基本信息,比如文件大小、修改日期之类。但是真正实用的地方是,它会显示一些metadata,比如视频文件的resolution和码率、图像的尺寸等等:

QQ截图20170708181142

在Win 10中,多增加了一个“状态栏”,会显示选中文件数量和大小——但是也就仅此而已了。远没有之前的实用。不过,“Details pane”并没有真的移除,只是(开启后)挪到了右边:

Untitled-1

不用多说,也能看出这个有多不方便。

还好,上述三个黑点全都可以用OldNewExplorer这个软件修复。具体过程不说了,有挺多选项的,下面是我“修复”之后的样子:

2017-07-07 (4).png

(把Details pane挪到下面之后其实状态栏就没多大用了,可以隐藏。)

哦还有最经典的问题:“复制过来的文件有重名文件时,保留两个文件”这个在Win 7 非常简单的操作在Win 10变得异常繁琐。

这是Win 10:

heh3

这是Win 7:

heh2

高下立判。

关于win7的文件关联问题

Windows的文件关联一直是个让人极为头疼的大问题。尤其是如果你是程序作者,如果你想完成诸如把某某文件类型的默认打开方式设置为自己的程序或者给某某文件类型添加一个右键菜单之类的功能,就得不得不面对这一问题。

之前我写Fixcue时,曾经大致地对这一方面进行了一定的了解,最终根据XP和Win7的不同,分别作出了不同的注册表写入方法,当时测试没有什么问题。结果这我自己装了win7之后,第一次运行就报错了。检查了一下程序的逻辑判断,没觉得有什么奇怪之处,结果一打开注册表傻眼了:在HKEY_CLASSES_ROOT下根本没有.cue这一项!我当时也懒得折腾,手动创建了一个改了下键值了事;今天折腾.txt又碰到类似的问题,于是决定彻底搞明白这玩意。

Win7注册表里,存储文件关联主要在这两个地方,一个自然就是HKEY_CLASSES_ROOT下,另一个是HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\。其实这么说可能不太恰当,因为准确地说,前者才是真正定义的地方,而后者则是从前者定义的各种类中选择一个。另外需要注意的是,后者既然在Current User下,那么自然是一个和当前登录用户有关的项。而前者,根据MSDN上关于HKEY_CLASSES_ROOT的介绍,我们可以得知,这个项的存在,主要是出于向下兼容的目的,其本质上是HKEY_LOCAL_MACHINE\Software\Classes和HKEY_CURRENT_USER\Software\Classes的集合(所以也就包含了全局的类和用户特有的类)。但是介于无论修改哪个,对应的项都会跟着变化,而HKEY_CLASSES_ROOT访问起来毕竟路径比较短比较好点,所以一般从这里下手比较多啦。

这里定义打开方式的形式是:在对应的后缀名下建立shell项,里面再建立open项,里面再建立command项,也就是形如:

HKEY_CLASSES_ROOT\.cue\shell\open\command

这样,然后command的键值里写入譬如c:\windows\notepad.exe %1的打开方式。

而后者的结构很清晰,还拿cue(HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.CUE)为例,里面有三个子项,分别为:

1. OpenWithList 打开方式里候选的程序;
2. OpenWithProgids 候选的Progid(程序标识符,一般来说就是一个类);
3. UserChoice 设定用户现在选择的打开方式。形式为里面含有Progid键,键值为对应的Progid名。(注意:这里的Progid名,绝大部分时候就是类名,其实就是HKEY_CLASSES_ROOT下的某个子项的名字)

如果没有UserChoice,那么则会选择对应的后缀名的ROOT里的shell\open\command里定义的打开方式。

如果问题只是这么简单就好了,但是实际上有个非常重要的设定——ROOT中类的“重定向”功能。在HKEY_CLASSES_ROOT之中,任意后缀名其本身的默认键值,其本来的目的(我猜)应该是对该类进行描述(比如txtfile的默认键值是Text Document),但事实上,更多的时候被用来进行“重定向”。其方法也很简单,就是将键值设置为另外一个类的名字,那么碰到此类后缀,就会自动把其当成后者。

一个例子就是HKEY_CLASSES_ROOT\.txt里的键值是txtfile,那么自然会对应到HKEY_CLASSES_ROOT\txtfile类。而txtfile里有设定shell\open\command的话,就会用这种方法打开;但是注意前提是HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.txt不能有设定UserChoice的Progid,否则它拥有更高的优先级;而HKEY_CLASSES_ROOT\.txt如果本身也设置有shell\open\command的话,优先级最低。即据优先级排:

HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.txt\UserChoice中的Progid键值>
HKEY_CLASSES_ROOT\txtfile\Shell\open\command的键值>
HKEY_CLASSES_ROOT\.txt\Shell\open\command的键值
前提:HKEY_CURRENT_USER\.txt的键值为txtfile。

另外更多的例子有如果你装了winrar,那么.rar将被重定向到WinRAR类、.zip将被重定向到WinRAR.zip类、如果你用TTplayer那么.cue将被重定向到Audio.CUE等等。

另外请注意,这个优先级,在XP下似乎有不同。又或者,XP下根本没有什么UserChoice的设定。总之,如果我没记错,在XP下用重定向类的方式来改变文件的打开方式抑或是添加右键菜单,屡试不爽。

其实,win7这种强制UserChoice最高优先级的作法,才是正确的。但是很遗憾的是,很多程序,甚至可以说绝大部分程序,还在使用重定向类的方式来关联程序。而这种方法在win7下,如果用户曾通过右键菜单手动指定过某文件类型的打开方式,那么是无效的(不过,如果用户从未进行过这类操作,那么UserChoice项根本不存在,倒是不会出现什么问题),双击打开该文件仍会采用UserChoice的设定。不得不提Foobar2000的作者的高明,早早地就采用了win7自带的文件关联方式,可以完美地处理文件关联问题。

更为蛋疼的是,如果UserChoice的Progid和重定向的不一致,那么对于某些依赖于某些文件类型的默认类的程序来说,是极为蛋疼的。这么说可能有点绕,拿我写的Fixcue来说吧:我现在需要实现在cue文件类型右键菜单添加一条“用Fixcue修复”的命令,那么我首先需要知道,.cue对应的到底是哪个类。如果在XP年代,我只需要查找一下ROOT\.cue的键值就知道了;而在win7里,你需要知道的是HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.cue\UserChoice里的Progid的键值。同样地,很多程序员依然没有注意到这一现象,仍然采用从ROOT\.cue找键值的方法,于是程序就会在意外的地方报错了。

注:本文中,Progid和类(Class)大部分时候同义。但是Progid似乎不限于类,具体我也搞不清,所以采取了可能会产生混淆的说法,请见谅,欢迎留言纠正。

解决win7傻逼重压无损壁纸问题

自己转成高质量jpg什么的才不要呢,无损和有损是有区别的,有区别的!

都是到英文网站上翻到的:

1.将图片保存成bmp(注意:只能是bmp)然后修改后缀名为jpg,然后再设置为背景;
2.用浏览器(IE,Fx皆可)打开图片并右键设置为背景。

总之m$急需自重!!!这问题太纱布了…