tags:

views:

122

answers:

4

Hi all, I have a program that creates a file and writes to it using ofstream. I need the program to be able to parse command line parameters later on. But for some reason, it does not create a file when I drag-and-drop a file onto the compiled executable, even if the program doesn't involve any command line parameters at all. If the executable is run normally, it works. So I'm left totally confused. Here is the source:

#include <iostream>
#include <fstream>
using namespace std;

int main ()
{
    ofstream outfile;
    outfile.open("test.txt");

    if(outfile.is_open())
    {
        outfile << "Test";
        outfile.close();
    }
    else cout << "Unable to open file";

    return 0;
}

Does anybody have any ideas? I appreciate any help.

+1  A: 

You are not using the command line arguments at all. Recode your main() method to look like this:

int main(int argc, char** argv)
{
  if (argc != 2) 
  {
    cout << "Usage: blah.exe file" << endl;
    return 1;
  }
  ofstream outfile;
  outfile.open(argv[1]);
  if(outfile.is_open())
  {
    outfile << "Test";
    outfile.close();
  }
  else cout << "Unable to open file";
  return 0;
}

Be careful what you drop, your code rewrites the file contents.

Hans Passant
I should have clarified, I don't want to write to the file that I dragged in. I want to create a new file that has no relation to the dragged-in file and write to it, just for testing purposes.
kaykun
Then you can't use drag+drop of course. It is very unclear to me how you'd want to take advantage of D+D. Maybe you can use the directory of the file that got dropped?
Hans Passant
In the end I want the program to be able to have a file dragged onto it and have the program analyze it and generate another text file based on the dragged file, but a different filename. But for now, I'm trying to solve this simple problem because it won't let me create any file whenever any file gets dragged onto it.
kaykun
Well, you got the part where you get the file that needs to be analyzed. You can do whatever you want with the file that is created from the analysis results. Using a full path name is highly recommended. Take a look at the _splitpath() CRT function.
Hans Passant
A: 

you haven't specified a path for "test.txt" so it will try and create that file in the current working directory of the executable. This will be different when the exe is invoked by dropping a file on it than it is when you run the program normally.

Try giving "test.txt" a full path and see if that works.

edit: To write your output file to the path that contains the exe, you would use

GetModuleFileName(NULL, ...) to the the full path of the exe, then PathRemoveFileSpec to strip off the exe name, leaving just the exe path then PathCombine to append test.txt to the exe path

John Knoeller
I've tried it with all files in the same directory - it still doesn't work.
anon
Sound like main isn't even getting invoked. Id add a call to DebugBreak(), at the top of main to see if you are even getting there.
John Knoeller
Thanks, but changing it to "C:\text.txt" gives me the program error "Unable to open file".
kaykun
don't forget that you have to double your \\ inside a string literal"c:\\text.txt"
John Knoeller
A: 

Since you have not specified a path, the file, test.txt, will be saved to the default path. Just bring up a command prompt (i.e. run cmd.exe) and the command prompt will show you the default path. The file should be in this directory.

You can change the default path by editing the HOMEDRIVE & HOMEPATH environment variables.

Also, you should note the other answers. You should be using argc/argv to specify the output file.

Mike Thompson
Thank you. If I wanted to create a file under the same directory as the executable (which would vary on different computers) and also under a different filename as the dragged file how would I handle that?
kaykun
+1  A: 

The following code does what the OP wants:

#include <iostream>
#include <fstream>
using namespace std;

int main ( int argc, char ** argv )
{
    cout << argv[1] << endl;
    ofstream outfile;
    outfile.open("testzzzzzzz.txt");

    if(outfile.is_open())
    {
        outfile << "Testzzzzz";
        outfile.close();
        cout << "wrote file"<< endl;
    }
    else cout << "Unable to open file";

    string s;
    getline( cin, s );
    return 0;
}

It allows drag and drop, but doesn't use the dropped file name in the file open. When you drop a file in it, you get the message

"wrote file"

Unfortunately, at the moment I have no idea where it wrote the file - not in the current directory, definitely. Just going to do a search...

Edit: It creates it in your Documents and Settings directory. So to put it in the current directory, you probably need to explicitly prefix it with "./", but I havent't tested this - I leave it as an exercise for the reader :-)

anon
Thanks, but outfile.open("./test.txt"); still creates the file in the Documents and Settings directory. Any suggestions?
kaykun
Extract the path from the dropped file and use that for the path for the new one, is all I can think of. This seems pretty bizarre behaviour, but I suppose one should never be suprised by Windows.
anon
@Kaykun: where do you want it to put the file?
John Knoeller
I want to create the new file in the same directory as the executable, and as a different filename than the dropped file.
kaykun
You can get the full path of the .exe by calling the Win32 API `GetModuleFilename()`, pass NULL as the first parameter. Strip off everYthing after the last \ and you have the exe path.
John Knoeller
This might be too much to ask, but could you explain the process of stripping off everything after the last \? I can get the executable path through argv[0] passed in main().
kaykun