Does QFileInfo have special handling for .lnk files on Windows? Can it be disabled?
-
Hi
In my opinion It is super bad idea to try to hijack windows .lnk extension.
Its handled at file system level and you risk user running a tool to remove
dead links and it might remove all of yours.
Since its not valid .lnk binary files, i would really recommend just using other extension. -
@koahnig said in Does QFileInfo have special handling for .lnk files on Windows? Can it be disabled?:
Did you checkout the behaviour of QFileInfo on windows as described in the Detailed description section?
What you describe does not match the description there.
I have checked it out, and I noticed that it doesn't match what I'm, observing, that's exactly why I opened this discussion.I can confirm that QFileInfo::exists return false for an existing text file with .lnk extension that's not a valid link file.
-
@mrjj said in Does QFileInfo have special handling for .lnk files on Windows? Can it be disabled?:
Hi
In my opinion It is super bad idea to try to hijack windows .lnk extension.
Its handled at file system level and you risk user running a tool to remove
dead links and it might remove all of yours.
Since its not valid .lnk binary files, i would really recommend just using other extension.Hi. I agree with you entirely, and you've raised an interesting concern, thanks. I'll fix the problem at hand by not using .lnk extension, but I'm concerned with the behavior of my file manager program when the user attempts to copy or move a valid .lnk. According to the Qt docs, it should do the right thing, i. e. copy the link file instead of copying the target. But according to the docs, exists shouldn't return false in my case, so the docs are wrong. I wonder where else the docs may be wrong.
-
Hi
Yes it does seems a bit odd.
RunningQFileInfo fi("e:/therealfile.txt.lnk"); qDebug() << "exists" << fi.exists(); qDebug() << "link" << fi.isSymLink(); qDebug() << "real file" << fi.symLinkTarget();
exists false
link true
real file ""Which is not what i expected reading the docs as real file is there.
so i was expecting
exists true
link true
real file "therealfile.txt"This is Qt 5.10.1.
What version are you on ? -
@mrjj said in Does QFileInfo have special handling for .lnk files on Windows? Can it be disabled?:
This is Qt 5.10.1.
What version are you on ?Aha! I was about to move to a sample demo program but you were faster. So not only does it work unexpectedly for broken .lnk files, it also works unexpectedly for valid links as well.
I'm using Qt 5.11.1. Will also try 5.9.6 in a moment.
-
Tested on Qt 5.9.6. QFileInfo("textfile.lnk").exists() also returns false for an existing file that's not actually a Windows link.
-
@Violet-Giraffe
Docs says
Returns true if the file exists; otherwise returns false.
Note: If the file is a symlink that points to a non-existing file, false is returned.so it dont seem to be working as advertised.
Note
you did useQFileInfo("c:\\fullpath\\textfile.lnk").exists() ?
-
Right, I missed that bit about
exists()
, this is the intended behavior.
So, is there some way to turn off this special handling of links? Some secret attribute, perhaps? It really messes up my program. -
@Violet-Giraffe
Hi
Browsing the source
https://code.woboq.org/qt5/qtbase/src/corelib/io/qfileinfo.cpp.htmlI dont see any options to allow that.
Also for real .lnk files, its handled at lower level than Qt by windows. -
Thanks.
Are you saying that there's no way to query real info for .lnk files on Windows? I don't quite believe that, Explorer and Total Commander display them properly, with proper size and all. Both valid and invalid links. -
@Violet-Giraffe
Nope, im saying its odd that even running the sample from QFileInfo docs
does not give the results the sample comments suggests. At least not for me.
Explorer is using native api calls which surely works.
I dont what Total Commander uses but most likely not Qt. -
@mrjj said in Does QFileInfo have special handling for .lnk files on Windows? Can it be disabled?:
Also for real .lnk files, its handled at lower level than Qt by windows.
I was referring to this part of your reply, which I probably misunderstood. Never mind that.
-
@Violet-Giraffe
Oh, ok.
well Windows resolves those links on file access to make it transparent to all application.
So its very tied to the OS. -
@mrjj Hi,
I'm stuck here and the implementation of QFileInfo over lnk files is really broken : Violet-Giraffe was talking about a real problem. What's inside the file should not be a Qt concern, lnk files are not symlinks, they are binary equivalent of the .desktop files on Linux, they are not filesystem levels : they are just files that can be placed on any filesystem and edited with any file editing software.Details and context:
I'm doing file listing databases with names, checksums and dateTime of every file into some folder.When running the Linux build of the program on some folder (into an USB drive), the lnk files are handled correctly (as normal files), no matter what is the meaning of what's inside : name, checksum, size, and dateTime are correctly handled. I just had to say QDirIterator "QDir::Hidden" to enable file/folder names beginning with a dot.
On the Windows build of the same program, running on the same folder on the same USB Disk, I had to enable "QDir::System" to have QDirIterator able to see *.lnk files.
Then QFile is able to correctly do the open, read, and checksum of what's inside the file, but QFileInfo give me "0" size and QDateTime from "lastModified()" function is invalid (and has no reason to be : according to here https://doc.qt.io/qt-5/qfileinfo.html QFileInfo on the lnk file is supposed to give information about the lnk file, not about its target).Well, just to say : QFileInfo lnk special handling and interpretation for .lnk file is malfunctioning, as if the content of the file is not talking about a still existing target, QFileInfo functions that are supposed to only focus on the .lnk file itself (date and size at least) are broken and give wrong results.
Hope this testimony will help to solve it for future Qt versions !
Best regardsEDIT : just for information, if I rename the file, Qt stops messing up with the file. But as I'm writing a client application for file versioning and backup, I'm not going to change any file name : for now, I will have to ignore *.lnk files to be sure that no permanent warning / failure message about those files are displayed on the client's screen because of Qt inaptitude to handle them correctly.
QFile::size() also fails (while QFile::open() / read() is working... strange !). -
Hi
Just for completeness.
What Qt version did you test with? -
@jrflop If rename the file work, maybe you can create a temporary file by QTemporaryFile, read that temp file by QFileInfo and then let the QTemporaryFile delete the temp file for you?
-
@mrjj Hi, it's Qt 5.13.0 (for Windows and Linux)
I found the problem is discussed here : https://stackoverflow.com/questions/53411886/qfileinfo-size-is-returning-shortcut-target-size
I'm in the case when the file size is returning zero.As a working workaround, Instead of using Qt functions for collecting files information, I'm using :
CONFIG += c++17 LIBS += -l"stdc++fs" #include <filesystem> record.size = std::filesystem::file_size(record.path.toStdString()); std::filesystem::file_time_type time = std::filesystem::last_write_time(record.path.toStdString()); //eeeww... !
I will now try to convert std::filesystem::file_time_type time to QDateTime (as I'm using Qt for SQLite databases (disk and ram ones) to have faster operations of file database search / comparison). I will have to care about timezone so every parameter of the QDateTime will be correctly set.
Those std functions are pretty new to c++ so it works with msvc2017_32 and msvc2017_64 but on Windows, when using mingw73_64, #include <filesystem> isn't even recognized :/
On Linux I had to add LIBS += -l"stdc++fs" because of link errors like : undefined reference to `std::filesystem::file_size(std::filesystem::__cxx11::path const&)'Well I have to say I love using Qt for all the code so that it easier to read (and to setup) : I'm happy to find working std::filesystem functions but let's face it : std functions are ugly, I mean for readability and typing by memory without looking on the Internet at each line, it really is a carnage :
- QDateTime dateTime = fileInfoFinder.lastModified();
vs - std::filesystem::file_time_type time = std::filesystem::last_write_time(record.path.toStdString());
Those who already used std::high resolution clock to measure milliseconds or microseconds probably know how much Qt is easier to write, remember and read.
At side of this little inaptitude with *.lnk files information, thanks anyway for the great work.
Best regards,
A convinced Qt/C++ developer :) - QDateTime dateTime = fileInfoFinder.lastModified();
-
QDateTime dateTime = fileInfoFinder.lastModified();
vs
std::filesystem::file_time_type time = std::filesystem::last_write_time(record.path.toStdString());It's only longer because you're making it longer :)
First, you can always omit the namespace by doing "using namespace std::filesystem;", or just alias it to something short, such as "namespace fs = std::filesystem;"
Second, you're writing out the variable types which is unnecessary; just use auto.
Third, you're only having the .toStdString() because you're mixing Qt and std; last_write_time() can take a filesystem::path directly.
So now we have:auto dateTime = fileInfoFinder.lastModified();
vs
auto dateTime = last_write_time(myFilePath);(Or more likely with the std approach, one would be using the cached fs::status or fs::directory_entry types rather than paths since checking multiple properties don't incur additional internal system calls: "auto dateTime = myFileItem.last_write_time();" );