【经验】C++|利用 Windows API,通过文件句柄获取文件路径的两种方式
方法一
主要参考博客:根据文件句柄获得文件名(这篇超级清晰,就是有一点点小问题)
通过文件句柄获得文件路径(这篇不是很好用,但是思路大体是一致的)
主要思路:
- 根据
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
没有问题)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix