get all running processes info using QProcess - windows

few days ago i asked about how to get all running processes in the system using QProcess.
i found a command line that can output all processes to a file:
C:\WINDOWS\system32\wbem\wmic.exe" /OUTPUT:C:\ProcessList.txt PROCESS get Caption
this will create C:\ProcessList.txt file contains all running processes in the system.
i wonder how can i run it using QProcess and take its output to a variable.
it seems every time i try to run it and read nothing happens:
QString program = "C:\\WINDOWS\\system32\\wbem\\wmic.exe";
QStringList arguments;
arguments << "/OUTPUT:C:\\ProcessList.txt" <<"PROCESS"<< "get"<< "Caption";
process->setStandardOutputFile("process.txt");
process->start(program,arguments);
QByteArray result = process->readAll();
i prefer not to create process.txt at all and to take all the output to a variable...

You can run wmic.exe with "/OUTPUT:STDOUT" switch to print the process info directly to stdout. However, I was unable to read this info through QProcess API and save it in variable. Here's the code I used:
#include <QtCore/QCoreApplication>
#include <QProcess>
#include <QDebug>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QProcess process;
process.setReadChannel(QProcess::StandardOutput);
process.setReadChannelMode(QProcess::MergedChannels);
// process.start("cmd.exe /C echo test");
process.start("wmic.exe /OUTPUT:STDOUT PROCESS get Caption");
process.waitForStarted(1000);
process.waitForFinished(1000);
QByteArray list = process.readAll();
qDebug() << "Read" << list.length() << "bytes";
qDebug() << list;
}
This code successfully captures output of "cmd.exe /C echo test", but doesn't work on wmic.exe. It seems that process wmic.exe is never finished, and I suppose it's stdout is never flushed so you don't receive anything throught QProcess::readAll().
That's all help I can give you. Maybe you, or some other SO user will find bug in the snippet above.

Try this it will work well.
process.start("cmd", QStringList() << "/C" << "echo" << "process" << "get" << "caption" << "|" << "wmic");

Related

How to write a shell script(any shell languages) that interacts with a program and passes arguments? [duplicate]

This question already has answers here:
Passing arguments to an interactive program non-interactively
(5 answers)
Closed 4 years ago.
#include <iostream>
using namespace std;
int main(void){
int number = 0;
cout << "Please enter a number: ";
cin >> number ;
cout << "the number you enter is " << number << endl;
return 0;}
This is my program that takes in an argument and prints it out.
#! /bin/bash
number=1
echo "1" | ./a.out #>> result.txt
This is my bash script that is trying to pass an argument to the program.
1
Please enter a number: the number you enter is 1
This is the result.txt. I wanted it more like this:
Please enter a number: 1
the number you enter is 1
How should I fix it so that the script would pass the argument more like a human does.
And is bash a really good scripting language doing this kind of work or there are other better scripting languages. (google says tcl is better that bash for this kind of interactive program?)
Unless I'm misunderstanding the problem, if you'd like to pass parameters to your c++ program, you should add argc and argv to your main function.
Your program.cpp:
#include <iostream>
using namespace std;
int main(int argc, char *argv[]) {
cout << "your number is " << argv[1] << endl;
return 0;
}
The shell script (send-arg.sh):
#!/bin/sh
./program 42
Output:
./send-arg.sh
your number is 42

Specific pipe command in Ubuntu's shell handling in C

