So this string I showed will be empty if the OS is not windows 10, you still have to add it to a legacy path , but it is not clear if the location you pin-pointed is the proper way to do it as maybe there would be other calls to file.getFullPathName() that would not get this prefix.
It would be more appropriate to apply this patch to juce::File instead, and once and for all.
Also it should preferably cache the long filename prefix in an opaque static string to call the statistics class only once.
in juce::File there is an internal “fullPath” member variable, this one should be once and for all prefixed with this longFilenamePrefix string I showed upper and it would not break other OSes.
EDIT: even better if you would add this prefix in
String File::parseAbsolutePath (const String& p)
It would be used everywhere now including the first fullPath internal string assignment.
Maybe try this new version for parseAbsolutePath:
String File::parseAbsolutePath (const String& p)
{
if (p.isEmpty())
return {};
#if JUCE_WINDOWS
static juce::String longFilenamePrefix(juce::SystemStats::getOperatingSystemType() >= juce::SystemStats::Windows10 ? "\\\\?\\" : "");
// Windows..
auto path = normaliseSeparators (removeEllipsis (p.replaceCharacter ('/', '\\')));
if (path.startsWithChar (getSeparatorChar()))
{
if (path[1] != getSeparatorChar())
{
/* When you supply a raw string to the File object constructor, it must be an absolute path.
If you're trying to parse a string that may be either a relative path or an absolute path,
you MUST provide a context against which the partial path can be evaluated - you can do
this by simply using File::getChildFile() instead of the File constructor. E.g. saying
"File::getCurrentWorkingDirectory().getChildFile (myUnknownPath)" would return an absolute
path if that's what was supplied, or would evaluate a partial path relative to the CWD.
*/
jassertfalse;
path = File::getCurrentWorkingDirectory().getFullPathName().substring (0, 2) + path;
}
}
else if (! path.containsChar (':'))
{
/* When you supply a raw string to the File object constructor, it must be an absolute path.
If you're trying to parse a string that may be either a relative path or an absolute path,
you MUST provide a context against which the partial path can be evaluated - you can do
this by simply using File::getChildFile() instead of the File constructor. E.g. saying
"File::getCurrentWorkingDirectory().getChildFile (myUnknownPath)" would return an absolute
path if that's what was supplied, or would evaluate a partial path relative to the CWD.
*/
jassertfalse;
return File::getCurrentWorkingDirectory().getChildFile (path).getFullPathName();
}
#else
// Mac or Linux..
// Yes, I know it's legal for a unix pathname to contain a backslash, but this assertion is here
// to catch anyone who's trying to run code that was written on Windows with hard-coded path names.
// If that's why you've ended up here, use File::getChildFile() to build your paths instead.
jassert ((! p.containsChar ('\\')) || (p.indexOfChar ('/') >= 0 && p.indexOfChar ('/') < p.indexOfChar ('\\')));
auto path = normaliseSeparators (removeEllipsis (p));
if (path.startsWithChar ('~'))
{
if (path[1] == getSeparatorChar() || path[1] == 0)
{
// expand a name of the form "~/abc"
path = File::getSpecialLocation (File::userHomeDirectory).getFullPathName()
+ path.substring (1);
}
else
{
// expand a name of type "~dave/abc"
auto userName = path.substring (1).upToFirstOccurrenceOf ("/", false, false);
if (auto* pw = getpwnam (userName.toUTF8()))
path = addTrailingSeparator (pw->pw_dir) + path.fromFirstOccurrenceOf ("/", false, false);
}
}
else if (! path.startsWithChar (getSeparatorChar()))
{
#if JUCE_DEBUG || JUCE_LOG_ASSERTIONS
if (! (path.startsWith ("./") || path.startsWith ("../")))
{
/* When you supply a raw string to the File object constructor, it must be an absolute path.
If you're trying to parse a string that may be either a relative path or an absolute path,
you MUST provide a context against which the partial path can be evaluated - you can do
this by simply using File::getChildFile() instead of the File constructor. E.g. saying
"File::getCurrentWorkingDirectory().getChildFile (myUnknownPath)" would return an absolute
path if that's what was supplied, or would evaluate a partial path relative to the CWD.
*/
jassertfalse;
#if JUCE_LOG_ASSERTIONS
Logger::writeToLog ("Illegal absolute path: " + path);
#endif
}
#endif
return File::getCurrentWorkingDirectory().getChildFile (path).getFullPathName();
}
#endif
while (path.endsWithChar (getSeparatorChar()) && path != getSeparatorString()) // careful not to turn a single "/" into an empty string.
path = path.dropLastCharacters (1);
// Add long prefix only once in Windows 10:
#if JUCE_WINDOWS
if (longFilenamePrefix.isNotEmpty() && !path.startsWith(longFilenamePrefix))
path = longFilenamePrefix + path;
#endif
return path;
}
EDIT2: note the if condition in the end to keep compatibility with other OS’es and concat only once.
EDIT3: Finally, you should test more as I could test it does work for the Projucer app where I could visualize source code but there is a lot of other code you might want to check like revealInFinder() API and similar.