方法一

主要参考博客:根据文件句柄获得文件名(这篇超级清晰,就是有一点点小问题)
通过文件句柄获得文件路径(这篇不是很好用,但是思路大体是一致的)

主要思路:

  1. 根据HANDLE 创建映射文件,调用GetMappedFileName获得一个DosDevice路径。
  2. 然后GetLogicaDriveStrings获得盘符字串,依次读取盘符字串获得对应的DosDevice路径,看之前的DosDevice路径中是否有现在的DosDevice路径(strstr)。
  3. 有的话,就拿到盘符字串,把盘字符串和去掉DosDevice盘符的DosDevice路径拼接;没有的话,就再读取下一个盘符的DosDevice路径,依次这样,直到找到为止。

缺点:

  1. 只能获得自己进程打开的文件,其它进程打开的文件貌似不行。
  2. 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++通过文件句柄获取文件路径(两种方式)的更多相关文章

  1. Springboot 创建的maven获取resource资源下的文件的两种方式

    Springboot 创建的maven项目 打包后获取resource下的资源文件的两种方式: 资源目录: resources/config/wordFileXml/wordFileRecord.xm ...

  2. Eclipse项目中引用第三方jar包时将项目打包成jar文件的两种方式

    转载自:http://www.cnblogs.com/lanxuezaipiao/p/3291641.html 方案一:用Eclipse自带的Export功能 步骤1:准备主清单文件 “MANIFES ...

  3. 加载xib文件的两种方式

    一.加载xib文件的两种方式 1.方法一(NewsCell是xib文件的名称) NSArray *objects = [[NSBundle mainBundle] loadNibNamed:@&quo ...

  4. java动态获取WebService的两种方式(复杂参数类型)

    java动态获取WebService的两种方式(复杂参数类型) 第一种: @Override public OrderSearchListRes searchOrderList(Order_Fligh ...

  5. js 图片base64转file文件的两种方式

    js 图片base64转file文件的两种方式 https://blog.csdn.net/yin13037173186/article/details/83302628 //将base64转换为bl ...

  6. jsp:jsp包含文件的两种方式

    第一种:include指令 include指令:当JSP转换成Servlet时引入指定文件(指令元素),这是一种静态包含,它运行的时候不会单独编译成.class文件,它生成一个新的整体.class文件 ...

  7. MyBatis获取参数值的两种方式

    MyBatis获取参数值的两种方式:${}和#{} ${}的本质就是字符串拼接,#{}的本质就是占位符赋值 ${}使用字符串拼接的方式拼接sql,若为字符串类型或日期类型的字段进行赋值时,需要手动加单 ...

  8. MyBatis_04(MyBatis获取“参数值”的两种方式)

    MyBatis获取"参数值"的两种方式 (重点!!!) MyBatis获取参数值的两种方式:${}和#{} ${}的本质就是字符串拼接 , #{}的本质就是占位符赋值 ${}使用字 ...

  9. Spring加载properties文件的两种方式

    在项目中如果有些参数经常需要修改,或者后期可能需要修改,那我们最好把这些参数放到properties文件中,源代码中读取properties里面的配置,这样后期只需要改动properties文件即可, ...

  10. springmvc获取资源文件的两种方式(超简单)

    1 比如我们在sc目录下新建一个db.properties文件内容如下 DriverClass=com.mysql.jdbc.Driverurl=jdbc:mysql://localhost:3306 ...

随机推荐

  1. hibernate基础查询语句使用

    hibernate最新文档 项目仓库地址项目201102-hibernateSelect 数据准备 -- 创建数据表 drop table if exists t_book; create table ...

  2. 13. Docker-compose容器编排(详解说明)

    13. Docker-compose容器编排(详解说明) @ 目录 13. Docker-compose容器编排(详解说明) 1. Docker-compose容器编排概述 2. Docker-Com ...

  3. [BZOJ3771] Triple 题解

    <关于贫穷的樵夫拥有 40000 把斧头这件事>. 相当于是多项式乘法,但是得带容斥,具体自己看代码吧. #include<bits/stdc++.h> using names ...

  4. [ZJOI2015]幻想乡战略游戏 题解

    题目链接:\(luogu\) 声明变量: \(tr1/tr2\):原树/点分树,用链式前向星维护 求链长(包括求 \(lca\)) \(a_i\):原树欧拉序 \(st_{i,j}\):\(RMQ\) ...

  5. SpringBoot实现HandlerInterceptor拦截器的接口没有需要重写的方法也不报错是怎么回事

    以前实现HandlerInterceptor接口,总会提示需要实现3个方法(preHandle.postHandle.afterCompletion).现在没有出现提示.原因:这是Java8的新特性- ...

  6. 【COM3D2Mod 制作教程(1)】教程简介

    [COM3D2Mod 制作教程(1)]教程简介 教程来自:https://bdffzi.github.io/opencom3d2/#/Research/MakeMod(含配套视频) 前言 没有Mod ...

  7. sql 周岁计算

    select  FLOOR(DATEDIFF(DY, substring(身份证字段,7,4), GETDATE()) / 365.25)  age  from [表名]

  8. 洛谷P11380 [GESP202412 八级] 排队 题解

    数据太可恶了,竟然有重边!!! 题目传送门. 显然一道简单图论题. 把 \(a_i\) 和 \(b_i\) 的关系想象成一条有向边,于是可以得出:如果 \(x\) 的出度大于 \(1\) 或者 \(x ...

  9. go、thinkphp8、webman数据读取并发测试、性能测试

    前期准备:本地搭建程序运行所需环境,分别编写go,thinkphp8和webman程序,确保程序运行正常,新建mysql的student表,模拟存储学生信息,共计3646条数据,分别使用go语言.th ...

  10. Qt 实现带阴影 无边框的QMessageBox

    Qt 实现带阴影的QMessagebox 在实际项目里面使用到了QMessageBox做一个弹窗,最开始是样式不是需要的样式,就去找了一下QMessageBox的样式表,一般来说可以使用findChi ...