Answered by:
Where does stdout (printf, cout) go on Windows Universal Apps?
Question
-
We're trying to port a library to run on Windows Universal Apps. It's pure math, so doesn't need to call any system functions. We test it on other platforms using the googletest framework. Internally it uses printf to write output to stdout, which is where the results are reported. Is there any way to capture stdout (I'd like to at least redirect it to OutputDebugString so that it can be captured and checked). I could adapt googletest to output to OutputDebugString directly, but I wanted to see if there's any easy way to capture the output first.
We have too many tests to easily re-write using the Universal Unit Test App project type, so even though it's a better fit for the platform, the googletest and Windows Unit Test App markup are too different to easily port the tests.
Thanks,
-Derian Reuss
Monday, February 8, 2016 10:44 PM
Answers
-
Microsoft C++ code is close to the most recent published C++ standard.
I used the freopen, but you might want to use the more secure freopen_s. You can find more information here:
This code may work for what you are looking for, note the "w" opens an empty file and writes the data, but if the file exists then the data is not written.
If this answered your question, please mark this as answered, other wise, let me know via a reply.
// Compile options needed: none #include <stdio.h> #include <stdlib.h> void main(void) { FILE *stream ; if((stream = freopen("outputfile.txt", "w", stdout)) == NULL) exit(-1); printf("The ouputfile.txt contains the stdout output\n"); stream = freopen("CON", "w", stdout); printf("And now back to the console once again\n"); }
Sam Stokes
Tuesday, February 9, 2016 12:48 AM -
This gave me enough to get started, but I had to make some modifications. Notably, the working directory isn't necessary safe to write to.
The code below was able to capture stdout, and write it to OutputDebugString, so that either the stdout.txt can be retrieved and read, or debug output can be used.
//Truncated MainPage.xaml.cpp up to the MainPage::MainPage function
#include "gtest/gtest.h" //Normally this function would be main() in a gtest app. Renamed because it's not the entry point in a Windows Universal App GTEST_API_ int __main(int argc, char **argv); MainPage::MainPage() { InitializeComponent(); //We need to fake command line args, or it won't run the tests int argc = 2; char *args[] = { "test.exe", "test_param", 0 }; //Redirect stdout to a file Platform::String^ outfilename = Windows::Storage::ApplicationData::Current->LocalFolder->Path + L"\\stdout.txt"; FILE *stdout_capture; if ((stdout_capture = _wfreopen(outfilename->Data(), L"w", stdout)) == NULL) { OutputDebugString(L"Couldn't open file to redirect stdout\n"); exit(-1); } //Print file location to OutputDebugString OutputDebugString(L"Redirecting stdout to "); OutputDebugString(outfilename->Data()); OutputDebugString(L"\n"); //Call what would normally be main() to invoke the gtest tests __main(argc, args); //End capturing stdout freopen("CON", "w", stdout); fclose(stdout_capture); //Output the captured stdout to OutputDebugString if ((stdout_capture = _wfreopen(outfilename->Data(), L"r", stdout)) == NULL) { OutputDebugString(L"Couldn't open file to read redirected stdout\n"); exit(-1); } char* buffer; fseek(stdout_capture, 0, SEEK_END); size_t stdout_len = ftell(stdout_capture); rewind(stdout_capture); buffer = (char*)malloc((sizeof(char)*stdout_len)); memset(buffer, 0, (sizeof(char)*stdout_len)); size_t result = fread(buffer, 1, stdout_len, stdout_capture); OutputDebugStringA(buffer); free(buffer); fclose(stdout_capture); //TODO: Testing is complete. App will idle, and never indicate that it is now done. // Need to signal that execution is done somehow. }
- Marked as answer by ReussDr Tuesday, February 9, 2016 10:36 PM
Tuesday, February 9, 2016 10:36 PM
All replies
-
Microsoft C++ code is close to the most recent published C++ standard.
I used the freopen, but you might want to use the more secure freopen_s. You can find more information here:
This code may work for what you are looking for, note the "w" opens an empty file and writes the data, but if the file exists then the data is not written.
If this answered your question, please mark this as answered, other wise, let me know via a reply.
// Compile options needed: none #include <stdio.h> #include <stdlib.h> void main(void) { FILE *stream ; if((stream = freopen("outputfile.txt", "w", stdout)) == NULL) exit(-1); printf("The ouputfile.txt contains the stdout output\n"); stream = freopen("CON", "w", stdout); printf("And now back to the console once again\n"); }
Sam Stokes
Tuesday, February 9, 2016 12:48 AM -
Also please note if you need use some Win32 API, double check its documentation to see if it support UWP app, for instance OutputDebugString is supported, with the requirement:
--James
We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
Click HERE to participate the survey.- Edited by Jamles Hez Tuesday, February 9, 2016 2:44 AM
Tuesday, February 9, 2016 2:44 AM -
This gave me enough to get started, but I had to make some modifications. Notably, the working directory isn't necessary safe to write to.
The code below was able to capture stdout, and write it to OutputDebugString, so that either the stdout.txt can be retrieved and read, or debug output can be used.
//Truncated MainPage.xaml.cpp up to the MainPage::MainPage function
#include "gtest/gtest.h" //Normally this function would be main() in a gtest app. Renamed because it's not the entry point in a Windows Universal App GTEST_API_ int __main(int argc, char **argv); MainPage::MainPage() { InitializeComponent(); //We need to fake command line args, or it won't run the tests int argc = 2; char *args[] = { "test.exe", "test_param", 0 }; //Redirect stdout to a file Platform::String^ outfilename = Windows::Storage::ApplicationData::Current->LocalFolder->Path + L"\\stdout.txt"; FILE *stdout_capture; if ((stdout_capture = _wfreopen(outfilename->Data(), L"w", stdout)) == NULL) { OutputDebugString(L"Couldn't open file to redirect stdout\n"); exit(-1); } //Print file location to OutputDebugString OutputDebugString(L"Redirecting stdout to "); OutputDebugString(outfilename->Data()); OutputDebugString(L"\n"); //Call what would normally be main() to invoke the gtest tests __main(argc, args); //End capturing stdout freopen("CON", "w", stdout); fclose(stdout_capture); //Output the captured stdout to OutputDebugString if ((stdout_capture = _wfreopen(outfilename->Data(), L"r", stdout)) == NULL) { OutputDebugString(L"Couldn't open file to read redirected stdout\n"); exit(-1); } char* buffer; fseek(stdout_capture, 0, SEEK_END); size_t stdout_len = ftell(stdout_capture); rewind(stdout_capture); buffer = (char*)malloc((sizeof(char)*stdout_len)); memset(buffer, 0, (sizeof(char)*stdout_len)); size_t result = fread(buffer, 1, stdout_len, stdout_capture); OutputDebugStringA(buffer); free(buffer); fclose(stdout_capture); //TODO: Testing is complete. App will idle, and never indicate that it is now done. // Need to signal that execution is done somehow. }
- Marked as answer by ReussDr Tuesday, February 9, 2016 10:36 PM
Tuesday, February 9, 2016 10:36 PM