GetOpenFileName and system function call run time errors c++ win32 api - c++

I've been working on a simple windows program using Visual C++ 2010 express on a 64bit Windows 7 machine. So far I have simple menu with and an editable text area. I'm trying to allow the user select a media file (movie or music file) and play it using the default program.
When the user selects from the menu File->Play->File from Computer it runs the following code.
case ID_PLAY_FFC:
{
system("cd c:/windows/system32/&&cmd.exe");
FileOpen(hWnd);
system("cd c:/windows/system32/&&cmd.exe");
}
break;
The problem is that the first system call runs as expected. The second call tells me that "cmd.exe is not recognized as an internal or external command, operable program, or batch file". I've tried placing the second system call within the File Open function and it seems to work anywhere before GetOpenFileName but not after.
The only thing I really need to get the is file path so I was wondering if any one knew how to fix this problem or a better way to accomplish this?
code for FileOpen():
void FileOpen(HWND hwnd)
{
OPENFILENAME ofn; // common dialog box structure
char szFile[MAX_PATH]; // buffer for file name MAX_PATH = 260
HANDLE hf; // file handle
// Initialize OPENFILENAME
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hwnd;
ofn.lpstrFile = szFile;
// Set lpstrFile[0] to '\0' so that GetOpenFileName does not
// use the contents of szFile to initialize itself.
ofn.lpstrFile[0] = '\0';
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFilter = "All\0*.*\0Text\0*.TXT\0";
ofn.nFilterIndex = 1;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
// Display the Open dialog box.
//system("cd c:/windows/system32/&&cmd.exe"); will execute here.
if (GetOpenFileName(&ofn)==TRUE)
{
//system("cd c:/windows/system32/&&cmd.exe"); but not here.
hf = CreateFile(ofn.lpstrFile,
GENERIC_READ,
0,
(LPSECURITY_ATTRIBUTES) NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
(HANDLE) NULL);
if (hf == (HANDLE)-1)
{
MessageBox(NULL,"Could not open this file", "File I/O Error", MB_ICONSTOP);
return;
}
}
}

The GetOpenFileName() function changes the working directory and drive as part of it's operation. Your call to cd does not change the working drive and cmd.exe is still not in the working directory.
The solution depends on what exactly you're trying to do in the end, but you can specify the full path to cmd.exe (See the %COMSPEC% environment variable) and not rely on a command interpreter, or pass the OFN_NOCHANGEDIR flag to tell it not to clobber the working directory.
Note that there isn't any real reason for a (GUI) app to require a specific working path. You should fully qualify everything you can.

Calling system() starts a new process, so even if your cd commands were valid (which they are not), it would not matter because you would be changing the working directory of another process, not your app's process. To set the working directory of your app's process, use SetCurrentDirectory() instead of system(), eg:
case ID_PLAY_FFC:
{
SetCurrentDirectory(TEXT("c:/windows/system32/"));
FileOpen(hWnd);
SetCurrentDirectory(TEXT("c:/windows/system32/"));
}
break;
However, you don't need to do that manually because the OFN_NOCHANGEDIR flag of GetOpenFileName() automatically handles that internally for you. Whatever the calling process's working directory is, GetOpenFileName() will preserve it when OFN_NOCHANGEDIR is specified.
Try this:
case ID_PLAY_FFC:
{
FileOpen(hWnd);
}
break;
void FileOpen(HWND hwnd)
{
OPENFILENAME ofn; // common dialog box structure
TCHAR szFile[MAX_PATH+1]; // buffer for file name MAX_PATH = 260
// Zero out szFile so that GetOpenFileName does
// not use the contents to initialize itself.
ZeroMemory(szFile, sizeof(szFile));
// Initialize OPENFILENAME
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hwnd;
ofn.lpstrFile = szFile;
ofn.nMaxFile = MAX_PATH;
ofn.lpstrFilter = TEXT("All\0*.*\0Text\0*.TXT\0");
ofn.nFilterIndex = 1;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR;
// Display the Open dialog box.
if (GetOpenFileName(&ofn)==TRUE)
{
int ret = (int) ShellExecute(
hwnd,
NULL,
ofn.lpstrFile,
NULL,
TEXT("c:/windows/system32/"),
SW_SHOWNORMAL);
if (ret <= 32)
{
MessageBox(NULL, TEXT("Could not open this file"), TEXT("File I/O Error"), MB_ICONSTOP);
return;
}
}
}

