Virtual Files are opened from Temporary Internet Files - c++

I have created a namespace extension that is rooted under Desktop. The main purpose of the extension is to provide a virtual list of ZIP files that represent a list of configurable directories. When the user clicks one of the those items the contents of the related directory are zipped in place and the resulting ZIP file is stored in a cache folder.
All this works well aside a minor issue. If we go to Windows Explorer, open the extension and double click an item the opened file is the one from the cache. [CORRECT]
If on the other hand we open it by an Open Dialog the opened file is one from a Temporary Internet files directory. [INCORRECT]
What do I have to change for the Open Dialog (when used for example trough notepad.exe) to open the file from the cache folder and not from Temporary Internet files. I have tried to send allways the qualified file name in IShellFolder::GetDisplayNameOf but without any luck.

It sounds like you are not passing in the correct initial directory (in the lpstrInitialDir or lpstrFile parameter of your OPENFILENAME struct).
Enter your cache directory in lpstrInitialDir and leave lpstrFile blank and it should work.

The problem was fixed by masking SFGAO_FILESYSTEM in the attributes returned by implementation of interface method IShellFolder::GetAttributesOf.

Related

QT5 - Detecting when new files are added to a directory and retrieving their path

My problem is relatively simple. I have an application where I need to monitor a particular folder (the downloads folder, in my case) for added files. Whenever a file is added to that folder, I want to move that file to a completely different directory. I have been looking at QFileSystemWatcher; however, none of the signals it provides seems to be ideal for my situation.
Here is my current code:
connect(&m_fileWatcher, &QFileSystemWatcher::directoryChanged, this, &FileHandler::directoryChanged);
void FileHandler::directoryChanged(const QString &dir)
{
qDebug() << "File changed...." << string;
// Some other logic
}
This signal only gives me a string to work with which is the directory that witnessed a change. I don't know what kind of change took place (add, rename, or delete), and I also have no idea which file has changed.
I understand that I could store all of the files in the directory in some sort of data structure and do some other logic when this signal is emitted, but that doesn't seem very performant in this case since I'm dealing with the user's downloads folder (which could contain thousands of files).
How can I make this work? Should I refer to a different helper class provided by QT, or is there some other way I can do this while utilizing QFileSystemWatcher? I'm simply just looking for ideas.
Thank you.
You’ve hit the limit of what the underlying OS provides: notification of change to the content of a directory.
If you wish to identify the file:
deleted you must have a prior list of files available for compare
added same as deleted
modified loop through the directory for the file with the most recent last modified date
IDK if you wish to use any specific filename container class from Qt or just a std::vector <std::filesystem::path> or the like for your cached folder contents.
QFileSystemWatcher only notifies you that a change happened, but not the details of what was changed. So you will have to resort to OS-specific APIs to get the details. For instance, on Windows, you can use ReadDirectoryChangesW() instead of QFileSystemWatcher.

toad locks folders from editing

Say I have test.sql opened in Toad and I close it. It seems Toad still 'looks' at the location of this file. Namely, after closing it, I can edit the file itself, but not the folder it is in, as attempts to do so result in the error message "The action can't be completed because the folder or a file in it is open in another program".
Closing the file doesn't help, ending the connection in which I opened it doesn't help. But closing Toad does the trick, so I'm guessing Toad still has the location of the file memorized.
My issue is that I do not want to close Toad to edit the name of the folder. Does anyone know if this is possible? Is there for example an overview of which locations are in use/looked at by Toad?
You can't delete the folder if it is Toad's current directory. As a workaround you can browse to a new folder location in a Toad open dialog. You may need to actually open a file from that new location. As I Google it there's a property of the open dialog used to not change the current directory. It's too late to change for the release underway (12.10), but I'll log a bug report to revisit this for the next release of Toad.
I had the same issue in 12.0.0.61 after exporting a data set. I tried opening a random file from another location, but that did not work in my case.
One workaround that I did find to be successful is to open the FTP utility and manually change the current folder. When opening the FTP utility in TOAD, the "local system" location will default to the current folder. In my case, I just went up a level and that releases the hold on the folder I'm trying to modify.

GetFileAttributes treat normal file as hidden file during frequent rename action

