failing to execute a shell command in windows using WindowsAPI - c++

I am trying to execute a ping command in windows via their ShellExecute function.
ShellExecute(0, L"open", L"cmd.exe", normToWide(command).c_str(), 0, SW_HIDE);
This is how i call the Function.
to get the wide string i use this function
std::wstring normToWide(std::string str)
{
std::wstring str2(str.length(), L' ');
std::copy(str.begin(), str.end(), str2.begin());
return str2;
}
the command is this:
ping 127.9 -l 4 -n 300 > output.txt
Although the ip is invalid it should not matter as output.txt should still be populated with some sort of error message at hte least. What is going on with my function?
I expected there to be a output.txt file with the output of the command
I also tried hardcoding my command to make sure it was not a widestr issue

The problem is ping is not a built in command in cmd.exe and it will not automatically execute the command you pass to it, thus ping even if it is installed and in the command path will not be executed. To fix this you have two choices.
The first is to prefix the command string with the /C option which "Carries out the command specified by string and then terminates" like so
/C ping 127.9 -l 4 -n 300 > output.txt
This will force cmd.exe to execute ping if it is in installed and in the command path.
The second is just as easy - just specify ping.exe as the command for ShellExecute to execute instead of cmd.exe.
ShellExecute(0, L"open", L"ping.exe", normToWide(command).c_str(), 0, SW_HIDE);

If you want to execute ping.exe and capture the output it produces, it'll be much cleaner to use something on this order:
FILE *f = _popen("ping 127.9 -l 4 -n 300");
char buffer[256];
while (fgets(buffer, sizeof(buffer), f) {
// `buffer` contains a line of output from `ping`
}

ShellExecute(NULL,NULL,L"cmd.exe", L"/K ping 127.9 -l 4 -n 300 > d://test.txt",NULL, SW_SHOWNORMAL);
/k: end cmd window does not disappear
/c: end cmd window disappear

Related

Want to run a cpp executable in a new terminal and then send a file into the input stream

I would like to run a c++ executable in a new linux terminal, which I am doing using:
xterm -e executable options &disown
and this works. However, I also need to parse a text file through the command line. Normally, the file would be parsed by:
./executable options < inputFile.txt
and then the file is handled by the c++ code using this function:
void parse_lines(istream &in){
verify_version_number(in);
read_variables(in);
...
}
However the following line does not work:
xterm -e executable options < inputFile.txt &disown
How can I run the executable in a new terminal and then send the contents of inputFile.txt into the istream?
Thanks!
If you put quotes around the command, it will be sent to the shell as a single command, and the special characters < and & will be interpreted in the shell running within xterm rather than in the shell where you start xterm:
xterm -e "executable options < inputFile.txt &disown"
Try x-terminal-emulator instead of xterm. Perhaps it works.

Using grep with execl()

A little context for my project: We have an arbitrary number of files that need a separate process for each file then need to search using an exec() call to find every time a specific KEY is used. I know how to use grep from the command line using this command:
grep -o KEY FILENAME.txt | wc -l > OUTPUT.txt
But I cannot figure out how to do this in c++. I found a thread on here that gave me this line.
execl("/bin/grep","grep",pattern,filename,NULL);
It compiles and runs so I think it works but the problem is I need to output the number of times the pattern occurred to a file and I tried the line below but expectedly it didn't work. It gave this error "grep: out.txt: No such file or directory"
execl("/bin/grep", "grep",pattern,fileName,output,NULL);
Here are the directions of this part of my project.
You can do this by means of the
system call exec() , providing it with the path to the executable of the shell (typically, /bin/sh )
and, as arguments of /bin/sh , the string -c and the string corresponding to the search command
( grep -o ... ).
Some guidance here would be much appreciated!
For the actual execution as you would do on command line would be:
execl("/bin/sh", "/bin/sh", "-c", "grep -o KEY FILENAME.txt | wc -l > OUTPUT.txt")
This will mean that the shell would take the line grep -o KEY FILENAME.txt | wc -l > OUTPUT.txt, interpret it and run it. Note that this will include wild card expansion and all what the shell does.
Then of course if you wan't to continue after it has completed you will have to fork first because execl does not return if it's successful at starting the program (ie bash).

c++ createprocess powershell as admin, hidden and dont wait for it

This is what I have, starting powershell.exe without the command and closing directly after it.
why doesnt it work?
int main(int argc, char *argv[])
{
[...]
CreateProcess( NULL, // No module name (use command line)
"powershell.exe -command \".C:\\test\\t.ps1\" ",
[...]
&si, // Pointer to STARTUPINFO structure
&pi ); // Pointer to PROCESS_INFORMATION structure
return 0;
}
in normal cmd the command would look like this:
powershell -command ".c:\test\t.ps1"
and in the file this one-liner, if you want to test it:
write-host "hello world" |out-file C:\test\hi.txt
should write hello world in the console and create hi.txt in the folder
The command line should be either:
CreateProcess(NULL, // No module name (use command line)
"powershell.exe -command \"& {C:\\test\\t.ps1}\"",
or
CreateProcess(NULL, // No module name (use command line)
"powershell.exe -file C:\\test\\t.ps1",
In general, for executing scripts use -File unless the exit code is important to you. If it is, use -Command because there is a bug with -File where it always returns 0 (success) even if there is an error.
If you want the execution of powershell.exe to prompt for elevation, use the ShellExecute API instead. Pass in "RunAs" for lpOperation and you can specify a hidden window with the nShowCmd parameter.

Execute shell command in c++

I have a question regarding executing shell commands in c++. I'm building an application in winforms, vs 2008. My application has a button, when clicked should decode a binary file to a .csv file. I can decode files by first going to the right directory (cd Test_Copy2) and then execute a command in the command prompt (java -jar tool.jar -b x.fit x.csv). I tried a lot of different stuff but unfortunately got none to work!
I tried using:
system, _popen, ShellExecute(NULL, L"open", L"C:\\WINDOWS\\system32\\cmd.exe ", L"java -jar Tool.jar -b x.fit x.csv", L"C:\\Test_Copy2", SW_SHOWNORMAL)
Can anyone please provide me with an example on how to do that? I dont know where I'm going wrong, most of the time the command prompt opens but no command is executed!
If you really want to run the jar in a cmd.exe instance, you need to add one of the correct command line switches to cmd.exe for it to work the way you want it to:
/C Carries out the command specified by string and then terminates
/K Carries out the command specified by string but remains
For instance, your command string should be:
C:\\WINDOWS\\system32\\cmd.exe /c java -jar Tool.jar -b x.fit x.csv
You can use the system() function to execute shell commands.
For example:
system("DIR") executes the DIR command in the CMD shell. The default directory at the start is the directory you're .exe file is located.
'system("PAUSE")` executes the PAUSE command.
The command/s you wannt to execute should be passed as a constant string to the function.
Edit:
For you paritcular program the syntax (IMO) would be:
system("java -jar Tool.jar -b x.fit x.csv")

Why child process returns exit status = 32512 in unix?

In my program I'm executing given command and getting result (log, and exit status). Also my program have to support shell specific commands (i.e. commands which contains shell specific characters ~(tild),|(pipe),*). But when I try to run sh -c ls | wc in my home directory via my program it failed and its exit status was 32512, also in stderr stream "sh: ls | wc: command not found" was printed.
But the interesting thing is that the command sh -c ls | wc works correct if I run it in shell.
What is the problem? Or more preferable how can I run shell specific commands via my program (i.ec which command with which parameters should I run)?
The code part bellow is in child part after fork(). It executs the command.
tokenized_command is std::vector<std::string> where in my case "sh", "-c", "ls", "|", "wc" are stored, also I have tried to store there "sh", "-c", "\"ls | wc\"" but result is same. command is char * where full command line is stored.
boost::shared_array<const char *> bargv(new const char *[tokenized_command.size() + 1]);
const char **argv = bargv.get();
for(int i = 0; i < tokenized_command.size(); ++i)
{
argv[i] = tokenized_command[i].c_str();
printf("argv[%d]: %s\n", i, argv[i]); //trace
}
argv[tokenized_command.size()] = NULL;
if(execvp(argv[0], (char * const *)argv) == -1)
{
fprintf(stderr, "Failed to execute command %s: %s", command, strerror(errno));
_exit(EXIT_FAILURE);
}
P.S.
I know that using system(command) instead execvp can solve my problem. But system() waits until command is finished, and this is not good enough for my program. And also I'm sure that in implementation of system() one of exec-family functions is used, so the problem can be solved via exec as well, but I don't know how.
execvp takes a path to an executable, and arguments with which to launch that executable. It doesn't take bourne shell commands.
ls | wc is a bourne shell command (among others), and it can't be broken down into the path to an executable and some arguments due to the use of a pipe. This means it can't be executed using execvp.
To execute a bourne shell command using execvp, one has to execute sh and pass -c and the command for arguments.
So you want to execute ls | wc using execvp.
char *const argv[] = {
"sh",
"-c", "ls | wc", // Command to execute.
NULL
};
execvp(argv[0], argv)
You apparently tried
char *const argv[] = {
"sh",
"-c", "ls", // Command to execute.
"|", // Stored in called sh's $0.
"wc", // Stored in called sh's $1.
NULL
};
That would be the same as bourne shell command sh -c ls '|' wc.
And both are very different than shell command sh -c ls | wc. That would be
char *const argv[] = {
"sh",
"-c", "sh -c ls | wc", // Command to execute.
NULL
};
You seem to think | and wc are passed to the sh, but that's not the case at all. | is a special character which results in a pipe, not an argument.
As for the exit code,
Bits 15-8 = Exit code.
Bit 7 = 1 if a core dump was produced.
Bits 6-0 = Signal number that killed the process.
32512 = 0x7F00
So it didn't die from a signal, a core dump wasn't produced, and it exited with code 127 (0x7F).
What 127 means is unclear, which is why it should accompanied by an error message. You tried to execute program ls | wc, but there is no such program.
You should execute sh -c 'ls | wc'.
Option -c expects a command in form of string. In shell of course it is working, because there is no difference between spawning ls and redirecting output to wc and launching ls | wc in separate shell.