今天在调试一个Winform程序,使用File.Exists 判断一个已经存在的驱动文件,程序一直返回false。因为驱动文件属于系统目录,心想难道是权限不够导致的?然后用管理员身份运行软件,依然返回false。吓的我赶紧去系统目录C:\Windows\system32\drives 搜索该文件,一看在这里啊,怎么还是返回false。开始还以为VS出问题了,然后尝试判断一个D盘下的文件,发现可以判断成功。

判断代码如下

// 获取系统目录
var system = Environment.GetFolderPath(Environment.SpecialFolder.System);
var filePath = system + @"\drivers\evserial7.sys";
var flag = File.Exists(filePath);
MessageBox.Show("系统路径:" + filePath + "\r\n" + "checkDrives:" + flag);

运行结果

在系统中找文件确实存在,如下图

奇怪在于当我把程序设置成Release运行的时候判断又成功了,第一张图Debug运行的,下图是Release

当时心想为什么Release和Debug不一样呢,一时有点诧异,然后就想着,看看反编译后的IL代码,看两者是不是有什么差别?

Debug反编译

Release反编译

这样看两者并没有任何差异,因为我们判断是路径,所以我们只看IL中路径是否有不同编译, 两者中IL_0002: call string [mscorlib]System.Environment::GetFolderPath(valuetype [mscorlib]System.Environment/SpecialFolder)都是一样的,说明系统路径一样,后面拼接字符串更加不会有任何差别。

最终通过stackoverflow找到原因,因为我当前程序编译的是32位即X86,32位应用程序在64位系统中是无法访问system32目录的。为什么我程序要选择编译32位呢,因为我程序当中需要调用一个C++写的dll,该dll是32位的,我无法改变。如果我程序编译时选择AnyCPU或者X64,那么该dll是无法调用的。所以我只能改成X86。

为什么当我用Release又能判断正确,原因在于上图的这个生成配置页面在Release的时候目标平台任然是:Any CPU。(不是X86),所以能判断成功。当把Release模式的目标平台改为X86后结果就是flase了。

那么编译的32位程序到底该怎么判断64位系统中的系统文件呢?其实当我们32位应用程序访问system32文件夹的时候,64位系统会自动帮我们自动重定向到SysWoW64文件夹。通过专业解释该文件夹主要是被设计用来处理许多在32-bit Windows和64-bit Windows之间的不同的问题,使得可以在64-bit Windows中运行32-bit程序。

所以我们在32位程序的时候判断系统路径其实已经重定向到了:  C:\Windows\SysWoW64\drivers\evserial7.sys,这是系统自动重定向,所以IL代码中我们也看不到差异。这个目录肯定不存我们的文件,所以导致返回判断false。

那我们如何在32位下真正的访问system32目录呢?不要系统重定向。使用 C:\Windows\SysNative路径,这是个虚拟路径,我们在Windows资源管理器中是无法找到的。但是他最终还是会指向到system32中。SysNative文件夹目的就是让32位应用程序访问64位系统文件的方法。

现在我将代码改下,前面的 Environment.GetFolderPath(Environment.SpecialFolder.System)是获取system32这里要改为Environment.SpecialFolder.Windows,获取windows目录,并在下面拼接上Sysnative目录。

这只是在判断系统文件的时候会存在32位和64位的差异,普通文件就不存在任何影响了。

最后修改代码如下

// 获取windows目录
var system = Environment.GetFolderPath(Environment.SpecialFolder.Windows);
var filePath = system + @"\Sysnative\drivers\evserial7.sys";
var flag = File.Exists(filePath);
MessageBox.Show("系统路径:" + filePath + "\r\n" + "checkDrives:" + flag);

运行结果