I am facing some issues with this function GetFileAttributes().
I am using C++ to get windows OS notifications and process them. For a particular case of frequent rename action on a single file, some times we are getting FILE_ATTRIBUTE_HIDDEN for those file. I am using Windows 7 Profession Service Pack 1.
Assume I have a pdf file say test.pdf. We are monitoring a directory say (D:\Test) using automatic directory monitoring in windows os. I am renaming the file (D:\Test\test.pdf) frequently as test1.pdf, test12.pdf, test123.pdf and so on.
I got rename notifications for each of the above actions. We used to check the file attributes for each notifications and if it is hidden file, we won't process further. While checking the file attributes, some times it shows as FILE_ATTRIBUTE_HIDDEN for the file. Is there any known issue with GetFileAttributes() ?
Is there any other thing I could try instead of GetFileAttributes ?

Qt C++: Moving a file, source and destination paths are on different drives

I want to move a file from a folder (say on Drive C) to another folder (say on Drive D) in C++. If, the file is already present in the destination folder, it should overwrite that. How can I achieve it with C++ std libraries or Qt?
I found "rename" method, but I'm not sure that it will work if paths are on different drives. Moreover, what is the platform dependency?
Just use QFile::rename(). It should do approximately the right thing, for most purposes. C++ standard library does not have a inter-filesystem rename call I think (please correct me in comments if I am wrong!), std::rename can only do move inside single filesystem.
However, normally the only (relevant) atomic file operation here is rename within same file system, where file contents are not touched, only directory information changes. I'm not aware of a C++ library which supports this, so here's rough pseudocode:
if basic rename succeeds
you're done
else if not moving between file systems (or just folders for simplicity)
rename failed
else
try
create temporary file name on target file system using a proper system call
copy contents of the file to the temporary file
rename temporary file to new name, possibly overwriting old file
remove original file
catch error
remove temporary file if it exists
rename failed
Doing it like this ensures, that file in new location appears are a whole file at once, and worst failure modes involve copying the file instead of moving.

Cannot access INI files in "Program Files"

I wrote this C++ application that needs to check an INI file (“preference.ini”), and eventually modify it (e.g. if the user does not want to see the introduction form anymore). I created it in WinXP, and it works fine on the system where I compiled it (in many locations, including “Program Files”).
Problem:
In Win 7, it works fine if I put the complete program folder under “C”:\” (e.g. “C:\MyProgram”), but if I put it in “C:\Program Files (x86)\MyProgram”, it just retrieves some mysterious data (values not present in my INI file). When I change some settings and save them to file, it (apparently) save the changes (get no errors, but the changes are not there when I go and open the file...
I had some similar issue on a system with another WinXP system (not the one where I compiled it.
I used 'getcwd' to define the path at runtime, and I verified that it is getting it right, even under "Program Files (x86)":
char currentPath[MAXPATH];
getcwd(currentPath, MAXPATH);
std::string licensePath(currentPath);
licensePath.append("\\dat\\preference.ini");'
Any ideas? Thanks in advance for your help.
The answer is as #Kirill has already said - Win7 won't let you write data into Program Files unless you have higher than normal permissions (Run as Administrator). In this case it may be redirecting your file writes so that they still apear to work, but the data itself is not stored in Progam Files.
To add to his answer: In general (unless you want to run your app as an administrator), you should not write any program data to the Program Files folder.
Application settings should be stored in one of the AppData folders. You can get to your user's appdata manually by going to your start menu Search box (Vista/Win7) and typing %appdata%.
To find this location in your code, use SHGetFolderPath with CSIDL_APPDATA (current user) or CSIDL_COMMON_APPDATA (all users).
It could be related to that Windows use virtualization of the file system. You could read here about it. Check if your INI file is located in <root>\Users\<User_name>\AppData\Local\VirtualStore.
Seems to me that the licensePath: getcwd() + "\\dat\\preference.ini" is not what you would expect.
Log this value (console or in a log file) and see what exactly is the value of licencePath is when running you program from different folders.
This article is about game development but has the best description of how and why this happens that I've been able to find
http://msdn.microsoft.com/en-us/library/ee419001(VS.85).aspx
This paragraph from the article describes what is happening most likely -
Attempting to create or write a file
or directory under a folder which does
not grant write permission to the
process will fail under Windows Vista
if the application does not have
administrative privileges. If your
32-bit game executable is running in
legacy mode, because it did not
declare a requested execution level,
its write operations will succeed, but
they will be subjected to
virtualization as described in the
section "UAC Compatibility with Older
Games" later in this article.