Is this possible? I wish AllocConsole (or a set of function calls behaving the same way) to allocate a PowerShell window instead of a normal console window.
If it's not possible, can I CreateProcess and attach my input and output to a PowerShell instance?
PowerShell also uses a "normal console window" because there is only one console window type. Cmd.exe and PowerShell.exe are not special, they just use the normal Windows console API functions.
If you want to control stdin and stdout then you must create some pipes with CreatePipe and set STARTF_USESTDHANDLES and the handles in STARTUPINFO before calling CreateProcess. See this MSDN example for details. You can write the stdout data to a console window you create with AllocConsole if you also want to display the output. Note that when you redirect stdin/stdout the interactive console functions no longer work.
Related
So, to be more specific, I want to make a C++ program (Windows) that can execute a command without anything being displayed to the user.
No CMD window, No Command Output.
I would show my previous attempts, but it's not really anything useful, I just used the system() function to execute a command. I need to do the same, but without a popup window.
system() uses CreateProcess() to run cmd.exe /C <command>. You have no control over the console window that may be created.
Use CreateProcess() directly instead, so you can specify the CREATE_NO_WINDOW flag, and/or set its input STARTUPINFO::wShowWindow field to SW_HIDE.
I have a WinAPI/Win32 application. If I try to use cin/cout/cerr when it is run from a command prompt, it doesn't work. I tried switching the project type from Windows Application to Console Application, but the problem is that a console window appears when I run it normally by double-clicking the executable.
So my question is: Is there any way I can use cin/cout/cerr with the parent (calling) console window in a Win32 application? (I only want this behaviour if parameter /c or /? were passed, so if it is called with no arguments then no matter what it should launch the GUI).
A GUI app does not have a console window attached to it by default.
When a GUI app is run from a console process, the GUI app can use AttachConsole() to attach itself to the console.
Or, if the GUI app is not run from a console process, but still wants to use a console window, it can create its own console window using AllocConsole().
Once the GUI app is attached to a console, it can use GetStdHandle() to get handles to the console's STDIN/STDOUT, and then redirect cin/cout to use them (how is dependent on your particular STL implementation).
Or, you can ignore cin/cout and just use ReadConsole() and WriteConsole() directly instead.
If you use CreateProcess with the flag CREATE_NEW_CONSOLE, the new process has its standard input, output, and error handles directed to the new console window. If you want to override the I/O streams, you can do so by setting the handles in STARTUPINFO fields hStdOutput, hStdInput, and hStdError and setting the flag STARTF_USESTDHANDLES.
But what if you want to override only one of the handles? For example, I might want to redirect stderr to a file while leaving the stdout and stdin connected to the new console window.
The STARTF_USESTDHANDLES flag tells CreateProcess to replace all of the handles instead of connecting them to the ones for the new console window. So it seems we must provide all three handles. Obviously I can set hStdError to the handle of the log file, but what values should be used for hStdInput and hStdOutput?
I tried using NULL, which seems to work on Windows 8.1, but it doesn't work on Windows 7.
I also thought about creating a console window first, and then calling CreateProcess with handles to the new console window's buffers (and omitting the CREATE_NEW_CONSOLE flag). Unfortunately, the parent process is also a console application, and it seems a console application cannot create a second console window.
According to this MSDN Support article:
How to spawn console processes with redirected standard handles
If the parent process only wishes to redirect one or two standard handles, specifying GetStdHandle() for the specific handles causes the child to create the standard handle as it normally would without redirection. For example, if the parent process only needs to redirect the standard output and error of the child process, then the hStdInput member of the STARTUPINFO structure is filled as follows:
hStdInput = GetStdHandle(STD_INPUT_HANDLE);
According to the GetStdHandle() documentation:
STD_INPUT_HANDLE
(DWORD)-10
The standard input device. Initially, this is the console input buffer, CONIN$.
STD_OUTPUT_HANDLE
(DWORD)-11
The standard output device. Initially, this is the active console screen buffer, CONOUT$.
STD_ERROR_HANDLE
(DWORD)-12
The standard error device. Initially, this is the active console screen buffer, CONOUT$.
...
The standard handles of a process may be redirected by a call to SetStdHandle, in which case GetStdHandle returns the redirected handle. If the standard handles have been redirected, you can specify the CONIN$ value in a call to the CreateFile function to get a handle to a console's input buffer. Similarly, you can specify the CONOUT$ value to get a handle to a console's active screen buffer.
Attach/detach behavior
When attaching to a new console, standard handles are always replaced with console handles unless STARTF_USESTDHANDLES was specified during process creation.
If the existing value of the standard handle is NULL, or the existing value of the standard handle looks like a console pseudohandle, the handle is replaced with a console handle.
When a parent uses both CREATE_NEW_CONSOLE and STARTF_USESTDHANDLES to create a console process, standard handles will not be replaced unless the existing value of the standard handle is NULL or a console pseudohandle.
So, if the parent process's STDIN has NOT been redirected, GetStdHandle(STD_INPUT_HANDLE) will return either NULL or a pseudo-handle that refers to CONIN$. When that value is passed to the child process via STARTUPINFO, the child process will receive a console handle for the STDIN of whichever console it happens to be running in. On the other hand, if the parent process's STDIN has been redirected, GetStdHandle(STD_INPUT_HANDLE) will return an actual handle to a real file/pipe/etc, which the child will inherit and access.
The same applies to STDOUT and STDERR.
So, if you want to redirect the child's STDIN/OUT/ERR handles, you have to set hStdInput/Output/Error to your own handles. If you want the child to receive default handles, use GetStdHandle() and let CreateProcess() decide what kind of handles the child receives based on whether the parent is itself being redirected or not.
On Windows 7, at least, the documentation here (as quoted by the existing answers) is misleading. The recommended approach only works if the parent process does not have redirected input.
This is the actual behaviour, as observed on my machine:
When a process opens a handle to CONOUT$ (for example) the returned handle always has the same numeric value (on my machine, the handle for CONOUT$ is always 7) unless that handle already exists.
So if you are a console process, and you were not launched with redirected output, your standard output handle is 7. If you open another handle to CONOUT$, it will have a different value. If you close handle 7, and then open a handle to CONOUT$, you'll get 7 again.
When a console process is launched, a handle to CONOUT$ with the magic value of 7 is usually present in the child process (regardless of redirection). If you have used STARTF_USESTDHANDLES, then the child's standard output will go to the console if and only if you specify 7 as the standard output handle. If you specify a handle to CONOUT$ that has any other value, it won't work.
Sometimes when a console process is launched with standard output redirected, there is no handle to CONOUT$ present in the child process. In particular, this happens when cmd.exe launches a console process with standard output redirected. So far, I have been unable to figure out what combination of parameters to use with CreateProcess to make this happen.
The behaviour of CONIN$ is analogous; on my machine, the magic value for CONIN$ is 3. (I haven't investigated how standard error works.)
The upshot is that I do not believe it is safe to make use of this behaviour unless you have complete control over the way the parent process was launched, because unless the standard handles already point to the console there is no reliable way of obtaining a handle to the console with the correct magic value.
Instead, launch a proxy process with CREATE_NEW_CONSOLE and without STARTF_USESTDHANDLES. From that process, since you know how it was launched, you know the standard handles will have the correct magic values, so it is safe to specify them as the handles for a child process.
If i interpreted this documentation correctly, you should use GetStdHandle(STD_INPUT_HANDLE) and GetStdHandle(STD_OUTPUT_HANDLE) for the other two handles.
I'd like to create a tool that can either act as command line (display some console output based on input parameters), or display a window, based on input parameters.
I'm using MSV2012 with C++, and it seems you have to 'choose' between console and window app.
I know the net is filled with samples which use AllocConsole() and redirect std::out, but it doesn't make it feel like a command line application : calling the exe from the windows console will open a new window with the console output...
Is there a way to have it use the current console window instead of allocating a new one?
If not possible, I'll make 2 applications instead, but that's a pity..
Someone else may have a more authoritative answer, but I don't believe it's supported.
The usual workaround is to create a Windows app, but have a command-line wrapper that launches it from the CLI (and provides a channel for communicating with the original console).
It's not technically supported but I found a good solution by getting a snapshot for the current process, finding the parent process, attaching to it's console if it's a console app or creating one with AllocConsole, redirecting the output, getting the thread of the parent process if it's cmd.exe and suspending it, resuming it just before I exit my app
So I start an ordinary console program and then create another process within it. Next the child process tries to write something onto console that is owned by parent process.
Is it possible to put a hook on this console so when child process tries to write some text I could do search and replace on this text and put it changed onto the console.
(I know it is possible with pipes, but here I ask specifically of doing it at the console level, because some programs behave differently if they see they are attached to pipes instead of console.)
Has SetWindowsHookEx something to do with my question ?
Just to avoid confusion, windows messages aren't involved with this so hooking is entirely the wrong concept.
If you want to change the child processes data written to STDOUT, you'll need to create your own pipes that you pass to the process when creating it. This allows you to read the data from it, change as you require then print to STDOUT yourself. There is no way to intercept data written direct to the console.
So you want to install a winproc hook on the console? Sure, you can do it, first you have to get the HWND (read here) of the console window then you can call your SetWindowsHookEx() and hook it. Do note that in your hook procedure , calling defwinproc will call the console's origional winproc, so if you don't want to modify the entire behavior of the console your in the clear.