How to fetch output of command of powershell with C++? - c++

i implemented program of network statistics with help of powershell scrpit. the program is running successfully and giving me perfact output as well . below is my program.
int main(int argc, char *argv[])
{
string strPath = "C:\\Get-NetworkStatistics.ps1";
char str[50] = "C:\\Get-NetworkStatistics.ps1";
char command[500];
//access function:
//The function returns 0 if the file has the given mode.
//The function returns –1 if the named file does not exist or does not have the given mode
if(access(strPath.c_str(),0) == 0)
{
_snprintf(command, sizeof(command), "Start Powershell.exe -noexit Set -executionpolicy;.'%s';Get-NetworkStatistics",str);
system(command);
}
else
{
system("cls");
cout << "File is not exist";
system("pause");
}
return 0;
}
! here is the output of above program
as you can see the output is in the powershell windows.. i want to fetch all this data of powershell output and want to display it in console. how should it possible?
please help me..

Unless you need to do display the info in realtime as it becomes available, just redirect it to a file, then read that file from C++.
Since netstat was lobotomized in Windows XP SP 2 or thereabouts I can understand using Powershell.
But it may just be that netstat will serve your needs, and then you don't have to deal with any of that complication.
By the way, I recommend using a scripting language for scripting tasks. There is of course the complication that Powershell scripting is disabled by default, otherwise using the Powershell scripting facility would be indicated. But e.g. in this case a [cmd.exe] batch file would be more natural than doing its job from C++.
The Windows Script Host shell objects, available from JScript and VBScript, provide functionality for process execution with output grabbing.
There is a little snag in that you then have to poll the output, but I think it's still easier than doing this at the C/C++ API level.

Related

Send characters to console application

I have simple console application that runs in terminal window reads and prints character:
int main(int argc, char **argv, char **envp)
{
while (true)
{
char c =getchar();
printf("%c \n",c);
}
}
Now I would like to make test application that could emulate character press in first application terminal.
Which way I should go? What API functions I should use for this purpose?
No need for special APIs or whatever. Since your sample application is only reading from standard input, you can just send stuff to there.
Before running the program in a terminal, check its connected terminal using tty command. Then send data to that tty that tty reports.
Alternatively, grab the PID of your running application and send data to /proc/$PID/fd/0 so you don't need to check for tty.
Just pipe the test data to your process:
echo "some test data" | ./myprogram
(Your example program in the question will read and print each letter from "some test data").
There are plenty of other variations on this. Read about the shell and shell pipelines.

Cannot read output of processes launched under cmd.exe pipe

I hope your programming is going well.
I have a question that I hope asserts an easy answer due to my lack of knowledge.
I've used this code from this question - CreateProcess cmd.exe read/write pipes deadlock
And everything works well.
The problem is when I run other commands from the cmd.exe shell that require interactivity, for example, python or powershell, I get the initial output then nothing gets written to the pipe.
So this is what my input/output looks like:
static PCSTR commands[] = { "powershell\r\n", "dir\r\n", "help\r\n"};
ULONG n = RTL_NUMBER_OF(commands);
PCSTR* psz = commands;
do
{
if (MessageBoxW(0,0, L"force close ?", MB_YESNO) == IDYES)
{
DisconnectNamedPipe(hFile);
break;
}
if (p = new U_IRP(&obj))
{
PCSTR command = *psz++;
p->Write(command, (ULONG)strlen(command) * sizeof(CHAR));
p->Release();
}
} while (--n)
When the code runs, I get the initial powershell.exe prompt as so
PS C:\Users>
But after that nothing gets written to the pipe.
The code is using CreateProcess(... "cmd.exe" ...) and I have tried changing it from "cmd.exe" to "cmd.exe /c" and "cmd.exe /k", neither of which work.
Perhaps you would know what I need to do read/write output to interpreted such as python or powershell from a CreateProcess() induced pipe? Thanks for your help!
you exec cmd.exe and send command to it via pipe to exec powershell. then all depended from powershell implementation
on window7:
powershell use ReadConsoleW for got input. so it not use you named pipe - not read from it. and you can note that console window become interactive after you exec powershell. so powershell not accept what you write to pipe (it simply not read from it at all) but read user input from screen. however after you manually input some command to console and press enter - you can got pipe output - powershell use (mix) both - WriteFile and WriteConsoleW for output. some information output via WriteFile and some via WriteConsoleW
on windows10:
powershell use ReadFile for got input. and WriteFile for output. so it read you commands from pipe and write results to it. and all perfect worked. also you can note that console window is inactive in this case - you can not enter any text to it (unlike win7)
so with code all absolute ok. problem only in how 3-rd program read and write data. if it not read from your pipe - you nothing can do here

Will File I/O In Current Working Directory Ever Fail?