I'm trying to simulate a pipe behavior on Ubuntu's Terminal, for example the command:
"echo hello | wc".
Please assume I got the tokens from stdin, handled everything correctly and now These are the commands I "received" from the user who typed them in the shell for me to handle.
I'm trying to create two processes. Using a pipe, in the first process, I point the file descriptor of the writing edge of the pipe to stdout. The second process should read into stdin with the reading edge of the pipe what execvp(..) returned.?
Here is the code I wrote:
#include <stdio.h>
#include <stdlib.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
int main()
{
char* fcmd[] = {"echo", "hello", NULL};
char* scmd[] = {"wc", NULL};
pid_t pid;
int pipe_des[2];
int i;
pipe(pipe_des);
for(i = 0; i < 2; i++)
{
pid = fork();
if (pid ==0)
{
switch (i)
{
case 0: // FIRST CHILD
{
dup2(pipe_des[1], STDOUT_FILENO);
close(pipe_des[0]);
execvp(fcmd[0], fcmd);
exit(0);
}
case 1: //SECOND CHILD
{
dup2(pipe_des[0], STDIN_FILENO);
close(pipe_des[1]);
execvp(scmd[0], scmd);
exit(0);
}
}
}
else if (pid < 0)
exit(EXIT_FAILURE);
return EXIT_SUCCESS;
}
I get: " amirla#ubuntu:~/Desktop/os/class/ex4$ 1 1 6 "
Like it should, but why he's printing the bash cwd first? The pipe seems to work because I get what I should, according to the length of the word I'm sending with the echo command(in the main()). After that the cursor just waits on the line below for another command without showing me the bash pwd. (maybe stdin is waiting?)
I've looked in many posts on here as well as on other websites and I still can't seem to find a solution to my problem. Any help would be appreciated. Thanks in advance.
Note: Please Ignore checking for errors, I've delete them to make the code shorter so assume they exist.
Why do I get a prompt before the output?
Your main process doesn't wait for the children to finish. What you see is:
Main starts
Main creates children
Main exits
BASH prints prompt
Children start their work
To prevent this, you need to wait for the children. See How to wait until all child processes called by fork() complete?
In your case, it's enough to add
waitpid(-1, NULL, 0);
after the loop.

Empty Working Set from cmd

I want to write a cmd script to periodically empty the working set from the command prompt. For now I empty the working set in the Rammap tool from sysinternals, but that can't be run by a script.
It's probably easiest to compile something like this:
#include <iostream>
#include <windows.h>
int main(int argc, char **argv) {
if (argc != 2) {
std::cerr << "Usage: min_mem <process_id>\n";
return 1;
}
HANDLE process = OpenProcess(PROCESS_SET_QUOTA, false, atoi(argv[1]));
SetProcessWorkingSetSize(process, -1, -1);
}
...and then run it in your script, something like:
mem_min 1234
...but replacing 1234 with the process ID (in decimal) of the process whose memory you want to minimize.
That said: I'd ask that this answer not be upvoted, since it's really a pretty crappy answer to a question that's basically just a gimme the codez I've been weak enough to post it, but would prefer not to get any rep for doing so.

Qt - Opening a custom file via double-click

I have a program and a .l2p file with some lines of info.
I have run a registry file:
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\.l2p\DefaultIcon]
#="\"C:\\Program Files\\ToriLori\\L2P.exe\",0"
[HKEY_CLASSES_ROOT\.l2p\shell\Open\command]
#="\"C:\\Program Files\\ToriLori\\L2P.exe\" \"%1\""
When I double-click the .l2p file the program starts but doesn't load the file. What do I have to do to make it load properly? Example code would be very appreciated.
When you double click on a file the file name is passed as a command line argument to the associated program. You have to parse the command line, get the file name and open it (how to do that depends on how your program works).
#include <iostream>
int main(int argc, char *argv[])
{
for (int i = 1; i < argc; ++i) {
std::cout << "The " << i << "th argument is " << argv[i] << std::endl;
}
}
If you run this program from command line:
>test.exe "path/to/file" "/path/to/second/file"
The 1th argument is path/to/file
The 2th argument is /path/to/second/file
In Qt if you create a QApplication you can also access the command line arguments via QCoreApplications::arguments().
You might want to load the file after having created your main window. You may do something like this:
#include <QApplication>
#include <QTimer>
#include "MainWindow.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow window;
QTimer::singleShot(0, & window, SLOT(initialize()));
window.show();
return app.exec();
}
This way the slot MainWindow::initialize() (which you have to define) gets called as soon as the event loop has started.
void MainWindow::initialize()
{
QStringList arguments = QCoreApplication::arguments();
// Now you can parse the arguments *after* the main window has been created.
}
If I'm understanding your question correctly, L2P.exe is a Qt program you created and you want to handle a passed argument as specifying a file to open. If that's the case, you just need to read that argument in your main() method and handle it. (This isn't something that happens automatically.) Something like the following, although you obviously want to add a bit of error checking:
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
const QStringList arguments = a.arguments();
// The final argument is assumed to be the file to open.
if (arguments.size() > 1 && QFile::exists(arguments.last())) {
your_app_open(arguments.last());
}
// ... etc.
}

