I am trying to run a process using CreateProcess(...) and run it independently in a seperate console window.
I can achieve this using the system("...") function, but I prefer CreateProcess since it gives me the possibility to specify environment and working directory, get a handle to the process, as well as piping stdin/out when I need to.
All I find on the internet is the inverse problem, which is people having additional console windows and wanting to get rid of them! It appears it was the normal behavior in earlier versions of Windows to open and show a new console window(s)?
Right now, I am unable to get an additional window, even if I run "cmd.exe /c ..."
I tried using the STARTF_USESHOWWINDOW flag with no luck.
Has anyone had this problem?
PS.: GUI windows are shown eg. notepad.exe will appear normally.
This is my code (in essence)
PROCESS_INFORMATION processInfo;
STARTUPINFOA startupInfo;
ZeroMemory(&startupInfo,sizeof(startupInfo));
startupInfo.dwFlags |= CREATE_NEW_CONSOLE;
startupInfo.dwFlags |= DETACHED_PROCESS;
ok&=CreateProcessA( NULL,
const_cast<char*>(comand.c_str()), // safe for CreateProcessA
NULL, NULL, TRUE, NULL, NULL, NULL,
&startupInfo, &processInfo);
I'm trying to run C:/Windows/system32/cmd.exe /c help
The program runs and I can read the output from a pipe. Still no window.
MSDN is really your best friend while working with Win32 API. Now, the relevant creation flags for you are the following:
(no flags set) — the child process (the one being started with CreateProcess()) will share the console with the parent process (the process which called CreateProcess()).
CREATE_NEW_CONSOLE — the child process will receive a new console, open in a new window. As the MSDN explicitly says, this flag MUST NOT be used together with DETACHED_PROCESS! And that's exactly the flag that you want to use.
CREATE_NO_WINDOW — the child process will receive a new console, but without any window for it. That's quite a surprising flag, so I will restate it again: the child process will have a console, to which you can write your output, from which you can try to read input, etc; this console is different from the parent process's console; this console is invisible, it has no visible window, but it exists. It's useful for, say, silently running child processes in background. Note that this flag has no effect when used with CREATE_NEW_CONSOLE or DETACHED_PROCESS — those flags override this one. Also keep in mind that this flag is ignored when you launch a GUI application: it won't receive an invisible console.
DETACHED_PROCESS — the child process will not receive any console whatsoever. You must not use this flag together with CREATE_NEW_CONSOLE.
And now a bit more about correct invocation of CreateProcess(). First of all, you should use CreateProcessW(). I am particularly tired of apps that can't access files in a directory named 日本語αβηλ.
Second, even if you use the ANSI version, specify CREATE_UNICODE_ENVIRONMENT flag if you pass NULL for the environment. If you don't do this, PATH may end up broken in the child process, and this bug is extremely annoying to trace down.
Third, don't const_cast<char*>command.c_str(). Just call strdup()/wcsdup() on it, and then free() after the CreateProcess() call returned. Or if you really insists on modifying command in place, pass &command[0] as the parameter.
Fourth, don't forget to set the size of your STARTUPINFO structure: startupInfo.cb = sizeof(startupInfo). Modern Windows (XP and 7, at least) actually allow you to leave this field to be a zero without any harmful consequences, but it's a bit of a sloppy programming to rely on this.
Oh, and while we are here: you mentioned that you use CreateProcess() because, among other things, it allows you to specify environment for the child explicitly. Well, there is a slight gotcha about lpEnvironment parameter which is documented, but quite easily overlooked. When you specify NULL, the child inherits the parent's environment. When you specify something non-NULL, the parent's environment IS NOT ADDED to it. If you want to add to the parent's environment, you'd have to use GetEnvironmentStrings() to obtain it and then explicitly tweak it.
Pass CREATE_NEW_CONSOLE in the dwCreationFlags when calling CreateProcess. I have not tested, but I suspect this forces the creation of a console window (perhaps even for non-console processes?) You could also use DETACHED_PROCESS instead, which merely detaches from the parent console.
Related
I am trying to run a program from cmd, but not as a child of the prompt. I have tried calling the program directly: program, but this starts it as a child process. I have tried start "" program, but this also starts it as a child process. Is this possible? I don't want the program to close when the prompt is closed.
Edit: This is not a duplicate question - start doesn't work in this case. I don't know enough to explain better, but some things to note:
The program in question doesn't open a new window
The path to the program contains spaces, so requires inverted commas. However, the inverted commas seem to suggest to start that the argument is intended to be the name of the new command window.
I need to pass switches to the program, which makes things a bit more complicated
I have a series of running processes I need to stop as gracefully as I can. I am finding that I can use CloseMainWindow() with any foreground process, but that none of the ones running in the system tray (i.e. background processes) end (just returning 'false'). That on it's own isn't an issue since I can force-quite those (e.g. Stop-Process) if needed.
However, how can I determine true/false of CloseMainWindow() on each process without actually closing the ones that return true? I could not find anything property that gave the foreground/background status of a process.
I think I figured out how to do this, though I am not certain it's the most reliable way.
I found that querying the MainWindowHandle property against a process return 0 only if it was running without a window in the background. Otherwise it would return some value > 0. If there's a better way, feel free to educate me.
My question is related to "Turn off buffering in pipe" albeit concerning Windows rather than Unix.
I'm writing a Make clone and to stop parallel processes from thrashing each others' console output I've redirected the output to pipes (as described in here) on which I can do any filtering I want. Unfortunately long-running processes now buffer up their output rather than sending it in real-time as they would on a console.
From peeking at the MSVCRT sources it seems the root cause is that GetFileType() is used to check whether the standard I/O handles are attached to a console, which then sets an internal flag and ends up disabling buffering.
Apparently a separate array of inheritable file handles and flags can also be passed on through the undocumented lpReserved2 member of the STARTUPINFO structured when creating the process. About the only working solution I've figured out is to use this list and just lie about the device type when setting the flags for stdout/stderr.
Now then... Is there any sane way of solving this problem?
There is not. Yes, GetFileType() tells it that stdout is no longer a char device, _isatty() return false so the CRT switches the output stream to buffered mode. Important to get reasonable throughput. Flushing output one character at a time is only acceptable when a human is looking at them.
You would have to relink the programs you are trying to redirect with a customized version of the CRT. I don't doubt that if that was possible, you wouldn't be messing with this in the first place. Patching GetFileType() is another un-sane solution.
I noticed that when a process starts for the first time, it statically reads some system parameter info only once and keeps it until terminated
which means,
that if there is some modification to the system parameters already read by the process, they wouldn'y reflect until the process is restarted.
e.g. Launch Notepad and type ';' key on the keyboard. Now change the input language from the langauge toolbar to Spanish. Now again hit the key ';'. Though the Input langauge has been changed to Spanish, the keys are still English (as seen by pressing ';' key).
Ideally on pressing ';' afer the input language is changed to Spanish, we should have noticed 'ñ'.
When we restart Notepad, we notice that ';' results in 'ñ' which means that the Notepad process needed to be restarted to take effect.
Is there some way where the process is not needed to be restarted to reflect the change in the Input method?
Thanks
If a process cares to, it can listen for notifications of changes to various system-wide settings. The wm_SettingChange message comes to mind.
It's a fool's errand to try to make some other process honor setting changes if it hasn't been written to do so. If a program isn't already listening for change notifications and acting upon them, you can't make it act differently.
Notepad probably isn't a good example; it's a pretty simple program, so it doesn't necessarily cover all the details that a good Windows program should.
The "answer" you gave, to refine your question, talks about changing the system's default input language with SystemParametersInfo. When you call that function, it will broadcast the wm_SettingChange message. To be notified of the change, other programs need to listen for that message; do that the same way you listen for any other window messages in your programming environment.
When you receive that message, the wParam parameter will be either spi_GetDefaultInputLang or spi_SetDefaultInputLang; I don't know which. That's you cue to call SystemParametersInfo to find out the new value of the setting. Based on what I've just read in "Languages, Locales, and Keyboard Layouts", you should call ActivateKeyboardLayout using the HKL value you get from SystemParametersInfo.
The process that changes the default input language cannot force other processes to use it. Until they choose for themselves to change their input languages, they will continue using whatever was the language when they started running. That's the distinction between the default setting and the current setting.
I need to create a new process with redirected standard error stream to some file. The code from which child process is being created has no console available, so there are cases when GetStdHandle(any) will return 0. Child process will try to duplicate all of its standard IO handles for some reason (source code for child process is unavailable) so all of it's handles should be valid.
So I need to run that process in the same manner as it's can be ran from the console with:
someproc <nul >nul 2>err
I see some ways for this:
1. Create two pair of pipes. This is possibly good solution, but it will be too complex for me.
2. Open "nul" file with CreateFile("nul", ...) function call. No file is being created by this call, but this looks weird too me.
3. Use INVALID_HANDLE_VALUE. This works too, but I think there can be different problems with another child processes.
I believe there are better ways.
As originally phrased, you have already answered your own question. To open a "nul" file, you simply specify "nul" when you call CreateFile. It only looks weird because hardly anyone ever uses that file name. (I don't see it used nearly as often as I see /dev/null.) It's perfectly valid, though.
But if you've found that Invalid_Handle_Value works, too, then go ahead and use that instead. It's certainly easiest. I wouldn't have expected it to work, initially, since I wouldn't expect it to be duplicable.
Yes, "nul" is doing what you think. If you move to unix, it will be "/dev/null". The funky name is a holdover from DOS days, along with "prn" and "com1", etc.
Using INVALID_HANDLE_VALUE with DuplicateHandle is improper: the documentation states that you need PROCESS_DUP_HANDLE access right on the handle. You don't have that righton INVALID_HANDLE_VALUE. Device NUL (symbolic link to /device/null) will work fine, though.