Run command line process as admin Qt - c++

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);

Related

Transition to command prompt once my console program finishes?

I'm writing some executables that use the Windows console, in C and C++.
I'm trying to get the console to not close after the logic of my program finishes... But not just merely pause or wait, I'd like it to become a cmd.exe command line console itself, ready to accept new prompts.
Essentially I'd like the behavior of running my program via double-clicking or drag-and-dropping to be equivalent to hitting winkey + r and running :
cmd /k "program.exe [list of drag+drop files if any]"
(While not opening a new console if run from a command-line itself.)
Is this possible at all?
Edit
I've been tinkering with this and arrived to a solution that seems to work:
std::getenv("PROMPT") will return 0 when not run from the commandline (I think anyway, not sure if that holds in all cases), and so that can be used to fork the logic depending on how the executable is run.
The following code works for me at least, in my limited experimentation with it. If it's run from the explorer, it uses it's first instance to invoke cmd.exe with parameters that lets THAT instance invoke our program again, with the original parameters.
int main(int argc, char * argv[]) {
// checks if we're in the explorer window, if so delegates to a new instance
if (std::getenv("PROMPT") == NULL) {
printf("Starting from explorer...\n");
std::string str("cmd /Q /k \"");
for (uint32 n = 0; n < argc; ++n) {
str.append("\"");
str.append(argv[n]);
str.append("\"");
if(n < argc-1)
str.append(" ");
}
str.append("\"\n");
system(str.c_str());
return 0;
}
// actual code we want to run
uint32 fileCount = 0;
for (uint32 n = 0; n < argc - 1; ++n) {
fileCount++;
printf("file %02u >> %s\n", n, argv[n+1]);
}
if (fileCount == 0) {
printf("No inputs...\n");
}
return 0;
}
So I guess conceptually, it looks like this.
____stays open_______________________ __closes when finished___
program.exe [paramList] ---> cmd.exe -+-> program.exe [paramList]
|
+-> any subsequent commands
|
etc
In my opinion, you have linked your program as a Windows console program, so it will always open a console terminal when you run it. In that case, your program is presenting the information it outputs in the console (as if the standard output had been redirected to the opened window) this means you cannot use it as a UNIX filter like dir or copy commands. (indeed, you are not in a unix system, so the console is emulated with a special windows library that is linked to your program).
To be able to run your program inside a cmd.exe invocation in a normal window terminal (as you do with the dir command --well, dir is internal to cmd.exe, but others, like xcopy.exe aren't), you need to build your program as a different program type (a unix filter command or a windowless console program, I don't remember the program type name as I'm not a frequent windows developer) so the standard input and the standard output (these are things that Windows hinerits from MS-DOS) are preserved on the program that started it, and you program is capable of running with no window at all.
Windows console program is a different thing that a windows filter program that doesn't require a console to run. The later is like any other ms-dos like command (like dir or copy) and they have an interface more similar to the unix like counterparts.
If you do this, you will be able to run your program from cmd in another window, and it will not create a Windows terminal console to show your program output.
You could simply insert the line
system( "cmd" );
at the end of your program, which will call the command prompt after your program finished executing.
However, this may not fulfil your following requirement:
(While not opening a new console if run from a command-line itself.)
Although using system( "cmd" ); will not open a new console window (it will use the existing one), it will create a new process cmd.exe, which means that you will now have 2 cmd.exe processes if your program was invoked by cmd.exe. Also, if the original cmd.exe process was invoked by your own program, then you will now have 2 processes running your program. If you now call your program again from this new command prompt, you will now have 3 cmd.exe processes and 3 processes running your program. This could get ugly very quickly, especially if you are repeatedly calling your program from a batch file.
In order to prevent this, then your program could try to somehow detect whether its parent process already is cmd.exe, and if it was, it should exit normally instead of invoking cmd.exe again.
Unfortunately, the Windows API does not seem to offer any official way for a child process to obtain the process ID of its parent process. However, according to this page, it is possible to accomplish this using undocumented functions.
Using undocumented functions is generally not advisable, though. Therefore, it would probably be better if you always called your program from a command prompt, so that it could simply exit normally.

Trying to display a text through CMD with C++ and I am presented with a error [duplicate]

This is a probably an embarasing question as no doubt the answer is blindingly obvious.
I've used Visual Studio for years, but this is the first time I've done any 'Console Application' development.
When I run my application the console window pops up, the program output appears and then the window closes as the application exits.
Is there a way to either keep it open until I have checked the output, or view the results after the window has closed?
If you run without debugging (Ctrl+F5) then by default it prompts your to press return to close the window. If you want to use the debugger, you should put a breakpoint on the last line.
Right click on your project
Properties > Configuration Properties > Linker > System
Select Console (/SUBSYSTEM:CONSOLE) in SubSystem option or you can just type Console in the text field!
Now try it...it should work
Starting from Visual Studio 2017 (15.9.4) there is an option:
Tools->Options->Debugging->Automatically close the console
The corresponding fragment from the Visual Studio documentation:
Automatically close the console when debugging stops:
Tells Visual Studio to close the console at the end of a debugging session.
Here is a way for C/C++:
#include <stdlib.h>
#ifdef _WIN32
#define WINPAUSE system("pause")
#endif
Put this at the top of your program, and IF it is on a Windows system (#ifdef _WIN32), then it will create a macro called WINPAUSE. Whenever you want your program to pause, call WINPAUSE; and it will pause the program, using the DOS command. For other systems like Unix/Linux, the console should not quit on program exit anyway.
Goto Debug Menu->Press StartWithoutDebugging
If you're using .NET, put Console.ReadLine() before the end of the program.
It will wait for <ENTER>.
try to call getchar() right before main() returns.
(/SUBSYSTEM:CONSOLE) did not worked for my vs2013 (I already had it).
"run without debugging" is not an options, since I do not want to switch between debugging and seeing output.
I ended with
int main() {
...
#if _DEBUG
LOG_INFO("end, press key to close");
getchar();
#endif // _DEBUG
return 0;
}
Solution used in qtcreator pre 2.6. Now while qt is growing, vs is going other way. As I remember, in vs2008 we did not need such tricks.
just put as your last line of code:
system("pause");
Here's a solution that (1) doesn't require any code changes or breakpoints, and (2) pauses after program termination so that you can see everything that was printed. It will pause after either F5 or Ctrl+F5. The major downside is that on VS2013 Express (as tested), it doesn't load symbols, so debugging is very restricted.
Create a batch file. I called mine runthenpause.bat, with the following contents:
%1 %2 %3 %4 %5 %6 %7 %8 %9
pause
The first line will run whatever command you provide and up to eight arguments. The second line will... pause.
Open the project properties | Configuration properties | Debugging.
Change "Command Arguments" to $(TargetPath) (or whatever is in "Command").
Change "Command" to the full path to runthenpause.bat.
Hit OK.
Now, when you run, runthenpause.bat will launch your application, and after your application has terminated, will pause for you to see the console output.
I will post an update if I figure out how to get the symbols loaded. I tried /Z7 per this but without success.
add “| pause” in command arguments box under debugging section at project properties.
You could run your executable from a command prompt. This way you could see all the output. Or, you could do something like this:
int a = 0;
scanf("%d",&a);
return YOUR_MAIN_CODE;
and this way the window would not close until you enter data for the a variable.
Just press CNTRL + F5 to open it in an external command line window (Visual Studio does not have control over it).
If this doesn't work then add the following to the end of your code:
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
This wait for you to press a key to close the terminal window once the code has reached the end.
If you want to do this in multiple places, put the above code in a method (e.g. private void Pause()) and call Pause() whenever a program reaches a possible end.
A somewhat better solution:
atexit([] { system("PAUSE"); });
at the beginning of your program.
Pros:
can use std::exit()
can have multiple returns from main
you can run your program under the debugger
IDE independent (+ OS independent if you use the cin.sync(); cin.ignore(); trick instead of system("pause");)
Cons:
have to modify code
won't pause on std::terminate()
will still happen in your program outside of the IDE/debugger session; you can prevent this under Windows using:
extern "C" int __stdcall IsDebuggerPresent(void);
int main(int argc, char** argv) {
if (IsDebuggerPresent())
atexit([] {system("PAUSE"); });
...
}
Either use:
cin.get();
or
system("pause");
Make sure to make either of them at the end of main() function and before the return statement.
You can also use this option
#include <conio.h>
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
int main() {
.
.
.
getch();
return 0;
}
In my case, i experienced this when i created an Empty C++ project on VS 2017 community edition. You will need to set the Subsystem to "Console (/SUBSYSTEM:CONSOLE)" under Configuration Properties.
Go to "View" then select "Property Manager"
Right click on the project/solution and select "Property". This opens a Test property page
Navigate to the linker then select "System"
Click on "SubSystem" and a drop down appears
Choose "Console (/SUBSYSTEM:CONSOLE)"
Apply and save
The next time you run your code with "CTRL +F5", you should see the output.
Sometimes a simple hack that doesnt alter your setup or code can be:
Set a breakpoint with F9, then execute Debug with F5.
Since running it from VS attaches the VS debugger, you can check for an attached debugger:
if (Debugger.IsAttached)
{
Console.WriteLine("Debugger is attached. Press any key to exit.");
Console.ReadKey();
}
I guess the only caveat is that it'll still pause if you attach any other debugger, but that may even be a wanted behavior.
Use Console.ReadLine() at the end of the program. This will keep the window open until you press the Enter key. See https://learn.microsoft.com/en-us/dotnet/api/system.console.readline for details.
Visual Studio 2015, with imports. Because I hate
when code examples don't give the needed imports.
#include <iostream>;
int main()
{
getchar();
return 0;
}
Currently there is no way to do this with apps running in WSL2. However there are two work-arounds:
The debug window retains the contents of the WSL shell window that closed.
The window remains open if your application returns a non-zero return code, so you could return non-zero in debug builds for example.
It should be added that things have changed since then. On Windows 11 (probably 10, I can't check any more) the new Terminal app that now houses the various console, PowerShell and other sessions has its own settings regarding closing. Look for it in Settings > Defaults > Advanced > Profile termination behavior.
If it's set to close when a program exits with zero, then it will close, even if VS is told otherwise.
Go to Setting>Debug>Un-check close on end.

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/

Running a console command which is stored in `std::wstring`

I have a console command, something like:
std::wstring ConsoleCommand;
ConsoleCommand = L"c:\\somepath\\anotherpath\\program.exe -opt1 /opt2 --opt3";
I want to execute this command.
How do I do it?
(It may be a Win32 API function, or a standard C/C++ library.)
Try ShellExecute(). You probably want the open verb. You could also use CreateProcess().
You must _wsystem() or _wpopen() on Windows.

How to output to the console in C++/Windows

When using iostream in C++ on Linux, it displays the program output in the terminal, but in Windows, it just saves the output to a stdout.txt file. How can I, in Windows, make the output appear in the console?
Since you mentioned stdout.txt I google'd it to see what exactly would create a stdout.txt; normally, even with a Windows app, console output goes to the allocated console, or nowhere if one is not allocated.
So, assuming you are using SDL (which is the only thing that brought up stdout.txt), you should follow the advice here. Either freopen stdout and stderr with "CON", or do the other linker/compile workarounds there.
In case the link gets broken again, here is exactly what was referenced from libSDL:
How do I avoid creating stdout.txt and stderr.txt?
"I believe inside the Visual C++ project that comes with SDL there is a SDL_nostdio target > you can build which does what you want(TM)."
"If you define "NO_STDIO_REDIRECT" and recompile SDL, I think it will fix the problem." > > (Answer courtesy of Bill Kendrick)
For debugging in Visual Studio you can print to the debug console:
OutputDebugStringW(L"My output string.");
If you have a none-console Windows application, you can create a console with the AllocConsole function. Once created, you can write to it using the normal std::cout methods.
If you're using Visual Studio you need to modify the project property:
Configuration Properties -> Linker -> System -> SubSystem.
This should be set to: Console (/SUBSYSTEM:CONSOLE)
Also you should change your WinMain to be this signature:
int main(int argc, char **argv)
{
//...
return 0;
}
The AllocConsole Windows API function will create a console window for your application.
If you're using Visual Studio, it should work just fine!
Here's a code example:
#include <iostream>
using namespace std;
int main (int) {
cout << "This will print to the console!" << endl;
}
Make sure you chose a Win32 console application when creating a new project. Still you can redirect the output of your project to a file by using the console switch (>>). This will actually redirect the console pipe away from the stdout to your file. (for example, myprog.exe >> myfile.txt).
I wish I'm not mistaken!
Whether to use subsystem:console or subsystem:windows kind of depends on whether how you want to start your application:
If you use subsystem:console, then you get all of the stdout written to the terminal. The trouble is that if you start the application from the Start Menu/Desktop, you (by default) get a console appearing as well as the application window (which can look pretty ugly).
If you use subsystem:windows, you won't get stdout/stderr even if you run the application from a DOS window, Cygwin, or other terminal.
If you want the middle way which is to output to the terminal IF the application was started in a terminal, then follow the link that Luke provided in his solution (http://dslweb.nwnexus.com/~ast/dload/guicon.htm)
For reference, I ran into this problem with an application that I want to run in either normal Windows mode or batch mode (that is, as part of a script) depending on command-line switches. The whole differentiation between console and Windows applications is a bit bizarre to Unix folks!
First off, what compiler or dev environment are you using? If Visual Studio, you need to make a console application project to get console output.
Second,
std::cout << "Hello World" << std::endl;
should work in any C++ console application.
Your application must be compiled as a Windows console application.
There is a good solution
if (AllocConsole() == 0)
{
// Handle error here. Use ::GetLastError() to get the error.
}
// Redirect CRT standard input, output and error handles to the console window.
FILE * pNewStdout = nullptr;
FILE * pNewStderr = nullptr;
FILE * pNewStdin = nullptr;
::freopen_s(&pNewStdout, "CONOUT$", "w", stdout);
::freopen_s(&pNewStderr, "CONOUT$", "w", stderr);
::freopen_s(&pNewStdin, "CONIN$", "r", stdin);
// Clear the error state for all of the C++ standard streams. Attempting to accessing the streams before they refer
// to a valid target causes the stream to enter an error state. Clearing the error state will fix this problem,
// which seems to occur in newer version of Visual Studio even when the console has not been read from or written
// to yet.
std::cout.clear();
std::cerr.clear();
std::cin.clear();
std::wcout.clear();
std::wcerr.clear();
std::wcin.clear();
I assume you're using some version of Visual Studio? In windows, std::cout << "something"; should write something to a console window IF your program is setup in the project settings as a console program.
If using MinGW, add an option, -Wl,subsystem,console or -mconsole.
You don't necessarily need to make any changes to your code (nor to change the SUBSYSTEM type). If you wish, you also could simply pipe stdout and stderr to a console application (a Windows version of cat works well).