Related

ifstream not opening filename from getopenfilename

Amateur programmer here. My problem today is that I am trying to load a .txt file in to be displayed in the edit box of a dialog box.
before I start with code: I can get it to work by SPECIFYING the file location and bypassing the load dialog from getopenfilename, and it works swimmingly. But when i obtain that file location from getopenfilename, i can't seem to work it.
The relevant code is:
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hDlg;
ofn.lpstrFile = szFile;
ofn.lpstrFile[0] = '\0';
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFilter = "All\0*.*\0Text\0*.TXT\0";
ofn.nFilterIndex = 1;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
if (GetOpenFileName(&ofn) == TRUE)
{
hf = CreateFile(ofn.lpstrFile, GENERIC_READ, 0, LPSECURITY_ATTRIBUTES)NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, (HANDLE)NULL);
ifstream inFile(ofn.lpstrFile);
if (!inFile)
MessageBox(0, "CAN'T OPEN FILE", "ALERT", MB_OK | MB_ICONWARNING);
else
{
string text;
while(getline(inFile, text));
inFile.close();
MessageBox(0, text.c_str(), "msg", MB_OK);
SetWindowText(editbox, text.c_str());
}
CloseHandle(hf);
hf = INVALID_HANDLE_VALUE;
I am a novice, but I have been wracking my brain and my google bar trying to figure this out.
It does not ever open via fstream.
The source of the problem is that you try to open the file with both Win32 API (CreateFile()) and with standard library (std::ifstream).
By looking at your CreateFile() call and at the documentation, one can see that you are passing 0 to the dwShareMode argument, whose description states:
If this parameter is zero and CreateFile succeeds, the file or device cannot be shared and cannot be opened again until the handle to the file or device is closed.
But, after that call, you proceed to try to open the file via std::ifstream, which fails due to the reason described above, and you are only checking if ifstream succeeds to open the file.
The issue can be avoided if you use only either CreateFile() or std::ifstream, not both.

Strange behaviour with GetOpenFileName dialog and opencv

I'm trying to use the open file dialog to allow the user of my program to select an image which will then be processed using opencv.
I have a function in which i open the dialog and try to load the image:
Mat load_image()
{
OPENFILENAME ofn; // common dialog box structure
TCHAR szFile[260]; // buffer for file name
HWND hwnd; // owner window
HANDLE hf; // file handle
// Initialize OPENFILENAME
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hwnd;
ofn.lpstrFile = szFile;
// Set lpstrFile[0] to '\0' so that GetOpenFileName does not
// use the contents of szFile to initialize itself.
ofn.lpstrFile[0] = '\0';
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFilter = L"All\0*.*\0Text\0*.TXT\0";
ofn.nFilterIndex = 1;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
// Display the Open dialog box.
if (GetOpenFileName(&ofn)==TRUE)
hf = CreateFile(ofn.lpstrFile,
GENERIC_READ,
0,
(LPSECURITY_ATTRIBUTES) NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
(HANDLE) NULL);
char filepath[260];
wcstombs(filepath, ofn.lpstrFile, 260);
cout << filepath << endl;
Mat src = imread(filepath);
//imshow("src", src);
return src;
}
The code you see here works, opens the dialog box and allows the user to choose a file. The filepath is then converted to string (to be passed into imread). The problem occurs when I try to interact with the image src.
For example, if I uncomment the 'imshow' line, GetOpenFileName will return 0 and the dialog box doesnt even open. This happens more than not, I cant actually access the image because everything I try causes this to happen.
In order for the function to work it is called like this:
load_image();
But if I try to assign an image ie:
img = load_image();
the same problem occurs. Help! What could possibly be causing this?
As it is mentioned in the previous comment, the CreateFile method locks the image file so cv::imread() is not able to access/read its content.
Try to avoid using of CreateFile, I see no reason of using it in your code, the following code is working well:
cv::Mat load_image()
{
cv::Mat outMat;
OPENFILENAME ofn; // common dialog box structure
TCHAR szFile[260]; // buffer for file name
// Initialize OPENFILENAME
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = NULL;
ofn.lpstrFile = szFile;
ofn.lpstrFile[0] = '\0';
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFilter = L"All\0*.*\0Text\0*.TXT\0";
ofn.nFilterIndex = 1;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
// Display the Open dialog box.
if (GetOpenFileName(&ofn) == TRUE)
{
char filepath[260];
wcstombs(filepath, ofn.lpstrFile, 260);
cout << filepath << endl;
outMat = cv::imread(filepath);
}
return outMat;
}
int main()
{
cv::Mat image = load_image();
cv::imshow("image", image);
cv::waitKey(-1);
return 0;
}
These are just things I notice in your code...so I don't expect this to work but maybe it will help.
imread is probably failing. You opened the file using CreateFile and locked it as a result of opening it (No Sharing Attributes. See CreateFile for more info). imread tries to open the file anyways so you don't need to create your own handle! Just use the file path received and call imread instead of using CreateFile.
Mat src;
if (GetOpenFileName(&ofn)==TRUE)
{
// Succeeded in choosing a file
char filepath[260];
wcstombs(filepath, ofn.lpstrFile, 260);
cout << filepath << endl;
src = imread(filepath);
}
Also if you don't have an hwnd then you should just set ofn.hwndOwner=NULL instead of arbitrarily setting it.
If you so choose to use CreateFile (maybe you wish to open it for manual read access for your own purposes outside of OpenCV), then make sure to call CloseHandle( HANDLE h ) on the file handle before you open the file again.

