Why cannot execute "taskkill" from cmd in c++? - c++

I want to execute taskkill from cmd in c++ code. I have tried two forms:
Simple form:
system("taskkill /IM 'example.exe' /F");
With administrative privilege (because one of my processes has high privilege):
system("runas / profile / user:administrator \"taskkill /IM 'exmaple.exe' /F\"");
Also my c++ program was run as administrator.
But none of these commands executed successfully. What is the problem?

An immediate fix could be to remove the single quotes (') enclosing example.exe.
E.g. instead of:
system("taskkill /IM 'example.exe' /F");
Use:
system("taskkill /IM example.exe /F");
Using double quotes (" - escaped in this case with \) is also OK:
system("taskkill /IM \"example.exe\" /F");
However -
As commented above by #PepijnKramer, you can use dedicated windows API functions to do the same.
This requires a bit more code, but offers much better control and feedback of errors.
Here's an outline of what you need to do:
Get the process PID from its name (see below).
Open the process using OpenProcess API to aqcuire a handle to it, with PROCESS_TERMINATE access right (see below).
An example of getting PID and then a handle to a process by its name: How can I get a process handle by its name in C++?.
Use the handle with TerminateProcess API to kill the process.
Note that in order to use it:
The handle must have the PROCESS_TERMINATE access right.
(this should be passed to OpenProcess via the dwDesiredAccess parameter).

Related

wait until shell command is executed

I have a script where I launch a shell command. The problem is that the script doesn't wait until the command is finished and continues right away.
I have tried WAIT but it doesn't work as the shell command turns the source off and on (ignition off/on) and I get the error that WAIT cannot be executed because power is off.
Is there any command I can use for program to wait until the command is executed?
My script looks like this:
OS.COMMAND echo OUTP OFF > COM1
OS.COMMAND echo OUTP ON > COM1
System.up
If I would want to execute a shell command without redirecting I would use OS.Area instead of OS.Command, because OS.Area is blocking and will wait until the shell command has finished. However OS.Area does not support redirecting I think.
If I would want to execute a shell command and redirect the output to a file I would first delete the file and then wait until it gets accessible. Like this:
IF OS.FILE.EXIST("myfile.txt")
RM "myfile.txt"
OS.Command ECHO "Hello World" > "myfile.txt"
WAIT OS.FILE.readable("myfile.txt")
However it looks like you want to write via a shell command to a COM port on Windows. But I don't think it is possible to wait in TRACE32 until this write to the COM port has been done when using OS.Command...
So I suggest to do this task with the TERM commands instead:
TERM.METHOD #1 COM COM1 115200. 8 NONE 1STOP NONE
TERM.view #1
TERM.Out #1 "OUTP OFF" 0x0A
TERM.Out #1 "OUTP ON" 0x0A
Of course you have to set the correct baud rate, bits, parity and stop bits. The 0x0A after each TERM.Out is simply the line-feed character.
Does you terminal show any output as a reaction to OUTP ON? If yes you can also wait for this output with e.g. SCREEN.WAIT TERM.LINE(#1,-1)=="OUTP is now ON" 5.s
Otherwise I assume that a simple WAIT 50.ms before SYStem.Up will probably do the trick too.

How can I find why system can not run my application?

I have a c++ program that run a command and pass some arguments to it. The code is as follow:
int RunApplication(fs::path applicationPathName,std::string arguments)
{
std::string applicationShortPath=GetShortFileName(applicationPathName);
std::string cmd="\""+applicationShortPath +"\" "+ arguments+" >>log.txt 2>&1 \"";
std::cout<<cmd<<std::endl;
int result=std::system(cmd.c_str());
return result;
}
When I run system command, the cmd window appears shortly and then closes, but the result is 1 and the cmd was not run (the command should generate output which is not generated).
To check that the cmd is correct, I stopped the application just before system line and copy/ paste cmd content to a cmd window and it worked.
I am wondering how can I find why application is not run in system()?
the cmd has this value just before running it:
"D:/DEVELO~3/x64/Debug/enfuse.exe" -w --hard-mask --exposure-weight=1 --saturation-weight=0.328 --contrast-weight=0.164 -o "C:/Users/m/AppData/Local/Temp/1.tif" "C:/Users/m/AppData/Local/Temp/1.jpg" "C:/Users/m/AppData/Local/Temp/2.jpg" >>log.txt 2>&1 "
How can I find why it is not working?
Is there any way that I set the system so it doesn't close cmd window so I can inspect it?
is there any better way to run a command on OS?
Does Boost has any solution for this?
Edit
After running it with cmd /k, I get this error message:
The input line is too long.
How can I fix it other than reducing cmd line?
There are two different things here: if you have to start a suprocess, "system" is not the best way of doing it (better to use the proper API, like CreateProcess, or a multiplatform wrapper, but avoid to go through the command interpreter, to avoid to open to potential malware injection).
But in this case system() is probably the right way to go since you in fact need the command interpreter (you cannot manage things like >>log.txt 2>&1 with only a process creation.)
The problem looks like a failure in the called program: may be the path is not correct or some of the files it has to work with are not existent or accessible with appropriate-permission and so on.
One of the firt thing to do: open a command prompt and paste the string you posted, in there. Does it run? Does it say something about any error?
Another thing to check is how escape sequence are used in C++ literals: to get a '\', you need '\\' since the first is the escape for the second (like \n, or \t etc.). Although it seems not the case, here, it is one of the most common mistakes.
Use cmd /k to keep the terminal: http://ss64.com/nt/cmd.html
Or just spawn cmd.exe instead and inspect the environment, permissions, etc. You can manually paste that command to see whether it would work from that shell. If it does, you know that paths, permssions and environment are ok, so you have some other issue on your hands (argument escaping, character encoding issues)
Check here How to execute a command and get output of command within C++ using POSIX?
Boost.Process is not official yet http://www.highscore.de/boost/process/

Run command line process as admin Qt

I am writing a Qt application that needs to call system programs (netsh) and run them as administrator.
However, QProcess, QDesktopServices and system() don't allow me to run the application as administrator (not even with runas).
The only solution that I found is to use ShellExecute, but it does not even open the program.
My code is:
#ifdef Q_OS_WIN {
ShellExecute(0, LPCWSTR("runas"), LPCWSTR("netsh wlan start hostednetwork"), 0, 0, SW_SHOWNORMAL);
}
I have also tried to use other options, such as open and tried to run other programs, such as Notepad (notepad.exe) and Control Panel (control.exe), nothing worked.
I have also tried to add an manifest file and nothing was solved.
Do I miss something in my code? (examples are welcome).
LPCWSTR("runas") - this is incorrect, you typecast string to widestring, and probably ShellExecute will return error and does not start an application. Specify "L" prefix instead.
Also, you need to split command and parameters, "netsh wlan start hostednetwork" will not work as command name.
Use it like this:
ShellExecute(0, L"runas", L"netsh", L"wlan start hostednetwork", 0, SW_SHOWNORMAL);

Querying process by CommandLine

I'm trying to do the following query in WMI:
SELECT ProcessID from Win32_Process where CommandLine='C:\Windows\system32\calc.exe'
But I got an "Invalid query" error. I also tried with:
SELECT ProcessID from Win32_Process where CommandLine='C:\\Windows\\system32\\calc.exe'
And still get the same error, also I tried to change the single quotes to double quotes but it didn't work.
Does anybody know if its possible to do that query?
Yes and No. Depends on how calc.exe is spawned. For instance, when I type calc into cmd.exe window, my calc gets a commandline of 'calc'. When I type calc into powershell.exe console, it get's a full path. The Win32_Process 'commandline' variable is not reliable IMO. Here are some differing result to prove my point.
cmd.exe 4028 C:\Windows\system32\cmd.exe /K set
calc.exe 2580 "C:\Windows\system32\calc.exe"
notepad.exe 3612 "C:\Windows\system32\notepad.exe"
cmd.exe 2864 "C:\Windows\system32\cmd.exe"
conhost.exe 480 \??\C:\Windows\system32\conhost.exe
WMIC.exe 3596 wmic
WmiPrvSE.exe 2272 C:\Windows\system32\wbem\wmiprvse.exe
cmd.exe 2296 "C:\Windows\system32\cmd.exe"
conhost.exe 3708 \??\C:\Windows\system32\conhost.exe
notepad.exe 1284 "C:\Windows\system32\notepad.exe"
calc.exe 1736 calc
powershell.exe 3136 "C:\WINDOWS\system32\WindowsPowerShell\v1.0\powershell.exe"
So to make it work you will need an OR clause in your SQL statement, matching 'calc' or "C:\Windows\system32\calc.exe"
In addition Windows adds sometimes an additional whitespace into the command line after the ExecutablePath and before the first parameter.
Even if there is no paramter and the Executable was lanched with quotes (because of whitespaces in the path) then in most cases the command line is the ExecutablePath and a final whitespace at the end.
That cost me some hours to find this.
Cheers!

How to get forkpty/execvp() to properly handle redirection and other bash-isms?

I've got a GUI C++ program that takes a shell command from the user, calls forkpty() and execvp() to execute that command in a child process, while the parent (GUI) process reads the child process's stdout/stderr output and displays it in the GUI.
This all works nicely (under Linux and MacOS/X). For example, if the user enters "ls -l /foo", the GUI will display the contents of the /foo folder.
However, bash niceties like output redirection aren't handled. For example, if the user enters "echo bar > /foo/bar.txt", the child process will output the text "bar > /foo/bar.txt", instead of writing the text "bar" to the file "/foo/bar.txt".
Presumably this is because execvp() is running the executable command "echo" directly, instead of running /bin/bash and handing it the user's command to massage/preprocess.
My question is, what is the correct child process invocation to use, in order to make the system behave exactly as if the user had typed in his string at the bash prompt? I tried wrapping the user's command with a /bin/bash invocation, like this: /bin/bash -c the_string_the_user_entered, but that didn't seem to work. Any hints?
ps Just calling system() isn't a good option, since it would cause my GUI to block until the child process exits, and some child processes may not exit for a long time (if ever!)
If you want the shell to do the I/O redirection, you need to invoke the shell so it does the I/O redirection.
char *args[4];
args[0] = "bash";
args[1] = "-c";
args[2] = ...string containing command line with I/O redirection...;
args[4] = 0;
execv("/bin/bash", args);
Note the change from execvp() to execv(); you know where the shell is - at least, I gave it an absolute path - so the path-search is not relevant any more.