On my home Linux laptop, I like to write wrapper programs and GUI helpers for things I use frequently. However, I don't like Bash scripting very much, so I do a lot of stuff in C++. However, a lot of times, this requires me to use the system() function from the cstdlib.
This system() command is awesome, but I wanted a way to call system() and receive the stdout/stderror. The system() command only returns the return code from the command. So, in a Bash script, one can do:
myVar=$(ls -a | grep 'search string')
echo $myVar
and myVar will output whatever the stdout was for the command. So I began writing a wrapper class that will add a pipe-to-file to the end of the command, open the file, read all of the piped stdout, and return it as either one long string or as a vector of strings. The intricacies of the class are not really relevant here (I don't think anyway), but the above example would be done like this:
SystemCommand systemCommand;
systemCommand.setCommand("ls -a | grep \'search string\' ");
systemCommand.execute();
std::cout << systemCommand.outputAsString() << std::endl;
Behind the scenes, when systemCommand.execute() is called, the class ensures that the command will properly pipe all stdout/stderr to a randomly generated filename, in the current working directory. So for example, the above command would end up being
"ls -a | grep 'search string' >> 1452-24566.txt 2>&1".
The class then goes attempts to open and read from that file, using ifstream:
std::ifstream readFromFile;
readFromFile.open(_outputFilename);
if (readFromFile.is_open()) {
//Read all contents of file into class member vector
...
readFromFile.close();
//Remove temporary file
...
} else {
//Handle read failure
}
So here is my main question will std::ifstream ever fail to open a recently created file in the current working directory? If so, what would be a way to make it more robust (specifically on Linux)?
A side/secondary question: Is there a very simplified way to achieve what I'm trying to achieve without using file pipes? Perhaps some stuff available in unistd.h? Thanks for your time.
So here is my main question will std::ifstream ever fail to open a recently created file in the current working directory?
Yes.
Mount a USB thumb drive (or some other removable media)
cd to the mount
Execute your program. While it's executing, remove the drive.
Watch the IO error happen.
There's a ton of other reasons too. Filesystem corruption, hitting the file descriptor limit, etc.
If so, what would be a way to make it more robust (specifically on Linux)?
Make temporary files in /tmp, whose entire purpose is for temporary files. Or don't create a file at all, and use pipes for communication instead (Like what popen does, like harmic suggested). Even so, there are no guarantees; try to gracefully handle errors.

Opening excel files with system( ) on mac?

I am trying to get my C++ program to open up an existing Excel spreadsheet (along with a bunch of applications), however it keeps returning an error that a file does not exist. I am using the following code:
int main(){
system("open ~/path/file");
//--open applications using same command--//
}
The file is definitely there and this command works to open all the applications, so I'm not sure what I am doing wrong.
Thanks in advance!!
Very probably, the system /bin/sh -which by definition is used by system(3)- does not expand ~.
You might try something like
char cmd[256];
snprintf(cmd, sizeof(cmd), "open %s/path/file", getenv("HOME"));
if (0 != system(cmd))
{ fprintf(stderr, "%s failed\n", cmd); exit(EXIT_FAILURE); };
since interactive shells usually expand ~ as $HOME and HOME is generally an environment variable.
(With C++, you could use std::string operations instead of snprintf)
My snprintf + system trick is not at all failproof. If $HOME contains spaces or bizarre characters like ; or ', it wont work. And snprintf itself might fail (e.g. because $HOME is huge).
Of course, you'll better test before that getenv("HOME") is not NULL. You might use getpwuid(3) with getuid(2) if getenv("HOME") fails by returning NULL.
On Linux you probably want xdg-open instead of open.

printing to a network printer using fstream c++ in mac

I wish to print some text directly to a network printer from my c++ code (I am coding with xcode 4). I do know that everything on unix is a file and believe that it would not be impossible to redirect the text using fstream method in c++ to the printer device file. The only problem is I don't know the device file in /dev associated with my network printer.
Is it possible to achieve printing using fstream method? Something like
std::fstream printFile;
printFile.open("//PATH/TO/PRINTER/DEV", std::ios::out);
printFile << "This must go to printer" << std::endl;
printFile.close();
And, if so
How to obtain the file in /dev corresponding to a particular printer?
Thanks in advance,
Nikhil
Opening and writing directly to a file used to be possible back in the days of serial printers; however, this is not the approach available today.
The CUPS daemon provides print queuing, scheduling, and administrative interfaces on OS X and many other Unix systems. You can use the lp(1) or lpr(1) commands to print files. (The different commands come from different versions of print spoolers available in Unix systems over the years; one was derived from the BSD-sources and the other derived from the AT&T sources. For compatibility, CUPS provides both programs.)
You can probably achieve something like you were after with popen(3). In shell, it'd be something like:
echo hello | lp -
The - says to print from standard input.
I haven't tested this, but the popen(3) equivalent would probably look like this:
FILE *f = popen("lp -", "w");
if (!f)
exit(1);
fprintf(f, "output to the printer");
I recommend testing some inputs at the shell first to make sure that CUPS is prepared to handle the formatting of the content you intend to send. You might need to terminate lines with CRLF rather than just \n, otherwise the printer may "stair-step" the output. Or, if you're sending PDF or PS or PCL data, it'd be worthwhile testing that in the cheapest possible manner to make sure the print system works as you expect.