C# File.Exists 判断系统文件,警惕32位和64位的差异
今天在调试一个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位的差异的更多相关文章
- JAVA判断32位还是64位,调用不同的DLL(转)
源:JAVA判断32位还是64位,调用不同的DLL 通过获取sun.arch.data.model可判断是32还是64的JAVA 将32或者64位的DLL放不同的目录,实现自适应调用DLL Prope ...
- 如何判断你的windows系统是32位还是64位?
[学习笔记] 如 何判断你的windows系统是32位还是64位? java -version时,如果没有64就是32位的.eclipse.ini中如果没有64,就是32位的.但是我们的ini文件里面 ...
- 如何判断系统是32位还是64位的linux系统
如何判断系统是32位还是64位的linux系统 某日,需要下载个安装包,忽然忘记了自己的系统是32位还是64位的系统了,一时想不起来怎么查看时32位还是64位,呵呵,随便百度下,就发现有好多方法,这里 ...
- VC++ 判断当前系统为32位还是64位
尝试了在VC++环境下判断系统为32位还是64位的方法,亲测有效!提供的函数如下 BOOL IsWow64() { typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) ...
- 32位和64位dll判断
如何判断一个dll文件是32位还是64位? 1. 开发中经常会使用到VC的一个工具 Dependency Walker用depends.exe打开dll,文件名前有64标示的即为64位. 但是这个方式 ...
- C#判断操作系统是32位还是64位(超简单)
由于项目需要在64位和32位系统运行,需要判断当前系统是32位还是64位. 网上很多方法,但是都感觉不是很简洁,最后发现可以使用int的长度来判断:看代码 /// <summary> ...
- 判断 Windows操作系统是32位还是64位
function IsWin64: Boolean; var Kernel32Handle: THandle; IsWow64Process: function(Handle: Windows.THa ...
- C#如何判断操作系统位数是32位还是64位
方法一: 对于C#来说,调用WMI是一种简单易行的方式.我们可以用Win32_Processor类里面的AddressWidth属性来表示系统的位宽.AddressWidth的值受CPU和操作系统的双 ...
- [转]C#如何判断操作系统位数是32位还是64位
方法一: 对于C#来说,调用WMI是一种简单易行的方式.我们可以用Win32_Processor类里面的AddressWidth属性来表示系统的位宽.AddressWidth的值受CPU和操作系统的双 ...
随机推荐
- 怎样用 I/O流读取txt文件?
java.io包提供了用来永久保存对象状态的机制,可处理各种类型的流,如文件流.字节流.字符流等,还提供实现可串行化Serializable接口.可处理对象流. Java语言提供3种自动生成的标准流. ...
- Java项目开启远程调试(tomcat、springboot)
当我们运行一个项目的时候,一般都是在本地进行debug.但是如果是一个分布式的微服务,这时候我们选择远程debug是我们开发的利器. 环境apache-tomcat-8.5.16 Linux 如何启用 ...
- JasperReport报表中输出Excel时,部分列不显示的问题
JasperReport开源报表功能强大,是我们WEB系统中做报表开发的一个强有力的工具,上手也比较简单.我碰到的问题是进行报表输出时,在html网页中显示正常,但如果导出为Excel时,部分列不显示 ...
- 11. RobotFramework内置库-Collections
Collections库是RobotFramework用来处理列表和字典的库,详细可参见官方介绍. 官方地址:http://robotframework.org/robotframework/late ...
- Tornado的使用
Tornado 和现在的主流 Web 服务器框架(包括大多数 Python 的框架)有着明显的区别:它是非阻塞式服务器,而且速度相当快.得利于其非阻塞的方式和对 epoll 的运用 基本操作 torn ...
- springSecurity使用
目录 1.1 依赖包导入 2.1 没有安全机制下的一个web 3.1 做一个安全机制的web 官网https://spring.io/guides/gs/securing-web/ 无情的翻译官... ...
- wcf服务各种情况下应用
1.控制台调用 第一步,添加wcf服务 2.写接口,记得要加好契约特性. 3.声明一个类继承wcf服务. 4.ipconfig配置 5.控制台运行 6.运行app.config里面,加上调用的接口方法 ...
- 谈谈你对this的理解
this的指向不是在编写时确定的,而是在执行时确定的,同时,this不同的指向在于遵循了一定的规则. 1.默认情况下,指向全局,浏览器的话就是指向window 2.如果函数被调用的位置存在上下文,那么 ...
- node+express实现简单的增删改查
var express = require('express'); var bodyParser = require("body-parser"); var cors = requ ...
- Celery无法注册任务的几种情况
Celery处理异步任务使得程序不必等待任务结束就可以继续执行其它任务或返回数据结果, 在处理耗时任务如发送邮件.发送信息验证码等场景下非常适用! Celery使用方法灵活,根据具体业务有不同的部署和 ...