我们先来看一张图。
起源
话说今天老衲在折腾一个VC++的程序,然后尝试编译它。但是当编译它的时候,VS2017报了这么一个错误。
LINK : fatal error LNK1104: 无法打开文件“LIBCMT.lib”
链接错误。链接错误是因为啥呢,库目录设置不对吗,还是哪里编译器设置不对了。
可是我在项目属性里瞅了大半天,并没有感觉哪里有问题。那是我库装的不对吗?祭出Everything搜了一下,发现无数个libcmt.lib。
当时的气氛有点尴尬,很明显是在欺负我这个新来的。
我能就这样认输吗?当然不能。
后来想想,掏出来Process Monitor,设置了过滤条件为“Path 包含 LIBCMT.lib”,然后开始捕捉并开始编译,尝试捕捉文件系统操作。
从上面的捕捉结果可以看到,嗯……NAME NOT FOUND……确实找不到这俩文件。然而路径并没有错啊,是因为安装出错了?于是我去这个目录下看。
什么鬼……这不好好地在这里吗。
什么鬼?
翻来覆去折腾项目编译设置无果。后来试着把Process Monitor里的那个路径复制出来,用记事本打开那个路径……
看起来确实是这个路径不存在?但是为啥啊??
我试着把文件名从 libcmt.lib 改成 LIBCMT.lib,再回去VS里编译,嘿……还真就不提示这个错误了……
区分大小写??
到这里,我只能解释为,Windows系统啥时候开始文件名区分大小写了……
我尝试在谷歌上搜了一圈,还真找到了这样一篇资料,介绍了支持区分大小写的文件系统……
总的来说,就是Windows10的NTFS系统开始支持文件名区分大小写,但是默认不开启。原因是因为Linux系统都支持的,而Windows10 四月更新开始支持基于WSL的Linux分发,所以为了对Linux实现兼容,文件系统开始支持区分大小写,但是默认不开启。
怎么搞定是否区分大小写?
文件名区分大小写是文件夹的额外属性……
如何判断呢?通过 fsutil.exe
。
比如在题图的那个文件夹,我们需要判断对应文件夹是否已启用区分大小写属性,可以通过如下的命令行:
fsutil file queryCaseSensitiveInfo .
既然能开启,就能通过这个命令打开或关闭。打开或关闭的语法如下:
fsutil file setCaseSensitiveInfo .[disable|enable]
关闭之前要确认不会因为不区分大小写导致文件名冲突,否则会报错。
好了,回到问题上来
辣么,既然这个是默认关闭的,为什么我的VS2017出现这个问题呢?
这里有个很有意思的细节,就是在WSL里创建的文件夹,为了保持兼容,默认是开启这个属性的。
然后由于一些难以启齿的历史遗留原因,确实这个目录是在WSL下创建的……
这个默认行为可以修改(在上面的链接文章里有介绍),但是我觉得……这个默认行为还是不要动了吧。
我用LinqPad写了一个脚本检测目录,发现上面放着这些lib的文件目录确实都被开启了文件名区分大小写……
发现了然后呢?当然是继续写脚本全部关闭这个很Linuxer的特性啊……除了fsutil没有别的方法能关也是没谁了。
或许有其它方法?只是我不知道?
在传统管理员模式cmd下先cd进你想要设置的批量目录的上一级目录然后打一行命令就可以了,多简单~(恩,一开始就没接触过DOS系统的人确实有点困难……)
for /D %I IN (*.*) DO fsutil file setCaseSensitiveInfo "%~fI" disable
ps1:不清楚Powershell是不是能行,我没win10,以后除非必要也不打算用各种Bug把小白当试验品的win10,如果换新电脑了,目前中意的版本是LTSB2015或者LTSB2016,或者Server2016,反正在中国Server系统不要钱~
ps2:这样只会给木马和勒索病毒提供方便,对于普通用户没有丝毫好处
啊,居然还有这么个坑,我觉着下次可以偷偷的捉弄下人了
鱼大,你有Linqpad的破解版分享一下吗?
我有老版本的但是我不是很愿意分享,毕竟我花银子买的正版了……嘿嘿。如果你真的需要,请发邮件给我。
我也很想要 linqpad 的破解版。。。