Windows控制台应用程序拖放问题

4

我有一个程序,使用ofstream创建文件并将内容写入其中。之后我需要让程序能够解析命令行参数。但是不知为何,即使程序中没有涉及到任何命令行参数,当我将文件拖动到已编译的可执行文件上时,它也无法创建文件。如果正常运行可执行文件,则可以正常工作。所以我感到非常困惑。以下是代码:

#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;
}

有人有什么想法吗?我会感激任何帮助。


您拖动的文件所在文件夹中是否具有访问权限?Windows根据拖动的文件设置程序的工作目录。 - Mehrdad Afshari
1
你已经硬编码了文件名。重写你的主函数声明,接受 argc 和 argv 参数,并在你的代码中使用它们。 - Hans Passant
@nobugz 我看不出Windows如何知道代码内部发生了什么。 - anon
@Mehrdad 我相信是这样的,我拖动的文件与可执行文件在同一个目录中。@nobugz 我想让它硬编码,因为它是我创建的文件。如果我不包括 argc 和 argv,命令行参数会被忽略吗?这是我目前想要的,但似乎并不是真的。 - kaykun
事实上,添加main(int argc,char**argv)是不起作用的。我必须承认,我以前从未尝试过在Windows控制台应用程序中使用它 - 它甚至应该工作吗? - anon
显示剩余2条评论
4个回答

1
你根本没有使用命令行参数。请重新编写你的main()函数,让它看起来像这样:
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;
}

小心你删除的内容,你的代码会重写文件内容。


我应该澄清一下,我不想写入我拖入的文件。我想创建一个与拖入文件无关的新文件,并向其写入内容,只是为了测试目的。 - kaykun
那么你当然不能使用拖放功能。我不太清楚你想如何利用拖放功能。也许你可以使用被拖动文件的目录? - Hans Passant
最终,我希望这个程序能够接受文件拖放,并分析该文件并生成另一个基于拖放文件的文本文件,但文件名不同。但现在,我正在尝试解决这个简单的问题,因为每当有文件被拖放到程序上时,它都无法创建任何文件。 - kaykun
1
好的,你已经得到了需要分析的文件部分。你可以对从分析结果创建的文件进行任何操作。强烈建议使用完整路径名。请查看_splitpath() CRT函数。 - Hans Passant

1
以下代码实现了OP想要的功能:
#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;
}

它支持拖放,但不会使用文件名进行文件打开。当你将文件拖入其中时,会得到以下消息:

"写入文件"

不幸的是,我目前不知道它将文件写在哪里 - 绝对不是当前目录。我要去搜索一下...

编辑:它创建在你的文档和设置目录中。所以要将其放在当前目录中,你可能需要显式地加上"./"作为前缀,但我没有测试过 - 我把它留给读者自己练习 :-)。


谢谢,但是outfile.open(“./test.txt”);仍然会在Documents and Settings目录中创建文件。有什么建议吗? - kaykun
从删除的文件中提取路径并将其用作新文件的路径,这是我所能想到的。这似乎是非常奇怪的行为,但我想一个人永远不应该对Windows感到惊讶。 - anon
@Kaykun:你想把文件放在哪里? - John Knoeller
我想要在可执行文件所在的同一目录中创建新文件,并将其命名为不同于被拖入文件的名称。 - kaykun
1
您可以调用Win32 APIGetModuleFileName()并将第一个参数传递为NULL来获取.exe文件的完整路径。从最后一个\之后剥离所有内容,即可得到exe路径。 - John Knoeller
这或许有些难度,但能否解释一下如何将最后一个 \ 后面的所有内容都去掉呢?我可以通过在 main() 中传入 argv[0] 来获取可执行文件路径。 - kaykun

0

你没有为“test.txt”指定路径,因此它将尝试在可执行文件的当前工作目录中创建该文件。当通过将文件拖放到可执行文件上调用exe时,这将与正常运行程序时不同。

尝试给“test.txt”一个完整的路径,看看是否可以正常工作。

编辑: 要将输出文件写入包含exe的路径,您可以使用

GetModuleFileName(NULL, ...)获取exe的完整路径, 然后使用PathRemoveFileSpec剥离exe名称,只留下exe路径,然后 使用PathCombine将test.txt附加到exe路径


我已经尝试将所有文件放在同一个目录下,但仍然无法正常工作。 - anon
听起来好像 main 函数没有被调用。我建议在 main 函数的顶部添加一个 DebugBreak() 调用,以查看是否能够到达该函数。 - John Knoeller
谢谢,但将它更改为"C:\text.txt"会导致程序错误"无法打开文件"。 - kaykun
不要忘记在字符串字面值中将 \ 加倍 "c:\text.txt" - John Knoeller

0

由于您没有指定路径,因此文件 test.txt 将保存到默认路径。只需打开命令提示符(即运行 cmd.exe),命令提示符将显示默认路径。文件应该在这个目录下。

您可以通过编辑 HOMEDRIVE 和 HOMEPATH 环境变量来更改默认路径。

另外,您应该注意其他答案。您应该使用 argc/argv 指定输出文件。


谢谢。如果我想在可执行文件所在的同一目录下创建一个文件(在不同的计算机上会有所不同),并且使用不同的文件名作为拖动的文件,我该如何处理呢? - kaykun

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接