Winapi 确定两个目录名是否指向同一目录

Winapi 确定两个目录名是否指向同一目录,winapi,directory,Winapi,Directory,我有两个包含文件夹路径的字符串。有没有办法确定它们是否指向同一个位置?考虑到大小写不敏感、8.3文件名长度混乱、subst等因素,字符串比较似乎有点不可靠 举例来说,我如何确定这两个点指向同一个地方: String1 = "c:\Program Files\MyFolder\" String2 = "C:\PROGRA~1\MYFOLDER" 这是一个C#样本。如果你使用的是其他语言,那么想法也是一样的。使用kernel32.dll中的GetLongPathName和/或GetShortPat

我有两个包含文件夹路径的字符串。有没有办法确定它们是否指向同一个位置?考虑到大小写不敏感、8.3文件名长度混乱、subst等因素,字符串比较似乎有点不可靠

举例来说,我如何确定这两个点指向同一个地方:

String1 = "c:\Program Files\MyFolder\"
String2 = "C:\PROGRA~1\MYFOLDER"
这是一个C#样本。如果你使用的是其他语言,那么想法也是一样的。使用kernel32.dll中的GetLongPathName和/或GetShortPathName并比较它们:

 [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
 public static extern int GetLongPathName(
    [MarshalAs(UnmanagedType.LPTStr)]
    string path,
    [MarshalAs(UnmanagedType.LPTStr)]
    StringBuilder longPath,
    int longPathLength
    );

 [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
 public static extern int GetShortPathName(
    [MarshalAs(UnmanagedType.LPTStr)]
    string path,
    [MarshalAs(UnmanagedType.LPTStr)]
    StringBuilder shortPath,
    int shortPathLength
    );


function bool PathsAreEqual(string path1, string path2)
{
    StringBuilder shortPath1 = new StringBuilder(255);
    StringBuilder shortPath2 = new StringBuilder(255);
    GetShortPathName(path1, shortPath1, shortPath1.Capacity);
    GetShortPathName(path2, shortPath2, shortPath2.Capacity);

    return shortPath1.ToString().ToLower() == shortPath2.ToString().ToLower();

}

为了获得最佳性能,您应该将路径简化为规范形式。这是8.3(GetShortPathName)和小写。

以下代码适用于文件(包括硬链接)和目录(包括连接),但两个路径都必须有效

#include <windows.h>
#include <stdio.h>

BOOL ArePathsEqual(LPCTSTR path1,LPCTSTR path2) 
{
    BY_HANDLE_FILE_INFORMATION bhfi1,bhfi2;
    HANDLE h1, h2 = NULL;
    DWORD access = 0;
    DWORD share = FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE;

    h1 = CreateFile(path1,access,share,NULL,OPEN_EXISTING,(GetFileAttributes(path1)&FILE_ATTRIBUTE_DIRECTORY)?FILE_FLAG_BACKUP_SEMANTICS:0,NULL);
    if (INVALID_HANDLE_VALUE != h1) 
    {
        if (!GetFileInformationByHandle(h1,&bhfi1)) bhfi1.dwVolumeSerialNumber = 0;
        h2 = CreateFile(path2,access,share,NULL,OPEN_EXISTING,(GetFileAttributes(path2)&FILE_ATTRIBUTE_DIRECTORY)?FILE_FLAG_BACKUP_SEMANTICS:0,NULL);
        if (!GetFileInformationByHandle(h2,&bhfi2)) bhfi2.dwVolumeSerialNumber = bhfi1.dwVolumeSerialNumber + 1;
    }
    CloseHandle(h1);
    CloseHandle(h2);
    return INVALID_HANDLE_VALUE != h1 && INVALID_HANDLE_VALUE != h2 
    && bhfi1.dwVolumeSerialNumber==bhfi2.dwVolumeSerialNumber
    && bhfi1.nFileIndexHigh==bhfi2.nFileIndexHigh
    && bhfi1.nFileIndexLow==bhfi2.nFileIndexLow ;
}

void main() 
{
    BOOL bRet = ArePathsEqual("c:\\program files","c:\\progra~1");
    printf("ArePathsEqual: %d\n",bRet);
}
#包括
#包括
BOOL ArePathsEqual(LPCTSTR路径1、LPCTSTR路径2)
{
通过处理文件信息bhfi1、bhfi2;
句柄h1,h2=NULL;
DWORD访问=0;
DWORD share=文件共享删除文件共享读取文件共享写入;
h1=CreateFile(路径1,访问,共享,NULL,打开\u现有,(GetFileAttributes(路径1)&文件\u属性\u目录)?文件\u标志\u备份\u语义:0,NULL);
if(无效的句柄值!=h1)
{
如果(!GetFileInformationByHandle(h1和bhfi1))bhfi1.dwVolumeSerialNumber=0;
h2=CreateFile(路径2,访问,共享,空,打开\u存在,(GetFileAttributes(路径2)和文件\u属性\u目录)?文件\u标志\u备份\u语义:0,空);
如果(!GetFileInformationByHandle(h2和bhfi2))bhfi2.dwVolumeSerialNumber=bhfi1.dwVolumeSerialNumber+1;
}
闭合手柄(h1);
闭合手柄(h2);
返回无效的\u句柄\u值!=h1&&无效的\u句柄\u值!=h2
&&bhfi1.dwVolumeSerialNumber==bhfi2.dwVolumeSerialNumber
&&bhfi1.nFileIndexHigh==bhfi2.nFileIndexHigh
&&bhfi1.nFileIndexLow==bhfi2.nFileIndexLow;
}
void main()
{
BOOL-bRet=ArePathsEqual(“c:\\program files”,“c:\\progra~1”);
printf(“arepath-sequal:%d\n”,bRet);
}

您如何知道OP正在使用.net?好问题。如果不是的话,两个kernel32.dll函数仍然可以使用。不仅仅是路径必须有效,文件必须存在。回答得很好。为什么不在两种情况下(文件和目录)都使用
FILE\u FLAG\u BACKUP\u SEMANTICS
。@kobik:我记不太清楚了,在文件上使用它可能也没什么坏处(但它是目录所必需的)@Anders,谢谢你的评论。我已经阅读了文档,并注意到对于目录来说这是
必需的
,但是我认为对于文件来说使用
文件\u标志\u备份\u语义
会有开销,所以我假设您这样做是为了优化速度,但另一方面,我们有
GetFileAttributes
。我只是想知道,因为这确实有点道理:)