how can I run a .exe file through C++? - c++

My .exe application needs to be opened in console window. Then I have to type the name of a .txt in the console application for it to read. How can I perform all these within my code at once?
I used to be able to run it (and not making it to read .txt) with system("name.exe"), but suddenly it gives,
error: input "name.exe" is not a valid windows application

You can make your application read the filename as a command-line parameter, then you can run your application using system("name.exe name.txt").

In Windows use the CreateProcess API to do this - http://msdn.microsoft.com/en-us/library/windows/desktop/ms682425(v=vs.85).aspx.
Do not use system.

1- type "name.txt" 2- press enter 3- type name2.exe 4- Press enter. How can I do that through my c++ code?
std::string appName, fileName
std::cin >> appName >> fileName;
system(std::string(appName + " " + filename).c_str())
If names contain spaces, you might need to use getline to read them instead of >>.
--EDIT--
Basically I want once my application is called the input is also automatically given to it.
Creating Child process with redirected input (msdn)
_popen documentation(msdn)
pipe to subprocess (GNU)

Related

Is there a way to use getline() with an external text file then get control back for cin to take input from console?

I am new to C++ and wondered of there is a way to use just standard iostream to read in an input file (from using debugging properties: < filename) or other then get control back to the console to input something else later with cin.
I separated the file read part into a different function but it seems when I specify in the project properties the command to grab the file contents line by line with getline() it skips over any cin commands I issue later.
I'm sure this could just be a setup issue or I am may need to break it off into another program in the project somehow? This is a console app but surely there is a way to do both in the same project?
I have read that you can't use both cin and getline together but how does one input a file then go ask for more info from the user in a C++ app using visual studio?
Separate program and functions for the file read
'int lineIter = 0;
cin.getline(rowData, arraySize); // Grab first row of data
while (!cin.eof()) {
// output each row of data to screen:
cout << rowData << endl;
}
///// Increment for next ROW
lineIter++;
cin.getline(rowData, arraySize);'
Then later how do I go back to being able to use cin or other to get input from user?
I tried many variations of below later:
'cin.clear();
cin.ignore(arraySize);
cin >> selectR[b];'
and other variations of getline() but none stop program execution and I can't get them to do anything except try to read the file again.
I am using VS 2019 Community Edition
I don't really understand what you're trying to achieve here.
Currently, the way you read your external file is by changing std::cin's "source" from the console to the given file ; this change is made outside your program, at the debugger's level. So you will not be able to change the source back to the console from the program itself. (You might be able to do from the debugger while it's running though).
If you want to read external files and still be able to use std::cin normally, why not using std::fstreams ?
On the other hand, if you absolutely have to pass the file to the program through std::cin, you should keep it default and simply copy-paste your file in the console. Be careful though : since the file probably contains newlines, you will not be able to use those as end of input, so you'll have to design another way for the program to reckognize the end of the file (two consecutive empty lines for example).

Sending data to stdin of another process through linux terminal

I've been trying to send data to stdin of a running process. Here is what I do:
In a terminal I've started a c++ program that simply reads a string and prints it. Code excerpt:
while (true) {
cin >> s;
cout << "I've just read " << s << endl;
}
I get the PID of the running program
I go to /proc/PID/fd/
I execute echo text > 0
Result: text appears in the terminal where the program is run. Note, not I've just read text, but simply text.
What am I doing wrong and what should I do to get this thing to print 'I've just read text'?
When you're starting your C++ program you need to make sure its input comes from a pipe but not from a terminal. You may use cat | myapp to do that. Once it's running you may use PID of your application for echo text > /proc/PID/fd/0
It could be a matter of stdout not being properly flushed -- see "Unix Buffering". Or you could be in a different shell as some commentators have suggested.
Generally, it's more reliable to handle basic interprocess communication via FIFOs or NODs -- named pipes. (Or alternatively redirect stdout and/or stderr to a file and read from that with your c++ program.)
Here's some good resources on how to use those in both the terminal and c++.
"FIFO – Named pipes: mkfifo, mknod"
"Using Pipes in Linux Processes"
"Programming with FIFO: mkfifo(), mknod()"
FD 0 is the terminal the program is running from. When you write to FD 0, you are writing to the terminal the program is running from. FD 0 is not required to be opened in read-only mode; in practice it seems to be read/write mode, so you can write to it. (I suspect this is because FDs 0, 1 and 2 all refer to the same file description)
So echo text > /proc/PID/fd/0 just echoes text to the terminal.
To pipe input to the program, you would need to write to the other end of the pipe (actually a PTY, which mostly behaves like a pair of pipes). Most likely, whatever terminal emulator you're using (xterm, konsole, gnome-terminal) will have the other end open, so you could try writing to that.

Trouble with getline when using eclipse's console

I recently started to use eclipse for my C++ code, and wanted to run a simple function that asks the user for a filename, then reads from the file and sums up all the numbers to test it out.
string filename;
do {
cout << "Enter File Name: "; // Asks for user input
getline(cin, filename);
}
while (filename.empty());
ifstream myfile (filename);
if (myfile.is_open()) {
// sums up text file & outputs it
}
else {
cout << "Error Opening " << filename << endl;
}
The program works perfectly when I run it via Windows Command Prompt in my executable folder and type in the filename. However, when I try to run it via eclipse's console using the exact same input, where I've set the working directory to the project root where the file most definitely exists, the file does not open.
If I change a single line:
ifstream myfile("test1.txt");
Then the code works again perfectly. So now I've narrowed down that for some reason, the Eclipse console interprets my text input via getline differently from the windows command prompt, but I'm not sure what I can do so it behaves consistently.
Calling
cin.ignore()
Before calling getline() just removes the first character of my input (so it tries to "est1.txt") instead.
Any idea what exactly eclipse does to its console that makes getline unreliable? And if this is the case, what I should do to work around it?

How to open Nano and get a string from it in C++?

I am creating a simple logging program. When a user enters log some_file into the console, the program currently simply receives some basic input from cin, and records it into some_file.
However, instead of implementing my own editor with cin, I'd like to open the Nano editor and let the user edit his message there.
Then, when the message is complete, I'd like my C++ logger to receive it as a string and carry on.
This is exactly what git does on commits.
How can I achieve this?
(Preferably without using tools such as expect, just raw C++ code.)
Most editors expect to work with normal files, so you'd typically create a temporary file, then pass the name of that file to the editor on its command line. When the editor returns, you copy the content from the temporary file into your log, then destroy the file.
If you want to use the Nano editor then you need to run the system() function to invoke Nano with a temporary file. Then remove the file later..
std::string filename = "/tmp/.out." + std::to_string(getpid());
std::string cmd = "/bin/nano " + filename
system(cmd.c_str());
// read from filename
unlink(filename.c_str());
Update
If using tmpnam() as suggested by DevSolar
char filename[L_tmpnam];
tmpnam(filename);
std::string cmd = "/bin/nano " + filename
system(cmd.c_str());
unlink(filename);
what about open a file(passing file name to the editor), save and then read it from your program? I've always thought git works the same way.

launch app, capture stdout and stderr in c++

How do I launch an app and capture the output via stdout and maybe stderr?
I am writing an automated build system and I need to capture the output to analyze. I'd like to update the svn repo and grab the revision number so I can move the files in autobuild/revNumber/ if successful. I also would like to build using make and upload the compile text to my server for everyone to see the warnings and errors on a failed build.
I can't find the system() function, but I found the CreateProcess() function on MSDN. I am able to launch what I need but I have no idea how to capture the stderr and stdout. I notice the process launches separately unless I set a breakpoint and keep my app exiting which it then will keep all the text in my app console window. I would also want to wait until all processes are finished and then scan the data it produced to do any additional operations I need. How do I do any of this?
In real shells (meaning, not sea shells - I mean, not in C Shell or its derivatives), then:
program arg1 arg2 >/tmp/log.file 2>&1
This runs program with the given arguments, and redirects the stdout to /tmp/log.file; the notation (hieroglyph) '2>&1' at the end sends stderr (file descriptor 2) to the same place that stdout (file descriptor 1) is going. Note that the sequence of operations is important; if you reverse them, then standard error will go to where standard output was going, and then standard output (but not standard error) will be redirected to the file.
The choice of file name shown is abysmal for numerous reasons - you should allow the user to choose the directory, and probably should include the process ID or time stamp in the file name.
LOG=${TMPDIR:-/tmp}/log.$$.$(date +%Y%m%d-%H%M%S)
program arg1 arg2 >$LOG 2>&1
In C++, you can use the system() function (inherited from C) to run processes. If you need to know the file name in the C++ program (plausible), then generate the name in the program (strftime() is your friend) and create the command string with that file name.
(Strictly, you also need getenv() to get $TMPDIR, and the POSIX function getpid() to get the process ID, and then you can simulate the two-line shell script (though the PID used would be of the C++ program, not the launched shell).
You could instead use the POSIX popen() function; you'd have to include the '2>&1' notation in the command string that you create to send the standard error of the command to the same place as standard output goes, but you would not need a temporary file:
FILE *pp = popen("program arg1 arg2 2>&1", "r");
You can then read off the file stream. I'm not sure whether there's a clean way to map a C file stream into a C++ istream; there probably is.
You need to fill up the STARTUP_INFO structure, which has hStdInput, hStdOutput and hStdError. Remember to inherit handles when you CreateProcess.
/* Assume you open a file handle or pipe called myoutput */
STARTUP_INFO si_startinfo;
ZeroMemory(&si_startinfo, sizeof(STARTUP_INFO));
si_startinfo.cb = sizeof(STARTUP_INFO);
si_startinfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
si_startinfo.hStdOutput = myoutput;
si_startinfo.hStdError = myoutput;
si_startifno.dwFlags != STARTF_USEHANDLES;
PROCESS_INFORMATION pi_procinfo;
ZeroMemory(&pi_procinfo, sizeof(PROCESS_INFORMATION);
CreateProcess(NULL, cmdline, NULL, NULL, true, 0, NULL, pathname, &si_startinfo, &pi_procinfo);
I have not shown the error handling aspects, which you will need to do. The 5th argument is set to true to inherit the handles. Others have explained how to create pipes so I won't repeat it here.
Microsoft's CRTs and the MSDN library do include the system function and the _popen function.