tinyxml load fails after using GetOpenFileName to retrieve xml filename

I was already using tinyxml 1 before I implemented the function GetOpenFileName in my code, so I know the load works whenever I give it a relative path or an absolute path.
I just don't understand why it doesn't work whenever the function GetOpenFileName executes first. I actually tried a few times to test and every time I executed that function, regardless of whether I used the filepath it gave me or not, tinyxml still wouldn't find the xml.
std::string tutName = getTutorialFilename();
if(tutName != "") {
std::cout << "Before replacing: " << tutName << std::endl;
boost::replace_all(tutName, "\\", "/");
bool loadTutorial = tutorial->loadTutorialSteps(tutName);
if(loadTutorial) {
std::cout << "success!" << std::endl;
} else {
std::cout << "failed: " << tutName << "to load" << std::endl;
}
}
The Function getTutorialFilename, which uses GetOpenFilename:
std::string getTutorialFilename() {
OPENFILENAME ofn; // common dialog box structure
char szFile[260]; // buffer for file name
HWND hwnd; // owner window
HANDLE hf; // file handle
// Initialize OPENFILENAME
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hwnd;
ofn.lpstrFile = szFile;
// Set lpstrFile[0] to '\0' so that GetOpenFileName does not
// use the contents of szFile to initialize itself.
ofn.lpstrFile[0] = '\0';
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFilter = "XML\0*.xml*\0All\0*.*\0";
ofn.nFilterIndex = 1;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
// Display the Open dialog box.
if (GetOpenFileName(&ofn)==TRUE) {
hf = CreateFile(ofn.lpstrFile,
GENERIC_READ,
0,
(LPSECURITY_ATTRIBUTES) NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
(HANDLE) NULL);
std::string tutorialFilename(szFile);
return tutorialFilename;
}
return "";
}
I know it finds the tutorialFilename with no extra spaces as I've ran the debugger on that, but I still can't understand why tinyxml fails to load.
I figured out the issue. TinyXML was outputting the error 13 - permission denied due to CreateFile blocking access to the file. I deleted that function because I don't need it.

Handle multiple file selection

