有方法读取一个已被其他进程打开且dwSharemode = 0的文件吗?
2015-03-12 22:37
281 查看
有方法读取一个已被其他进程打开且dwSharemode = 0的文件吗?
最近有项目要打开一个已被其他进程打开,且其dwShareMode=0,即其它进程不得共享打开。该如何做呢?久思不得其解,于是去bbs.pediy.com询问[1],网友给出的方法是:
我选用了第二种方法,果然能解决问题。但是中间也遇到了一些问题,本文来说说这中间遇到的问题。
既然是使用DuplicateHandle,那么必须知道原进程的PID,和文件在该进程中的句柄Handle。
所以程序的思路是先遍历系统中所有进程,然后或则进程中文件句柄,接着使用文件句柄获得文件名称——这样便可以得到PID和Handle了。
一. 遍历系统所有进程
可以使用多种方法遍历系统中所有进程,一般使用ZwQuerySystemInformation(SystemProcessesAndThreadsInformation)或者CreateToolhelp32Snapshot来实现。
二. 遍历句柄
句柄的遍历使用ZwQuerySystemInformation(SystemHandleInformation),该函数列出所有进程的所有句柄,然后使用TSYSTEM_HANDLE_INFORMATION结构体中的ProcessId来过滤出指定进程的句柄。
这里的句柄是各种类型。可以通过TSYSTEM_HANDLE_INFORMATION结构体中的ObjectTypeNumber来判断句柄类型。在程序中我使用File=28硬编码,因为我发现在Win7和XP下是成立的,
但是有网友[3]讨论说不是所有的系统都是这样的,于是我尝试遍历系统中所有的类型对象(type object),方法是使用ZwQueryObject(ObjectAllTypesInformation)。本想通过序号实时找出当前系统中的类型值,但是遗憾是序号值不对。
三. 根据文件句柄获取文件名
只有获得句柄对应的文件名,通过比较才能知道是否是想要的文件句柄,所以当务之急是获得文件名。但是得先通过调用OpenProcess和DuplicateHandle来复制一个句柄。然后再使用下面两类方法中的一种:
1. 使用ZwQueryInformationFile
该函数返回一个TFILE_NAME_INFORMATION结构,这个结构包括文件的名称,但是不包括驱动器名,所以需要通过其他方法(见下)获得驱动器名,将上述两者相连方可获得整个文件名了。
这个方法有个问题,在某些进程(如qq.exe)在调用ZwQueryInformationFile时会使调用程序“死掉”。难道qq这些程序有什么保护方法,不让复制的句柄来使用ZwQueryInformationFile?
2. 使用GetMappedFileName
这种方法使用CreateFileMapping、MapViewOfFile和GetMappedFileName获得文件名——同样没有驱动器名,所以也得通过其他方法(见下)获得驱动器名。
这种方法也有缺陷,不能调用CreateFileMapping打开没有访问权限目录中的文件。
3. 获得驱动器名
有两种方法获得驱动器名:
1) GetFileInformationByHandle和GetLogicalDriveStringsA比较
2) GetLogicalDriveStrings和QueryDosDevice比较
GetFileInformationByHandle也会使程序“死掉”,所以慎用。
四. 大功告成
知道了进程pid和句柄值,就可以通过复制句柄的方法访问文件了——这其实在前面已经这么做过一次了——获得文件名不正是复制句柄来实现的吗?
不过,在使用文件指针访问文件(如调用ReadFile和WriteFile)时要注意:因为原句柄和复制句柄共享一个文件指针,所以可能会造成指针位置的混乱。
五. 参考文献
1. http://bbs.pediy.com/showthread.php?t=198566
2. 有关遍历进程中句柄的方法总结http://blog.sina.com.cn/s/blog_58e7a03b01014c9e.html
3. http://bbs.pediy.com/showthread.php?t=179951
4. [Delphi]从handle获得文件名
http://cndkervip.blog.163.com/blog/static/32546863200772311416631/
最近有项目要打开一个已被其他进程打开,且其dwShareMode=0,即其它进程不得共享打开。该如何做呢?久思不得其解,于是去bbs.pediy.com询问[1],网友给出的方法是:
1) 干掉原句柄,比较常用的手段有杀死原进程,远程关闭句柄,创建远程线程调用CloseHandle 2) 复制原句柄,打开进程用DuplicateHandle复制一份即可使用 3) 如果使用驱动的话,直接下发IRP读文件内容即可,缺点是也许需要硬编码 |
既然是使用DuplicateHandle,那么必须知道原进程的PID,和文件在该进程中的句柄Handle。
所以程序的思路是先遍历系统中所有进程,然后或则进程中文件句柄,接着使用文件句柄获得文件名称——这样便可以得到PID和Handle了。
一. 遍历系统所有进程
可以使用多种方法遍历系统中所有进程,一般使用ZwQuerySystemInformation(SystemProcessesAndThreadsInformation)或者CreateToolhelp32Snapshot来实现。
二. 遍历句柄
句柄的遍历使用ZwQuerySystemInformation(SystemHandleInformation),该函数列出所有进程的所有句柄,然后使用TSYSTEM_HANDLE_INFORMATION结构体中的ProcessId来过滤出指定进程的句柄。
这里的句柄是各种类型。可以通过TSYSTEM_HANDLE_INFORMATION结构体中的ObjectTypeNumber来判断句柄类型。在程序中我使用File=28硬编码,因为我发现在Win7和XP下是成立的,
但是有网友[3]讨论说不是所有的系统都是这样的,于是我尝试遍历系统中所有的类型对象(type object),方法是使用ZwQueryObject(ObjectAllTypesInformation)。本想通过序号实时找出当前系统中的类型值,但是遗憾是序号值不对。
补充:这个index值应该是OBJECT_TYPE对象中的INDEX字段: |
只有获得句柄对应的文件名,通过比较才能知道是否是想要的文件句柄,所以当务之急是获得文件名。但是得先通过调用OpenProcess和DuplicateHandle来复制一个句柄。然后再使用下面两类方法中的一种:
1. 使用ZwQueryInformationFile
该函数返回一个TFILE_NAME_INFORMATION结构,这个结构包括文件的名称,但是不包括驱动器名,所以需要通过其他方法(见下)获得驱动器名,将上述两者相连方可获得整个文件名了。
这个方法有个问题,在某些进程(如qq.exe)在调用ZwQueryInformationFile时会使调用程序“死掉”。难道qq这些程序有什么保护方法,不让复制的句柄来使用ZwQueryInformationFile?
2. 使用GetMappedFileName
这种方法使用CreateFileMapping、MapViewOfFile和GetMappedFileName获得文件名——同样没有驱动器名,所以也得通过其他方法(见下)获得驱动器名。
这种方法也有缺陷,不能调用CreateFileMapping打开没有访问权限目录中的文件。
3. 获得驱动器名
有两种方法获得驱动器名:
1) GetFileInformationByHandle和GetLogicalDriveStringsA比较
2) GetLogicalDriveStrings和QueryDosDevice比较
GetFileInformationByHandle也会使程序“死掉”,所以慎用。
四. 大功告成
知道了进程pid和句柄值,就可以通过复制句柄的方法访问文件了——这其实在前面已经这么做过一次了——获得文件名不正是复制句柄来实现的吗?
不过,在使用文件指针访问文件(如调用ReadFile和WriteFile)时要注意:因为原句柄和复制句柄共享一个文件指针,所以可能会造成指针位置的混乱。
五. 参考文献
1. http://bbs.pediy.com/showthread.php?t=198566
2. 有关遍历进程中句柄的方法总结http://blog.sina.com.cn/s/blog_58e7a03b01014c9e.html
3. http://bbs.pediy.com/showthread.php?t=179951
4. [Delphi]从handle获得文件名
http://cndkervip.blog.163.com/blog/static/32546863200772311416631/
相关文章推荐
- c# 读取其他程序正打开的文件的时“正由另一进程使用,因此该进程无法访问该文件。"的问题解决方法
- 使用createprocess()创建进程打开其他文件方法
- C# System.IO.FileStream 读取被其他程序打开的文件提示“文件正由另一进程使用,因此该进程无法访问该文件。”
- C# System.IO.FileStream 读取被其他程序打开的文件提示“文件正由另一进程使用,因此该进程无法访问该文件。”
- vb读取xls文件而不打开excel进程 ado数据库方法读取xls
- C# System.IO.FileStream 读取被其他程序打开的文件提示“文件正由另一进程使用,因此该进程无法访问该文件。”
- 打开了一个size不为零的文件,读取到的值却为零的一种分析和解决方法
- C# System.IO.FileStream 读取被其他程序打开的文件提示“文件正由另一进程使用,因此该进程无法访问该文件。”
- 读取xml文件出现错误的一个解决方法(android)
- 用C#编程从数据库中读取图片数据导进Excel文件的方法(如何从数据库中读取保存的文件,直接打开,中间不保存到本地)
- Windwos下读取被独占打开文件的方法
- 将dll文件注入到其他进程中的一种新方法
- linux默认情况下,一个进程最多能打开多少文件?
- 一个进程能够打开最大文件句柄数设到多大才合适(Linux) (转)
- asp.net中打开Excel上传文件,读取数据的方法
- 如何从内核模式设备驱动程序中打开一个文件以及如何读取或写入文件(来自微软官网)
- 如何从内核模式设备驱动程序中打开一个文件以及如何读取或写入文件
- 在vc中用MFC按纽打开一个txt文件,在旁边的文本框里显示文件的路径的方法
- (转)读取一个大文件,比如7、8百兆的高效的方法?
- 让TXT文本等其他任意格式的文件,不在IE中打开,而直接下载的方法