关于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似乎不限于类,具体我也搞不清,所以采取了可能会产生混淆的说法,请见谅,欢迎留言纠正。

折腾了1小时解码包,回到原点…

如题。原来一直用的完美解码09年的一个版:PureCodec20091225,工作一切正常。解码器这种东西我的原则一般是够用就不换,这玩意折腾起来太麻烦,上次换就是因为coreAVC不升级到2.0很多新压的电影都会花屏,不得已而为之。

这次又来了类似的问题:前几天下了个哈7的720P:Harry.Potter.And.The.Deathly.Hallows.Part.1.REPACK.720p.BluRay.x264-TWiZTED,打开一看无论是coreAVC 1.5还是2.0都是各种花屏,ffdshow没事,估计是x264又进化出了什么新的参数罢。于是琢磨着这也1年多了,顺手换个新解码包好了。但是完美解码后面又是变完美者解码又是加各种捆绑,甚至到现在作者DIO本人都跑路了,实在是让人不太放心,但是我还是下了个最新版,20110330,恰好是昨天更新的。

安装一切顺利,控制台是新作者Nick重做的,无论是外观还是实用性上个人认为都不如dio原版,不过影响不大。我也没什么好改的,把默认播放器改成kmp,渲染器改成haali之后就算完成,然后进入kmp一顿设置,没发现什么问题,就吃夜宵去了。结果回来点看那哈利波特——慢着,怎么还花屏?打开滤镜信息一看:坑爹呀,coreAVC还是2.0.0!那我不是白忙活了吗!算了只要别的没什么问题,把别的一堆解码器分离器什么的升级下也不是坏事——慢着,怎么字幕加载不出来?我明明已经勾选了vobsub 2.39才对…检查了一遍,没错,但字幕就是出不来。尝试更换为mpc-hc,或者换用别的渲染器,依然无果;重装之,纯默认设置下可以出来,但是一旦动了渲染器设置vobsub就跟被反注册了似的怎么都出不来(改回去都不行)。

看来这个版本是没法用了,于是我去找了个带dio控制台的最后版本——20110126,结果这货更弱,kmp默认设置有问题,解码器全用的kmp内置解码器,于是控制台里怎么改根本没意义;而且kmp默认不显示高级菜单也让我很不适应。用控制台重置kmp设置之后恢复(吐槽:你的默认设置居然和刚装好时的初始设置不一样,请问那么这叫哪门子的默认设置?),但是又出现个很蛋疼的问题:播放视频时左下视频编码表示是黑的…虽然不影响播放,但是看着就难受,于是我赶紧把它卸了。

后来我想,干脆尝试下终极解码算了,就去找了个来装。安装一切顺利,之后控制台跳出来了。终极解码其实我也用过,不过这个控制台实在是不适应,看着太挤而且很多选项不知道干吗的orz。这些略去不表,我很快就发现最大的问题——它居然不带haali渲染器!那别的也不用废话了,直接卸。

于是……我又装回了Pure Codec 20091225版。至于那个哈利波特嘛…我决定再去重下个CHD压的版本orz。如果以后这类“花屏”视频多了,自己手动升级个coreAVC好了…

更新了一下foobar的插件

foobar2000在换win7的时候由于很多插件不兼容win7,直接顺手升级至了1.1.5。foobar从0.9到1.x这升级幅度还是蛮大的,许多东西比如上下文菜单啊都重新设计了,还有大幅改进的配置界面,文件关联界面,配置文件存放方式(现在主程序和插件的配置是分离的)等,总体而言比原来更加规格化了,是个好的趋势。

不过有些老的插件虽然能用,但是在上下文菜单里会被分类到“旧的命令”中,看着挺不爽的,就借此契机把自己常用的插件都升级了一下。顺便去官网把插件列表都扫了一遍,加了几个插件。

1. foo_quicksearch(原名:foo_uie_quicksearch)

这个插件改名字了,所以我一开始还以为作者停止开发了…不过吐个槽,原来这名字就不合适,这个_uie_是CUI(分栏界面)专用插件的命名格式,而这个插件和CUI的关系本身就不大,好比我这种DUI(默认界面)的忠实用户也一直都在用。

quicksearch这插件呢顾名思义是用来搜索的,可以搜媒体库也可以搜播放列表,搜索结果会自动发送到一个新的播放列表里。我个人主要是用来搜媒体库的(实际上我常播放的播放列表也基本囊括了媒体库里的大部分歌曲orz)。

