【经验】C++通过文件句柄获取文件路径(两种方式)
方法一
主要参考博客:根据文件句柄获得文件名(这篇超级清晰,就是有一点点小问题)
通过文件句柄获得文件路径(这篇不是很好用,但是思路大体是一致的)
主要思路:
- 根据
HANDLE创建映射文件,调用GetMappedFileName获得一个DosDevice路径。- 然后
GetLogicaDriveStrings获得盘符字串,依次读取盘符字串获得对应的DosDevice路径,看之前的DosDevice路径中是否有现在的DosDevice路径(strstr)。- 有的话,就拿到盘符字串,把盘字符串和去掉
DosDevice盘符的DosDevice路径拼接;没有的话,就再读取下一个盘符的DosDevice路径,依次这样,直到找到为止。缺点:
- 只能获得自己进程打开的文件,其它进程打开的文件貌似不行。
MapViewOfFile在多线程中会产生冲突,返回错误码6,暂待解决。
#include <windows.h>
#include <psapi.h>
typedef DWORD (WINAPI *MyGetMappedFileName)(HANDLE,LPVOID,LPTSTR,DWORD);
int GetFileNameByHandle(HANDLE hFile,LPSTR buff,DWORD bufSize)
{
HANDLE hfilemap = CreateFileMapping(hFile,NULL,PAGE_READWRITE,NULL,NULL,NULL); // 获取文件映射句柄
if(INVALID_HANDLE_VALUE==hfilemap)
{
printf("CreateFileMapping error: %d\n",GetLastError());
return 0;
}
LPVOID lpmap = MapViewOfFile(hfilemap,FILE_MAP_READ|FILE_MAP_WRITE,NULL,NULL,0); // 获取文件映射对象
if(NULL==lpmap)
{
printf("MapViewOfFile error: %d\n",GetLastError());
return 0;
}
// GetMappedFileName未定义
MyGetMappedFileName GetMappedFileName =(MyGetMappedFileName)GetProcAddress(LoadLibrary("psapi.dll"),"GetMappedFileNameA");
if(GetMappedFileName==NULL)
{
printf("Get 'GetMappedFileName' FuncAddress error.\n");
return 0;
}
char DosStr[MAX_PATH]= {0};
DWORD length = GetMappedFileName(GetCurrentProcess(),lpmap,DosStr,bufSize); // 获取Dos设备名
if(0==length)
{
printf("GetMappedFileName error: %d\n", GetLastError());
return 0;
}
char DosPath[MAX_PATH]= {0};
char DriverString[MAX_PATH]= {0};
if (0 == GetLogicalDriveStrings(MAX_PATH, DriverString)) // 获取电脑的盘符列表
{
printf("GetLogicalDriveStrings error: %d", GetLastError());
return 0;
}
char * p = (char *)DriverString; //p用来指向盘符
do
{
*(p+2)='\0'; //QuerDosDevice第一个参数必须是c:这种类型的,不能有\,所以把\抹掉
if (!QueryDosDevice((LPCTSTR)p, DosPath, MAX_PATH)) // 将盘符映射成DOS设备名
{
printf("QueryDosDrive error: %d\n", GetLastError());
return FALSE;
}
char * q = strstr(DosStr,DosPath); //检测buff中是否有DosDevice中的DosPath,有的话,p指向的那个字串就是要的盘符
if(q!=0)
{
sprintf(buff, "%s%s", p, DosStr+strlen(DosPath)); //找到之后应该把DosPath替换成盘符
return 1;
}
p=p+4; //指针移动到DriverString的下一个盘符处
}
while(*p!=0);
return 0;
}
调用测试:
int main()
{
HANDLE p=CreateFileA("a.txt", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, NULL, NULL);
char m[100000];
GetFileNameByHandle(p, m, sizeof(m));
printf("%s",m);
return 0;
}
结果截图:

方法二
char m[1000]; // 存储路径
int fileNameResult = GetFinalPathNameByHandleA(hFile, m, MAX_PATH, 0); // fileNameResult是路径长度
缺点:不能跨进程获取路径。
可能问题:fileapi.h不存在。(codeblocks中显示不存在,vs2019没有问题)
【经验】C++通过文件句柄获取文件路径(两种方式)的更多相关文章
- Springboot 创建的maven获取resource资源下的文件的两种方式
Springboot 创建的maven项目 打包后获取resource下的资源文件的两种方式: 资源目录: resources/config/wordFileXml/wordFileRecord.xm ...
- Eclipse项目中引用第三方jar包时将项目打包成jar文件的两种方式
转载自:http://www.cnblogs.com/lanxuezaipiao/p/3291641.html 方案一:用Eclipse自带的Export功能 步骤1:准备主清单文件 “MANIFES ...
- 加载xib文件的两种方式
一.加载xib文件的两种方式 1.方法一(NewsCell是xib文件的名称) NSArray *objects = [[NSBundle mainBundle] loadNibNamed:@&quo ...
- java动态获取WebService的两种方式(复杂参数类型)
java动态获取WebService的两种方式(复杂参数类型) 第一种: @Override public OrderSearchListRes searchOrderList(Order_Fligh ...
- js 图片base64转file文件的两种方式
js 图片base64转file文件的两种方式 https://blog.csdn.net/yin13037173186/article/details/83302628 //将base64转换为bl ...
- jsp:jsp包含文件的两种方式
第一种:include指令 include指令:当JSP转换成Servlet时引入指定文件(指令元素),这是一种静态包含,它运行的时候不会单独编译成.class文件,它生成一个新的整体.class文件 ...
- MyBatis获取参数值的两种方式
MyBatis获取参数值的两种方式:${}和#{} ${}的本质就是字符串拼接,#{}的本质就是占位符赋值 ${}使用字符串拼接的方式拼接sql,若为字符串类型或日期类型的字段进行赋值时,需要手动加单 ...
- MyBatis_04(MyBatis获取“参数值”的两种方式)
MyBatis获取"参数值"的两种方式 (重点!!!) MyBatis获取参数值的两种方式:${}和#{} ${}的本质就是字符串拼接 , #{}的本质就是占位符赋值 ${}使用字 ...
- Spring加载properties文件的两种方式
在项目中如果有些参数经常需要修改,或者后期可能需要修改,那我们最好把这些参数放到properties文件中,源代码中读取properties里面的配置,这样后期只需要改动properties文件即可, ...
- springmvc获取资源文件的两种方式(超简单)
1 比如我们在sc目录下新建一个db.properties文件内容如下 DriverClass=com.mysql.jdbc.Driverurl=jdbc:mysql://localhost:3306 ...
随机推荐
- mac安装python包
一.常用包安装记录1.分析exl用的pandas pip install xlrd==1.2.0 pip3 install pandas
- Netty高级使用与源码详解
粘包与半包 粘包现象 粘包的问题出现是因为不知道一个用户消息的边界在哪,如果知道了边界在哪,接收方就可以通过边界来划分出有效的用户消息. 服务端代码 public class HelloWorldSe ...
- 快速配置Azure DevOps代理服务器
快速配置Azure DevOps代理服务器(CentOS 7) Azure DevOps非常好用,但是代理服务器的配置相对有点麻烦而且易出问题,接下来笔者分享一下如何快速配置Azure DevOps的 ...
- WPF程序性能优化总结
原文链接: https://blog.csdn.net/u010265681/article/details/77571947 WPF程序性能由很多因素造成,以下是简单地总结: 元素: 1. 减少需要 ...
- 福尼斯焊机TPS320i/TPS400i/TPS500i的焊接特性
福尼斯焊机设备原理 TPS320i.TPS400i.TPS500i和TPS 600iMIG/MAG电源由微处理器控制,机器人驱动器维修,是完全数字化的逆变器电源. 模块化设计和系统的扩展潜力使其具有高 ...
- Typecho实现版权声明的三种方式
在安装完Typecho之后,第一件事应该就是想着如何去折腾了.对于个人博客而言,不希望自己辛辛苦苦写的文章,被别人转载或无脑采集,还不留原地址,所以就需要在文章的末尾地方放上一个版权声明,来提醒下转载 ...
- 寻找旋转排序数组中的最小值 II
地址:https://leetcode-cn.com/problems/find-minimum-in-rotated-sorted-array-ii/ <?php /** 154. 寻找旋转排 ...
- linux系统批量查找网站源码并替换字符,查找替换指定内容
问题描述:维护中需要批量修改代码中某个字符,如果单个打开页面进行修改则效率过低,linux系统下借助grep命令快速查找替换 命令示例1: grep -rl '查找的内容' . | xargs sed ...
- Ubuntu 22.04 添加 AppImage 到应用程序
前言 AppImage 逐渐成为 Linux 常用的一种软件包格式,本文将介绍如何将 AppImage 文件添加到 Ubuntu 的应用程序中. 如下图中的 CAJViewer : 操作过程 设置相关 ...
- surpac 中如何删除点
找到显示的编号 输入线窜线段编号