C# File.Exists 判断系统文件,警惕32位和64位的差异的更多相关文章

  1. JAVA判断32位还是64位,调用不同的DLL(转)

    源:JAVA判断32位还是64位,调用不同的DLL 通过获取sun.arch.data.model可判断是32还是64的JAVA 将32或者64位的DLL放不同的目录,实现自适应调用DLL Prope ...

  2. 如何判断你的windows系统是32位还是64位?

    [学习笔记] 如 何判断你的windows系统是32位还是64位? java -version时,如果没有64就是32位的.eclipse.ini中如果没有64,就是32位的.但是我们的ini文件里面 ...

  3. 如何判断系统是32位还是64位的linux系统

    如何判断系统是32位还是64位的linux系统 某日,需要下载个安装包,忽然忘记了自己的系统是32位还是64位的系统了,一时想不起来怎么查看时32位还是64位,呵呵,随便百度下,就发现有好多方法,这里 ...

  4. VC++ 判断当前系统为32位还是64位

    尝试了在VC++环境下判断系统为32位还是64位的方法,亲测有效!提供的函数如下 BOOL IsWow64() { typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) ...

  5. 32位和64位dll判断

    如何判断一个dll文件是32位还是64位? 1. 开发中经常会使用到VC的一个工具 Dependency Walker用depends.exe打开dll,文件名前有64标示的即为64位. 但是这个方式 ...

  6. C#判断操作系统是32位还是64位(超简单)

    由于项目需要在64位和32位系统运行,需要判断当前系统是32位还是64位. 网上很多方法,但是都感觉不是很简洁,最后发现可以使用int的长度来判断:看代码 /// <summary>    ...

  7. 判断 Windows操作系统是32位还是64位

    function IsWin64: Boolean; var Kernel32Handle: THandle; IsWow64Process: function(Handle: Windows.THa ...

  8. C#如何判断操作系统位数是32位还是64位

    方法一: 对于C#来说,调用WMI是一种简单易行的方式.我们可以用Win32_Processor类里面的AddressWidth属性来表示系统的位宽.AddressWidth的值受CPU和操作系统的双 ...

  9. [转]C#如何判断操作系统位数是32位还是64位

    方法一: 对于C#来说,调用WMI是一种简单易行的方式.我们可以用Win32_Processor类里面的AddressWidth属性来表示系统的位宽.AddressWidth的值受CPU和操作系统的双 ...

随机推荐

  1. js事件入门(6)

    7.事件冒泡机制 7.1.什么是事件冒泡 当一个元素接收到一个事件以后,会将事件传播给它的父级元素,它的负级元素会一层一层往上传播,直到最顶层window,这种事件传播机制叫作事件冒泡. <!D ...

  2. BootstrapDialog.confirm确认对话框

    1. 依赖文件: bootstrap.js bootstrap-dialog.js bootstrap.css bootstrap-dialog.css 2.代码 BootstrapDialog.co ...

  3. ASP.NET MVC 四种Controller向View传值方法

    控制器: // Get: Data public ActionResult Index() { //ViewData 方式 ViewData["UserName"] = " ...

  4. stb_image multiple definition of first defined here 多文件包含问题

    首先吐槽一下,网上的其他的一些内容都是瞎写,根本没有指出问题的根本原因,使用时出现异常情况不能自己解决也说明了C语言基础不牢固, 该头文件可以分为两种情况使用(推荐使用办法2,办法1中有解释原因)(任 ...

  5. JQ滚动加载

    $(window).scroll(function () { if ($(document).scrollTop() + $(window).height() >= $(document).he ...

  6. adb devices 不能连接设备 could not install *smartsocket* listener

    cmd以管理员身份运行命令adb devices  或adb reverse tcp:8081 tcp:8081,无法连接设备,出现上图信息. 输入命令:adb kill-server 再输入:adb ...

  7. day02总结

    1.机器语言:直接用二进制指令编写程序 优点:程序的运行速度快 缺点: 1.编写程序太复杂了 2.记忆困难 2.汇编语言:用英文标签取代二进制指令去编写程序 方便记忆了, 但编写程序还是复杂的 3.高 ...

  8. display:inline-block 什么时候不会显示间隙?

    移除空格 使用margin负值 使用font-size:0 letter-spacing word-spacing

  9. U盘+grub2安装centos8实战

    1. U盘准备 这里的U盘也可以换成硬盘 grub2安装一直失败,怀疑U盘坏了,下面命令修复了一下 [root@host2 ~]# lsblk NAME MAJ:MIN RM SIZE RO TYPE ...

  10. ETag简介与作用

    ETag简介与作用 一.ETag简介 ETag是URL的tag,用来标示URL对象是否改变.这样可以应用于客户端的缓存:服务器产生ETag,并在HTTP响应头中将其传送到客户端,服务器用它来判断页面是 ...