foobar官方在0.9.5/6之后,其实已经自带了一个媒体库的搜索功能(菜单栏->媒体库->搜索)。这个功能也蛮好用的,他搜索的结果会有个专门的区域陈列搜索结果,然后你可以从中选择自己想要的;另外还支持表达式搜索,详见foobar目录下的Query Syntax Help。

但是为什么我还要用这个第三方的Quicksearch呢?因为他有个非常好用的右键菜单功能——查找相同的xxx!好比查找同张专辑,查找同个艺术家,查找同路径下,等等。这个功能对于我这种播放列表完全是(几乎)乱序的人来说,有时候听到某首歌想要把这张专辑翻出来听一下,简直是再方便不过了!

2. foo_playcount

如此神器自然要重点介绍。foobar媒体库相关中最著名的播放计数插件——实际上是由fb2k的作者peter亲自开发的。这也是我当初即使面对众多困难也要启用媒体库的直接原因:播放次数统计和评分!!没错,听歌本身就是一个achievement啊,如果没有什么东西留下,拿那就太没趣了(茶)。虽然有last.fm这种东西的存在,但是建立一个本地的库的好处也是不言而喻的。

但是对于原来的playcount+媒体库这套玩意,一直有个最大的问题就是,一旦文件挪动位置,那么所有的播放次数和评分全部泡汤。虽然peter曾通过改进fileops(文件操作)这个官方插件,来做到用其移动文件时,不会导致这些数据丢失,但是这个插件的难用程度也是臭名昭著的。我当时就想,如果让我开发媒体库,一定不能使基于文件路径记录,显然应该基于一些歌曲本源的信息,比如艺术家,歌名,这些玩意来记录。于是在3.x版的foo_playcount,peter表示他终于也醒悟了!让我们看看doc里是怎么说的:

Playback statistics are now pinned to a combination of artist + album + disc number + track number + track title information, contrary to pre-3.0 versions which would pin data to file paths.

F**king yeah! 虽然我想象的系统比这个更复杂一点(可以将一首歌的不同版本(比如翻唱,remix)有机地连结在一起之类的),但是能做到这个,已经提升了200%的易用性了。而且最大的好处是移动文件再也不会丢失播放计数和评分。这样一来,foobar这套媒体库系统,终于进入了可用的范畴(我还没提0.9.4年代时,媒体库不会自动索引新文件的2b问题…)了。

还有个重大改进是现在playcount统计不再局限于媒体库,播放列表里的也会被统计。但是我已经上了媒体库这个贼船了,也体会到了其在搜索上的优势,想来是不会再回到操作各种播放列表的年代啦~

3. foo_jesus

罪过罪过,这么著名的插件我原来居然一直没装。其实我有知道这个插件啦,但是原来觉得连个foobar的配置都要备份是不是显得太蛋疼…不过后来搞了媒体库之后才知道这完全必要。因为如果foobar一崩溃,损失的不再仅仅是一些设置(可能本次启动根本没改动过),而是整整一天的播放数据啊!这简直太宝贵了。于是我再次发现这个插件是赶紧把它给装了。作者是HA(hydrogenaudio)fb2k版版主,水平不用怀疑。默认配置就可以很好地工作,会自动备份配置媒体库,配置文件,播放列表,播放计数数据库(老版和新版),总之一切foobar有关的settings,令人安心。

4. foo_texttools

一个甚为鸡肋的插件…可以自定义一些复制名称的格式,啥的…但是我通常根本是用foobar自带的那个比较多,这个仅在有时候需要复制整个列表输出到论坛时用(我前一段蛋疼地写了个带bb代码的格式。。)。

这次既然看到他了就更新一下呗,虽然俩小版本号而已。至于changelog..

Version 1.0.5 highlights: updated the preferences page to new foobar2000 v1.1 looks.

太棒了!这简直和blz的“猎人切换守护时将拥有新的叫声”一样coooooool了!

5. foo_tagbox

没错,我还在寻找foo_infobox这一神器的替代品。于是找到了这个至少号称带有下一首上一首功能的tagger。实际上嘛……用户体验较差,但是聊胜于无了,有需要时估计还是能用的上(其实后来想想,其实infobox现在用的也不多了,大部分时间都是手改cue来得快……)。

最后的遗憾

foo_masstag看来是太监了…虽然还是能用的大概(我没试,但是看上去那个界面似乎ok……?),但是现在右键菜单里残留的那个旧版命令(未分类)太丑了…所以我把它从上下文菜单中去掉了。最后一个小Tip:按住shift右键将弹出一个包含所有命令(无论你是否在配置中勾选)的右键菜单。

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

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

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

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

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