How to remove file if application is not running?

Not sure whether this is possible, but I'm creating a file encoding applcation. When a file is decoded, it is saved temporarily in a temp directory, after which it can be opened regularly. However, I actually need to be certain the file is removed as soon as the application that has opened it, has closed it (e.g. has shut down). Otherwise, the decoded (secret) file is just hanging in the temp directory without supervision.
What's more, even when my application itself has been shut down for any reason, I'd like to pass this task on to Windows, if possible. So say the user decodes a file and opens it and then my application is shut down (either normally or abnormally), the decoded file in the temp directory should still be removed as soon as it's not used anymore.
How would I go about this? I've seen tips like FileSystemWatcher and a trivial 'check every second' idea, but if my application is not alive at the moment the decoded file is closed, I'd still like to have the file removed. So I guess I'd need to pass this responbility to Windows, but I'm not sure if that's possible and if so, how.
So how do I remove a file as soon as it's closed if my application isn't running at that particular moment?
Doing this may work:
In the process that creates the file, create it with FileOptions.DeleteOnClose, and with FileShare.ReadWrite (or FileShare.Read if only read access is required from other processes). You may also need FileShare.Delete.
DO NOT let the file close in the main application that created it until the application exits.
In other processes that consume the temporary file, open it with the same file options as the original.
This way, when the last process that has the file open closes, the file will be deleted.
UPDATE:
As noted in the comments, there doesn't seem to be a way in the .NET API to specify both the FIleShare options and the FileOptions.DeleteOnClose. It is possible using straight Win32. I have copied a sample that I tested below. There are 2 programs, one that creates the file, another that consumes it. The only notable difference between the 2 is that the consumer opens the file with OPEN_EXISTING.
Creator
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <iostream>
#include <string>
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE fh = CreateFile(
L"yourFilePath\\tempFile.dat",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_WRITE|FILE_SHARE_READ|FILE_SHARE_DELETE,
NULL,
CREATE_NEW,
FILE_FLAG_DELETE_ON_CLOSE,
NULL);
if(fh==INVALID_HANDLE_VALUE)
{
std::cerr << "Failed to create file. Error code = " << GetLastError() << std::endl;
return 1;
}
std::cout<< "Hit enter to close.";
std::string inp;
std::getline(std::cin,inp);
CloseHandle(fh);
return 0;
}
Consumer
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <iostream>
#include <string>
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE fh = CreateFile(
L"yourFilePath\\tempFile.dat",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_WRITE|FILE_SHARE_READ|FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING,
FILE_FLAG_DELETE_ON_CLOSE,
NULL);
if(fh==INVALID_HANDLE_VALUE)
{
std::cerr << "Failed to create file. Error code = " << GetLastError() << std::endl;
return 1;
}
DWORD written;
if(!WriteFile(fh,"Test",4,&written,NULL))
{
std::cerr << "Failed to write data to file. Error code = " << GetLastError() << std::endl;
return 1;
}
std::cout<< "Hit enter to close.";
std::string inp;
std::getline(std::cin,inp);
CloseHandle(fh);
return 0;
}
Use FileOptions.DeleteOnClose.
Things like FileOptions.DeleteOnClose won't help if your media becomes unavailable or the machine gets shut down before the delete occurs. To me this looks very much like an exogenous condition.
Can you stream the decoding to a memory stream rather than to disk and take the whole problem away.

Resources