Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Windows 在Win32 GUI应用程序中使用stdout:如果我没有';无法重定向到参数中的文件_Windows_User Interface_Dll_Stream_Stdout - Fatal编程技术网

Windows 在Win32 GUI应用程序中使用stdout:如果我没有';无法重定向到参数中的文件

Windows 在Win32 GUI应用程序中使用stdout:如果我没有';无法重定向到参数中的文件,windows,user-interface,dll,stream,stdout,Windows,User Interface,Dll,Stream,Stdout,我正在构建一个Win32 GUI应用程序。在那个应用程序中,我使用的是一个DLL,它原本打算在命令行应用程序中使用 假设Foo.exe是我的GUI应用程序,bar()是DLL中的一个函数,它向标准输出“hello”。Foo.exe调用bar() 如果我使用重定向(>)从命令行运行Foo.exe(即Foo.exe>out.txt),它会将“hello”写入out.txt并正常退出(如预期) 但是,如果在没有重定向的情况下运行Foo.exe(从cmd.exe或在Windows资源管理器中双击),则调

我正在构建一个Win32 GUI应用程序。在那个应用程序中,我使用的是一个DLL,它原本打算在命令行应用程序中使用

假设Foo.exe是我的GUI应用程序,bar()是DLL中的一个函数,它向标准输出“hello”。Foo.exe调用bar()

如果我使用重定向(>)从命令行运行Foo.exe(即
Foo.exe>out.txt
),它会将“hello”写入out.txt并正常退出(如预期)

但是,如果在没有重定向的情况下运行Foo.exe(从cmd.exe或在Windows资源管理器中双击),则调用bar()时会崩溃

如果我在调试器中运行Foo.exe,并在命令行中使用重定向(通过项目的VS属性设置)并调用“GetStdHandle(STD_OUTPUT_HANDLE)”,我将获得一个合理的句柄地址。如果在命令行中没有重定向的情况下调用它,则得到0

我需要一些东西来“初始化”标准输出吗?有没有办法在应用程序启动时设置此重定向?(重定向到一个文件是很理想的。但是仅仅抛出DLL打印的数据也可以。)

最后,我怀疑DLL是通过CRT POSIX类API写入stdout的,因为它是一个跨平台DLL。我不知道这是否重要

我试着用CreateFile创建一个文件并调用SetStdHandle,但这似乎不起作用。但是,我可能创建的文件不正确。请参阅下面的代码

HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
// hStdOut is zero  

HANDLE hFile;
hFile = CreateFile(TEXT("something.txt"),        // name of the write
                   GENERIC_WRITE,               // open for writing
                   0,                           // do not share
                   NULL,                        // default security
                   CREATE_NEW,             // create new file only
                   FILE_ATTRIBUTE_NORMAL,  // normal file
                   NULL);                  // no attr. template
BOOL r = SetStdHandle(STD_OUTPUT_HANDLE, hFile) ;   
hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
// hStdOut is now equal to hFile, and r is 1

bar();
// crashes if there isn't a redirect in the program arguments
更新:我刚找到这篇文章:。它声明“请注意,此代码不会更正句柄0、1和2的问题。事实上,由于其他复杂性,无法更正此问题,因此有必要使用流I/O而不是低级I/O。”

我的DLL肯定使用文件句柄0、1和2。因此,这个问题可能没有好的解决办法


我正在开发一个解决方案,检查这种情况,并使用CreateProcess适当地重新启动exe。完成后,我将在此处发布。

您必须使用该开关将foo.exe构建为控制台应用程序。Windows将自动为您的应用程序分配控制台(stdout),该控制台可以是:

  • 当前控制台
  • 对文件的重定向
  • 到另一个程序STDIN的管道
如果将foo.exe构建为GUI应用程序,则默认情况下不会分配控制台,这解释了崩溃的原因


如果必须使用GUI子系统,仍然可以使用AllocConsole完成。这个老家伙想帮你

我找到的解决方案如下:

  • 以某种方式获取有效的文件句柄以指导标准输出。 让我们调用文件句柄“fh”。 (请注意,在Windows上,文件句柄与文件描述符不同)
  • 将文件描述符与文件句柄与_open_osfhandle关联 (详情请参阅) 让我们调用“fd”这个新的文件描述符,一个int值
  • 调用dup2将标准输出文件号与给定的文件描述符关联: dup2(fd,标准输出文件号)
  • 创建与标准输出文件描述符关联的文件strem 文件*f=_fdopen(标准文件号,“w”)
  • 将标准输出设置为f的内容: *标准输出=*f
  • 对给定的文件句柄调用SetStdHandle: 设置TDHandle(标准输出句柄,ofh)
请注意,我并没有完全测试这个序列,但有点不同

我不知道有些步骤是否多余

在任何情况下,下面的文章都很好地解释了文件句柄、描述符和文件流的概念:


你能告诉我你用哪一个图书馆吗?这个问题有很好的解决办法。编写小存根启动器EXE(在GUI模式下,但没有窗口!),其中包含您的图标和所有快捷方式。使此存根EXE“CreateProcess”成为真正的EXE,并将输出重定向到“NUL”或“CON”,或者,将其挂起的CreateProcess()作为其标准输出,对其不做任何操作。这样,您的原始EXE应该在没有可见控制台的情况下工作,但实际上可以在父不可见存根EXE所使用的句柄0、1和2中写入。请注意,杀死父EXE可能会使子级丢失其句柄并崩溃

在任务管理器中可能会有两个进程。所以你可以试着让这两个进程像谷歌Chrome一样工作


关于你的问题,我是否需要一些东西来“初始化”标准输出只有您的父/启动器才能“正确”预初始化句柄0、1和2的标准输出。

如果我添加
freopen(“two.txt”,“w”,标准输出)
在调用
bar
之前,然后运行
Foo.exe>one.txt
bar
的输出转到two.txt。但是,如果我只是在没有重定向的情况下运行
Foo.exe
Foo.exe,它仍然会崩溃。您可以将调用堆栈添加到问题中吗?谢谢您的评论。不幸的是,分配控制台似乎并不能解决问题。我相信这篇文章是相关的:。“请注意,此代码不会更正句柄0、1和2的问题。事实上,由于其他复杂性,无法更正此问题,因此有必要使用流I/O而不是低级I/O。”我相信将其构建为控制台应用程序将解决此问题。但是,我需要将其构建为GUI应用程序。而且,这是一个出货产品——有一个控制台弹出窗口并不理想。