Detecting identical path names
-
Is there an Win32 API call for detecting different ways of naming the same physical file? That "
X:\projects\test\..\work\ch~1.gif
" and "\\Tyrus\MyShare\projects\WORK\Cha-Cha-Cha.gif
" actually refer to the same physical file? CheckedPathXXX
but no luck there. -
Is there an Win32 API call for detecting different ways of naming the same physical file? That "
X:\projects\test\..\work\ch~1.gif
" and "\\Tyrus\MyShare\projects\WORK\Cha-Cha-Cha.gif
" actually refer to the same physical file? CheckedPathXXX
but no luck there. -
Hi Mattias, Try using the WNetGetConnection Function[^] to get the name of the network resource associated with drive "X:" Hopefully it returns "\\Tyrus\MyShare\" Best Wishes, -David Delaune
-
I didn't even know there was a group of calls starting with
WNetXXXXX
... Anyway,WNetGetUniversalName
did half the trick convertingX:
into\\Tyrus\share
, but that call won't help me with short/long names, or upper/lower case, or relative paths. Was hoping for something likeArePathsReferringToTheSameFile
, but will manage with the above andPathMakePretty
or similar. [edit] Turns out thatWNetGetUniversalName
wasn't that perfect for my purpose, as it can't handle paths that are local paths (not on a network resource at all). Fixed by usingPathIsNetworkPath
, but I would rather not do all these conversions and checks manually...modified on Friday, September 11, 2009 8:28 AM
-
I didn't even know there was a group of calls starting with
WNetXXXXX
... Anyway,WNetGetUniversalName
did half the trick convertingX:
into\\Tyrus\share
, but that call won't help me with short/long names, or upper/lower case, or relative paths. Was hoping for something likeArePathsReferringToTheSameFile
, but will manage with the above andPathMakePretty
or similar. [edit] Turns out thatWNetGetUniversalName
wasn't that perfect for my purpose, as it can't handle paths that are local paths (not on a network resource at all). Fixed by usingPathIsNetworkPath
, but I would rather not do all these conversions and checks manually...modified on Friday, September 11, 2009 8:28 AM
Mattias G wrote:
...but that call won't help me with short/long names, or upper/lower case...
See
GetLongPathName()
,GetShortPathName()
, andStrCmpI()
."Old age is like a bank account. You withdraw later in life what you have deposited along the way." - Unknown
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
-
I didn't even know there was a group of calls starting with
WNetXXXXX
... Anyway,WNetGetUniversalName
did half the trick convertingX:
into\\Tyrus\share
, but that call won't help me with short/long names, or upper/lower case, or relative paths. Was hoping for something likeArePathsReferringToTheSameFile
, but will manage with the above andPathMakePretty
or similar. [edit] Turns out thatWNetGetUniversalName
wasn't that perfect for my purpose, as it can't handle paths that are local paths (not on a network resource at all). Fixed by usingPathIsNetworkPath
, but I would rather not do all these conversions and checks manually...modified on Friday, September 11, 2009 8:28 AM
Hi Mattias, It is the weekend and I am working on some personal projects. A thought occured to me while working on a CMFCShellTreeCtrl[^] derived class. The Explorer shell internally uses PIDL identifier lists[^] to uniquely identify files and folders. It should be possible to obtain a PIDL of both files and compare them for equality. Anyway, I thought of your post while working with PIDL. I guess its another option for you to consider. Best Wishes, -David Delaune
-
I didn't even know there was a group of calls starting with
WNetXXXXX
... Anyway,WNetGetUniversalName
did half the trick convertingX:
into\\Tyrus\share
, but that call won't help me with short/long names, or upper/lower case, or relative paths. Was hoping for something likeArePathsReferringToTheSameFile
, but will manage with the above andPathMakePretty
or similar. [edit] Turns out thatWNetGetUniversalName
wasn't that perfect for my purpose, as it can't handle paths that are local paths (not on a network resource at all). Fixed by usingPathIsNetworkPath
, but I would rather not do all these conversions and checks manually...modified on Friday, September 11, 2009 8:28 AM
You can do what JkDefrag does when evaluating paths for mount points etc. Get the short path and short name (to eliminate the relative paths), then get the long path and name. Do this for both files, then either do a case insensitive compare of the long path/name strings, or force the path/file strings to lower or upper case before the compare. Dave.
-
You can do what JkDefrag does when evaluating paths for mount points etc. Get the short path and short name (to eliminate the relative paths), then get the long path and name. Do this for both files, then either do a case insensitive compare of the long path/name strings, or force the path/file strings to lower or upper case before the compare. Dave.
Thanks for the input. Have been trying
IShellItem::Compare
, but can't get that to work unless files on the same share are specified the same way (\\share\path or X:\path).IShellItem::Compare
can handle differences in case, however. I'm usingSHCreateShellItem
to create the objects, and that call fails if I'm using a relative path such as \\share\bohoo\tada\..\tada\file.txt. As always, this could be due to user incompetence on my side, so feel free to check this one for errors:// ...
PIDLIST_ABSOLUTE pid1;
PIDLIST_ABSOLUTE pid2;
IShellItem* itm1;
IShellItem* itm2;pid1 = ILCreateFromPath(szPath);
SHCreateShellItem(NULL, NULL, pid1, &itm1);
ILFree(pid1);for(unsigned i = 0; i < m_rgGlossaries.size(); i++){
BSTR strPath;
// ...
pid2 = ILCreateFromPath(strPath);
SysFreeString(strPath);
SHCreateShellItem(NULL, NULL, pid2, &itm2);
ILFree(pid2);
itm1->Compare(itm2, SICHINT_ALLFIELDS, &nCmpResult);
itm2->Release();
if(nCmpResult == 0){
AfxMessageBox(_T("Hurrah"));
// ...
}
}// ...
Eagerly awaiting suggestions. Would prefer not to do lots of conversions and resolving on my own.
-
Thanks for the input. Have been trying
IShellItem::Compare
, but can't get that to work unless files on the same share are specified the same way (\\share\path or X:\path).IShellItem::Compare
can handle differences in case, however. I'm usingSHCreateShellItem
to create the objects, and that call fails if I'm using a relative path such as \\share\bohoo\tada\..\tada\file.txt. As always, this could be due to user incompetence on my side, so feel free to check this one for errors:// ...
PIDLIST_ABSOLUTE pid1;
PIDLIST_ABSOLUTE pid2;
IShellItem* itm1;
IShellItem* itm2;pid1 = ILCreateFromPath(szPath);
SHCreateShellItem(NULL, NULL, pid1, &itm1);
ILFree(pid1);for(unsigned i = 0; i < m_rgGlossaries.size(); i++){
BSTR strPath;
// ...
pid2 = ILCreateFromPath(strPath);
SysFreeString(strPath);
SHCreateShellItem(NULL, NULL, pid2, &itm2);
ILFree(pid2);
itm1->Compare(itm2, SICHINT_ALLFIELDS, &nCmpResult);
itm2->Release();
if(nCmpResult == 0){
AfxMessageBox(_T("Hurrah"));
// ...
}
}// ...
Eagerly awaiting suggestions. Would prefer not to do lots of conversions and resolving on my own.
I really cannot comment on the C++ code, I am mainly a ANSI C and MASM programmer. I am currently away from my development system and my laptop has no compiler or source code. At this week's end (Friday) I will send you the JkDefrag code that is used for this. It is interesting that JkDefrag is labled as C++ (JkDefrag.cpp), but contains only ANSI standard C coding. If you do not want to wait until Friday, Google JkDefrag 3.36 (4.0 is NOT open source), download the open source Zip, expand the Zip, and hunt for DefragOnePath in JkDefragLib.cpp. Dave.
-
I really cannot comment on the C++ code, I am mainly a ANSI C and MASM programmer. I am currently away from my development system and my laptop has no compiler or source code. At this week's end (Friday) I will send you the JkDefrag code that is used for this. It is interesting that JkDefrag is labled as C++ (JkDefrag.cpp), but contains only ANSI standard C coding. If you do not want to wait until Friday, Google JkDefrag 3.36 (4.0 is NOT open source), download the open source Zip, expand the Zip, and hunt for DefragOnePath in JkDefragLib.cpp. Dave.
Hi Dave, David here. I'm curious as to why you believe JkDefrag source code will solve this problem? 1.) JkDefrag uses DeviceIOControl to query local device drivers for NTFS-MFT and/or FAT disk cluster offsets. So he cannot possibly use these techniques for remote drives. 2.) If your eluding to the usage of GetVolumeNameForVolumeMountPoint then how will this help for non-mounted shares accessed with \\Server\\Path\\To\\File type URI? These paths do not have a mount point. 3.) If he needs to resolve relative paths into full paths he can use the GetFullPathName Function[^] and/or GetLongPathName Function[^]. So can you explain why you believe JkDefrag adds anything useful into this particular situation? Best Wishes, -David Delaune
-
Hi Dave, David here. I'm curious as to why you believe JkDefrag source code will solve this problem? 1.) JkDefrag uses DeviceIOControl to query local device drivers for NTFS-MFT and/or FAT disk cluster offsets. So he cannot possibly use these techniques for remote drives. 2.) If your eluding to the usage of GetVolumeNameForVolumeMountPoint then how will this help for non-mounted shares accessed with \\Server\\Path\\To\\File type URI? These paths do not have a mount point. 3.) If he needs to resolve relative paths into full paths he can use the GetFullPathName Function[^] and/or GetLongPathName Function[^]. So can you explain why you believe JkDefrag adds anything useful into this particular situation? Best Wishes, -David Delaune
David, As I mentioned, I do not have the source with me right now, but remembered that it did resolve path/name matches by a double transform (trying to match a path name with a mask containing wild cards including the case where a mount point when expanded to its full hardware path did match the mask). It is true that JkDefrag will not defrag an unmounted share. I think it will not even handle a share because the API can only handle local drives. Again, I do not have the source here right now, so can't check. Dave.