I have the following code:
void OpenJpgFile(HWND hWnd)
{
OPENFILENAME ofn;
wchar_t szFileName[17*MAX_PATH] = L"";
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hWnd;
ofn.lpstrTitle = L"Selecione as fotos que deseja adicionar...";
ofn.lpstrFilter = L"Arquivos JPEG (*.jpg)\0*.jpg\0Todos os Arquivos (*.*)\0*.*\0";
ofn.lpstrFile = szFileName;
ofn.nMaxFile = MAX_PATH;
ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_ALLOWMULTISELECT;
ofn.lpstrDefExt = L"jpg";
if(GetOpenFileName(&ofn))
{
//Test
MessageBox(hWnd,ofn.lpstrFileTitle,L"TESTE",NULL);
if(gpBitmap)
{
delete gpBitmap;
}
gpBitmap = new Bitmap(szFileName);
InvalidateRect(hWnd, NULL, TRUE);
UpdateWindow(hWnd);
}
}
What I wanted to know is how can I get the name of all files the user has selected...
All I can get is the path to the folder... is there an array that keeps the file names?
Per the documentation of OFN_ALLOWMULTISELECT when OFN_EXPLORER is also specified, lpstrFile will contain the directory followed by the names of the files, separated by null characters, and terminated with two adjacent null characters. When you call new Bitmap(szFileName) you are treating szFileName incorrectly - that is you pass it to a constructor that expects a standard single-null terminated string. Instead you have to process it more carefully to read past the initial null, and probably recreate your full file paths.
This string format happens to be the same format as used for REG_MULTI_SZ so, aside from not having to worry about missing final terminators, advice related to handling values of type REG_MULTI_SZ can help you here.
Note that to be fully general, you may also have to handle cases that require a larger buffer. See GetOpenFileName() with OFN_ALLOWMULTISELECT flag set for another angle on that

Save/Open Common Dialog boxes in win32 without MFC

How do you create the deafault Save/Open dialog boxes using pure unmanaged Win32 API ?
Following the guide here, the following code is executed when WM_CREATE message is handled in the message loop of the main window:
Ive included <Commdlg.h> also.
OPENFILENAMEA ofn;
char Buffer[300];
fill(Buffer, Buffer + 300, '\0');
ofn.lStructSize = sizeof(OPENFILENAMEA);
ofn.hwndOwner = hWnd;
ofn.lpstrFile = Buffer;
ofn.nMaxFile = 300;
ofn.Flags = OFN_EXPLORER;
ofn.lpstrFilter = NULL;
ofn.lpstrCustomFilter = NULL;
ofn.nFilterIndex = 0;
ofn.lpstrFileTitle = NULL;
ofn.lpstrInitialDir = NULL;
ofn.lpstrTitle = NULL;
out << GetOpenFileNameA(&ofn) << endl;
out << Buffer << (int)CommDlgExtendedError();
However, this code gives NO output whatsoever. Help?!
the following code is executed when WM_CREATE message is handled
Look in the Output window and observe the first-chance exception notification for 0xc0000005, an AccessViolation exception. There's a backstop in the Wow64 emulator that swallows exceptions while WM_CREATE is being dispatched.
The exception is caused by not fully initializing the OPENFILENAMEA structure. Quick fix:
OPENFILENAMEA ofn = {0};
And favor displaying the dialog before calling ShowWindow() instead of the WM_CREATE message handler.
The overall idea is right, but if you are passing the handle of the window you are creating as the owner, then it is not going to be initialized yet.
For diagnostics, consider creating variables to store the API function return values and examining them in the debugger.
It is also more convenient and less error-prone to initialize the structure to zero, instead of explictely zeroing out unneeded members, like this:
OPENFILENAME ofn = { 0 };
GetOpenFileName blocks (for a while), and then returns either TRUE if the dialog was closed by 'OK', or FALSE if it was cancelled.
The actual result (the directory/file path) can be read from the OPENFILENAME structure.
from https://learn.microsoft.com/en-us/windows/win32/dlgbox/using-common-dialog-boxes#opening-a-file we get a utf-16 version of this, with some small changes of mine:
OPENFILENAME ofn = { 0 }; // common dialog box structure
WCHAR szFile[260]; // buffer for file name
HWND hwnd; // owner window
HANDLE hf; // file handle
// Initialize OPENFILENAME
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hwnd;
ofn.lpstrFile = szFile;
// Set lpstrFile[0] to '\0' so that GetOpenFileName does not
// use the contents of szFile to initialize itself.
ofn.lpstrFile[0] = '\0';
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFilter = "All\0*.*\0Text\0*.TXT\0";
ofn.nFilterIndex = 1;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
// Display the Open dialog box.
if (GetOpenFileName(&ofn)==TRUE)
hf = CreateFile(ofn.lpstrFile,
GENERIC_READ,
0,
(LPSECURITY_ATTRIBUTES) NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
(HANDLE) NULL);