So I have a Qt program that saves files among other things. I saved a few files in my C:/ directory. When I look for the file in windows explorer, cygwin, or my command prompt, I cannot find the file. I checked my folder options and those look fine. Despite not being able to find the file, when I need to load a file in my Qt program, the program is able to find the file. Only my program is able to find the file, windows cannot. I am logged in as an administrator, but could this possibly have something to do with permissions?
Also, it may be worth noting that when I save files in c:/users/me/Documents/folder/folder I don't seem to have an issue.
Code that saves file:
QString saveFileName = QFileDialog::getSaveFileName(this,"Select the file you wish to save to.","","");
QFile saveFile(saveFileName);
if(saveFile.open(QIODevice::WriteOnly))
{
QTextStream stream(&saveFile);
QString stringToSaveToFile;
stream << stringToSaveToFile;
saveFile.close();
}
else
{
QMessageBox::warning(this, "Error", "Cannot open file.");
}
Code that opens file:
QString selectedFile = QFileDialog::getOpenFileName(this, "Select a .pro file.", "", tr("Profile file (*.pro);;All (*.*)"));
QString fileContents;
QFile file(selectedFile);
if (file.open(QIODevice::ReadOnly) | (QIODevice::Text))
{
QTextStream in(&file);
fileContents = in.readAll();
}
else
{
QMessageBox::warning(this, "Error", "Unable to open file.");
}
Edit: Just tried this on a different computer. My computer has windows 8, the other computer had windows XP. I could not replicate the problem on the XP machine.
Edit:
I believe I have found what the issue is (http://answers.microsoft.com/en-us/windows/forum/windows_vista-files/windows-explorer-compatibility-files/5b377209-cfe4-4be6-959d-e1de4b8be16d), but I am still trying to find out how to resolve it.
The files I am trying to save to the c:/ directory are actually being saved in C:/users/username/AppData/Local/VirtualStore.
Is there a way to somehow override this?
For now my solution is to warn the user if they save in the C:/, C:/Program Files/, C:/Program Files (x86), or C:/Windows/ directories. All files saved in these directories actually get saved in C:/User/Current User/AppData/Local/VirtualStore/.
If anyone has a better solution let me know.
Even though you might be logged in as an administrator by default most programs are run in unelevated mode (basically, NOT as an administrator). Also by default unelevated programs do not have write access to the root directory on C: drive (same way they do not have permission to write in, for example, C:\Program Files\). This was not always the case - I do not remember exactly at the moment but I think write to program files was already protected in Windows XP, and C: became protected only afterwards, I think at least since Windows 7? Anyway, for compatibility reasons write to those protected directories is virtualized.
Try running your Qt application in elevated mode (right click -> Run as administrator, or right click -> Properties -> Compatibility -> Run this program as an administrator) if you want to write directly in C:\, but really, you shouldn't.
If you are really worried about users being confused by this, you can implement a check for write access - after user chooses location for the file, but before an actual write - and display a warning or let them choose another location.
Related
I have googled a lot but dint find any relative solution for my problem.
PROBLEM: I want to open .MTS file and its working find if its available in any directory. But if its in any package then my QFileDialog is not able to look into that package and select those .MTS files.
CODE:
auto filePaths = QFileDialog::getOpenFileNames(this, "Open Video File", lastOpenedPath, "*.MTS;*.mov");
qDebug() << "File Paths " << filePaths;
Now the .MTS files created under AVCHD(Advanced Video Coding High Definition) package default in Sony & Panasonic HD Camera, and I want to import/select that .MTS files.
HINT: QFileDialog is able to import/select those .MTS files in Windows machine, but fail to import/select in mac machine.
Highly appreciated any thoughts.
Thanks.
Well, if I understand what you want to do properly, I'm not sure that it's possible in Qt alone.
It did turn out to be easier than I expected to simply call in to Cocoa and NSOpenPanel to achieve what I think you're looking for.
Sample project is at: https://github.com/NSGod/widgetsOpenFileDialogCocoa
Basically, I renamed mainwindow.cpp to mainwindow.mm, then added an #import <Cocoa/Cocoa.h>:
#import <Cocoa/Cocoa.h>
void MainWindow::on_openFileButton_clicked()
{
NSOpenPanel *openPanel = [NSOpenPanel openPanel];
[openPanel setAllowedFileTypes:[NSArray arrayWithObjects:#"mts", #"mov", nil]];
[openPanel setAllowsMultipleSelection:YES];
[openPanel setTreatsFilePackagesAsDirectories:YES];
[openPanel setTitle:#"Open Video File"];
NSInteger result = [openPanel runModal];
QStringList stringList;
if (result == NSFileHandlingPanelOKButton) {
NSArray *URLs = [openPanel URLs];
NSLog(#"URLs == %#", URLs);
for (NSURL *URL in URLs) {
stringList += QString::fromNSString(URL.path);
}
// do something with stringList
qDebug() << "filePaths == " << stringList;
}
}
Included in the project is a fakeBundle.component directory, which will be treated as a bundle (or "package") by OS X. But by setting treatsFilePackagesAsDirectories to YES, you can have the NSOpenPanel treat it as a directory (which it really is, of course).
Here is an image showing how the Finder treats this fakeBundle.component directory as if it were a single file:
And here in the NSOpenPanel, it's being treated as a directory:
An OSX package is a:
File system directory that is normally displayed to the user by the Finder as if it were a single file. Such a directory may be the top-level of a directory tree of objects stored as files, or it may be other archives of files or objects for various purposes, such as installer packages, or backup archives.
This is akin to an .mst or .msi file on Windows. Just as with OSX packages you would not be able to open your specified file within one of these packages. Your system open dialog is in fact doing you a disservice by allowing you to see into them, as you cannot open said files.
Your work around is to copy the file out of the package externally to the program then open the copy of the file.
The file exists in the directory, and I've tried running Visual Studios in Administrator Mode. However, ifstream can not find the file I give to it.
Here is the code I am using:
std::ifstream instream;
instream.open("appdata.txt");
if (!instream)
{
std::cout << "Could not find appdata.txt!";
}
But I am always greeted with Could not find appdata.txt! when I run the program.
Here is a picture of my directory, for proof that I have it spelled correctly and it exists.
So, my question is, am I missing something so glaringly obvious that I am glazing over it each time I look? I can not figure out for the life of me why instream can not open appdata.txt.
This is a problem with current directory being set to something else than a dir where your file is (usually your home folder if executing from explorer).
Try executing the program from command line from directory where your file is.
EDIT
If you want to set the working directory to some specific location, check this: https://msdn.microsoft.com/en-us/library/aa363806.aspx
Add the file by right clicking on project name on visual studio interface.
This will keep your file in the right directory.
If you want to add in the directory by yourself, first add a file using the method I said above and the find which is the folder you should keep so that you can use that file by mentioning just the file-name. And then you can add your files in that folder.
I have inherited a project to work on and the initial build was developed on linux. I dont know if this matters or not but thought I would share it.
In order to debug the project on a windows machine I first use the CMakeGUI on win7 to create a Visual Studio Solutions file to open the project using Visual Studio 2013 and then set the startup project and build the project I am interested in. Up till now everything is okay. Now comes the confusing part.
On load the program is suppose to read a file lets call it in.dat and is declared in const char * inputFileName this variable is then passed through a class which attempts to open then file to obtain data.
fstream fs;
fs.open(inputFileName.c_str(), fstream::in);
if(!fs.is_open())
{
std::cout << "Cannot open input file!" << std::endl;
exit(0);
}
This where I am stumped...the file when placed in the debug folder for some reason cannot be opened i.e fs.is_open() returns false when I try debugging the application BUT if I cd directly into the debug folder of the project, outside of VS, and run the executable it runs as expected i.e fs.is_open() now returns true.
Your debugger's working directory defaults to your project's root directory and the binary is in the \debug subdirectory, resulting, in effect, to the path to the input file being wrong.
Set the debugger's working directory to \debug.
Here is more info on that:
https://msdn.microsoft.com/en-us/library/kcw4dzyf(v=vs.120).aspx
The following code throws a 110 Error on the EndUpdateResource call only when windows explorer is open at D:\test\output\ where the executable is being copied to:
std::ifstream in("C:\\Windows\\notepad.exe", std::ios::binary);
std::ofstream out("D:\\test\\output\\notepad.exe", std::ios::binary);
out << in.rdbuf();
in.close();
out.close();
Handle hUpdateRes = BeginUpdateResource(_T("D:\\test\\output\\notepad.exe"), FALSE);
EndUpdateResource(hUpdateRes, FALSE);
As long as I don't have that folder open in windows explorer it works fine. If I have it open it will throw an error. Also, if I do a CreateFile with read and write access before the BeginUpdateResource call it will work fine even if I have the output folder open. I am really confused and would appreciate any help. Thanks!
I disabled the on demand virus scanner on the machine and the code no longer throws an error.
It's all about directory's permissions for the files you're writing. At least it was for me. I was writing files on desktop, which had Read only attribute and was getting this error randomly. I solved it by simply creating a folder on desktop and writing files to it. So, the solutions:
1) Don't write files to system's directories.
2) Create a directory yourself
3) Edit directory's attributes. Take off read-only. To do it programmatically:
How to Remove the Readonly attribute of a File MFC
removing readonly from folder, its sub folders and all the files in it
Or combine all of them.
I have 2 questions to ask regarding opening files (any kind of files) using C++. I am currently working on a GUI program and I want to add a changelog in txt form. Also I want a menu in my program to open that changelog.txt with the default text editor every user has installed or to simply put it to open that text file. Please keep in mind that I want to open the file for display NOT in the program for input/output.I know I can do that using
system("notepad.exe filepath.txt");
or to open them with the preset program:
system("filepath.txt");
The problem is that both of those open a command line behind the notepad. I know there is another command to open files using Win32 API called CreateProccess() but my compiler doesn't recognise that command (OpenWatcom W32).
So here are my questions:
1) Is there any other command to open files or is there a way to stop the command line from opening when using system command?
2) How do you define in Windows that the text file is in the current program folder? I mean instead of giving the entire filepath which will change from user to user is there any way to "tell" the program that the file is always on the current folder that the program is in?
I am sorry for any errors, if you want any clarification please let me know.
CreateProcess would be the wrong function to use here. That would require you to decide which process to run. The user may prefer to use a text editor other than Notepad, I know I do! The right way to do this on Windows is to ask the shell to open the file with whatever program the user has associated with the file. The ShellExecute function does this.
Call it like this:
ShellExecute(
MainWindowHandle,
"open",
FullyQualifiedTextFileName,
NULL,
NULL,
SW_SHOWNORMAL
);
You will need to include the Shellapi.h header file and link to the Shell32.lib library. If your compiler does not include these files, and I would be surprised if that was the case, then you can get them from the Platform SDK. That said, if you are serious about programming on Windows you should get hold of a tool that gives you access to the Windows API.
I do recommend that you use a fully qualified path for a task like this. Since your text file is located in the same directory as the executable you should simply join that directory to your text file's name. Get hold of the full path to the executable by calling GetModuleFileName passing NULL for the hModule parameter.