Create process in another WSL window from C - c

I'm working on a C program that invokes some other programs from the same directory. The idea is to call fork, and make the child processes execute the desired programs, each one on a new terminal window, I'm using WSL from windows and I can't seem to make it work.
On a regular Linux machine, I've seen something similar to the following working, which is just calling a terminal emulator which creates a new window:
execlp("/usr/bin/x-terminal-emulator", "/usr/bin/x-terminal-emulator", "-e",
"./programname.exe", NULL);
But in WSL isn't possible to just execute a command on a new window like that, instead, executing this command directly in a WSL terminal does spawn a new window and allows to execute a given program on it:
cmd.exe /c start cmd.exe /c wsl.exe ls
Using ls in the line above is just illustrative. Trying to use execlp to run cmd.exe and passing the rest of the command as arguments doesn't work, it just runs cmd in the same terminal used to run the program. Is there any way to achieve this?, preferably using C. I'm aware that just using a bash script to execute those programs on separated windows using the command from above would work, I'm just wondering if there's any solution for a use case like this one.

Related

Issuing a command in the shell a program is run from

I have a program which hacks around in the user's shell configuration file (by placing a . (execute) command for an auto-generated alias file) and I'm having trouble figuring out how to run commands in the parent shell, i.e. without forking into a new shell.
I only need to run a command to execute the alias file so that the "program" can be used without logging in and out. Surely there must be another way to interact with the shell beside forking.
N.B.: When I say "forking" I mean both using system() and execl() - as I said, I want to send the command to the shell hosting the program, not a new instance of it.
After some thinking about your use case, I suppose what you want to do, that is, to signal your parent shell to reload the configuration, is impossible, but what you can do here is to reverse the control.
What I mean is, don't think how to make your parent shell do something, but let it do it for you. If you have a program that fixes shell configuration, make a shell wrapper for it:
/path/to/program
. ~/.bashrc # or any other way to reload the shell config
and call your program using . wrapper.sh to make sure it will be executed in the context of the current shell. In this way the program will make changes to the configuration but will not bother with interacting with its parent, and the calling shell will just reload itself after the program finishes.

Why GUI application blocks a batch file?

There are many references on Internet claiming that one of differences between a GUI and a console application is that running the GUI application from a batch file does not block its execution, while running the console application does block it.
Few of many references, these are particularly from SO/SE:
How can I get an MFC application to block from the command line?
How to wait for a process to terminate to execute another process in batch file
How do you wait for an exe to complete in batch file?
Run a program in a batch script and wait for it to finish before continuing
Moreover, I myself remember this is/was true.
Yet it does not seem to work this way.
I've tested this on a simple batch file like:
echo Pre
notepad
echo Post
The Post is not printed until I close notepad. Why, when a notepad is clearly a GUI application?
I've tested this on Windows 8, 7, and XP just to rule out a possibility that the behavior has changed in recent versions of Windows. I've tried to disable command extensions as one of possible culprits too.
It has to do with how the application that you launch runs and terminates. Some programs launch another process and then terminate, others continue to run. Calc.exe and Notepad.exe simply run until you close them. Write.exe and any program that launches as a result of a file association (e.g., bitmap, wave file, control panel applet, etc.), actually launch another program and then the process that launched them terminates returning control back to the batch file so it can execute the next line.
Here are some examples:
#echo off
echo Starting Calc.exe
calc.exe
echo Calc was closed by the user
echo Starting Notepad.exe
Notepad.exe
echo Notepad was closed by the user
echo Starting WordPad.exe
write.exe
echo Write launched WordPad and then terminated allowing the batchfile to continue
echo Starting Services.msc
services.msc
echo Windows launched MMC, opened services.msc, then returned control to the batchfile
echo Launching WMP via Chord.wav
c:\windows\media\chord.wav
echo Windows launched WMP, opened Chord.wav, then returned control to the batchfile
The CMD process knows Calc and Notepad are still running because it spawned them itself. The CMD process does not know that the others are still running because the intermediate process terminated.
To observe this, open Process Explorer and view the processes displayed in the hierarchical tree. Calc.exe and Notepad.exe both remain as child processes of the CMD process that ran the batchfile. Write.exe and MMC.exe (services.msc) both become top-level processes, no longer children to the CMD process. WMPlayer.exe remains a child process to svchost.exe, which is how Windows launched it. The CMD process doesn't know they are still running because it didn't launch them, some other Windows process did. So execution continues...
One more example of this is how MSPaint.exe functions. If you run it by using the Windows built-in file association for BMPs, then Windows launches MSPaint.exe and control is immediately returned to the batchfile. However, if you pass the BMP to MSPaint.exe, then the batchfile waits for you to close MSPaint before continuing. (I'm on a dev machine with no BMPs, so create a simple one called C:\MyBitmap.bmp.)
#echo off
C:\MyBitmap.bmp
calc.exe
mspaint.exe C:\MyBitmap.bmp
notepad.exe
Calc.exe will open immediately, Notepad.exe will not open until you close the second instance of MSPaint.exe.
I know you didn't ask about launching Windows processes via their file association, but it just demonstrates how the owning process can change. If the CMD process owns the launched process, it should wait until it terminates to continue execution. If the spawned process hands control off to another process, then the CMD process doesn't know about the grandchild process and it continues on with its execution.
Because it waits for return code.You can use start command to create a separate subprocess:
#echo pre
#start "notepad" notepad
#echo post
I've used Windows since NT 3.1, and I too would have said "cmd.exe does not wait for GUI programs to terminate" when you simply type the name of the program (as opposed to using the START command). Though memory grows dim, I believe it originally worked this way. But today, my statement is true interactively, false for "batch" files. Having been thus reminded, I vaguely think it was intentionally changed as some point, since the naïve batch-writer expects sequential execution, but I can't be sure and I don't know when.
I think the answer lies in this question Difference between Windows and Console application.
I quote from two answers.
Konrad Rudolph answered:
The sole difference is that a console application always spawns a console if it isn't started from one (or the console is actively suppressed on startup). A windows application, on the other hand, does not spawn a console. It can still attach to an existant console or create a new one using AllocConsole.
This makes Windows applications better suited for GUI applications or background applications because you usually don't want to have a terminal window created for those.
oefe answered:
Console and Windows applications behave differently when called interactively from the command prompt:
When you start a console application, the command prompt doesn't return until the console application exits. When you start a windows application, the command returns immediately.
This is not true for batch files; they will always wait until the application exits.
The difference in this bahviour between cmd and batch made you think that it worked before.

How to launch gvim.exe from cscope-win32 when run from cmd.exe?

For years now my Windows C tagging/scoping solution has almost worked. I can build the filelist, build the tags (via Exuberant Ctags) for vim/gvim navigation, build cscope.out, and tag around within gvim.exe windows I launch by clicking on C source files.
The final piece that eludes me is that I can't seem to get cscope in cmd.exe to launch my editor when I select an item. I made sure gvim.exe is in my Path environment variable. I made sure the CSCOPE_EDITOR environment variable is set (more on that below). But when I select a line item from within cscope the editor is not launched. Instead I get one of the two following failures:
If CSCOPE_EDITOR is either gvim.exe -f or "gvim.exe -f" then I see that printed at the top of the cmd.exe window followed by the line offset and the filename (e.g. "gvim.exe -f +72 myfile.c") and then it quickly returns to cscope without the editor ever popping.
If CSCOPE_EDITOR is gvim.exe (without the -f option) then a gvim.exe process is kicked off (I see it in Windows Task Manager under Processes) but it never comes to the foreground as an application. Furthermore, the cscope window in cmd.exe goes blank and is unresponsive until I manually kill the gvim.exe process that was spawned.
For reference:
cscope -V returns "cscope: version 15.8a" and was downloaded from this site: http://code.google.com/p/cscope-win32/
My version of gvim.exe is 7.3 which the latest available from http://www.vim.org/
Also, I have tagged this post with "C" because, while this is not a C language question, cscope and ctags are primarily used for C programming and thus I think the C tag is relevant. (Thought I'd point that out before someone comes along and removes the tag and says this isn't a C question, since C programmers are the most likely people to have the answer.)
With help from #mattn and #mMontu and a lot of trial-and-error and an ugly but simple hack I finally have this working. Here are the problems I encountered:
cscope-win32 does not handle spaces in the EDITOR or CSCOPE_EDITOR environment variables. I tried every space-escape trick I could think of (single-quotes, double-quotes, backslash escapes) and nothing worked.
When gvim.exe is successfully launched by cscope-win32, if that gvim.exe tries to add the same cscope.out database (via cs add cscope.out) the add command hangs. If the add is part of a vimrc file then the editor will hang during opening (with the gvim.exe and cscope.exe processes starting but the application window never appearing). If the add is done after the editor window opens then the window will hang. This appears related to multiple cscope-win32 processes being attempted in the same process tree, but I have no actual proof of that.
Here's my solution to the problem. Like I said, it is an ugly but simple hack.
Create a wrapper batch file. I named mine gvim_cscope.bat. Make sure it is in a directory that exists in your PATH environment variable. You can verify this in a cmd.exe shell by calling "where gvim_cscope.bat".
Edit the batch file and add your editor command but precede it with the windows start command. For example, my batch file contains the following:
start gvim.exe %*
Create/Update your CSCOPE_EDITOR environment variable to be "gvim_cscope.bat". In case you've never modified a Windows environment variable before, you can get to them (on Windows 7 anyway) via Start -> right-click Computer -> Properties -> Advanced System Settings -> Environment Variables.
That's all I needed to get things working. Open a new cmd.exe window (so the updated environment variable is pulled in) and open cscope.exe and everything works. I am able to pop multiple gvim.exe windows from within cscope.exe, each with its own connection to the cscope.out database. The first problem is avoided by using the wrapper batch file (no more spaces in the command) and the second problem is avoided by using the windows start command so that gvim.exe is started as a separate process.
Thanks for the help #mattn and #mMontu. So nice to have things working right!

Control cmd prompt using C

I'm trying to write a C program to control the windows cmd prompt. For example, opening the cmd prompt, go to a specific directory (ex: C:/Program Files/...), and then run an exe in that folder.
Can this be done with C programming? If so, how? So far, I am only aware of system("cmd.exe") to open up the cmd prompt. How would I further interact with cmd prompt?
Thanks.
This wouldn't be very portable. system calls are often frowned upon, but just to answer your question, the system function does work with the commands you're aiming to use.
For example:
system("notepad.exe my_file.txt");
system("del my_file.txt");
system("pause");
This will open up a file called my_file.txt in notepad, delete it and pause the program.
Again, this is not portable. It's specific to Windows Operating systems.
In fact, I don't even think it's guaranteed to work on all releases of Windows.
(Don't quote me on that.)
On topic: You could start cmd via "CreateProcess" and send key input via window messages ("SendMessage").
I think you should rethink how you want things to be done. The command prompt is not a kind of API base to do things on windows. It's a tool to do things and get information without writing your own program. If you wirte an own program, you should directly use the WinAPI.
To get started you can google "winapi [whatever you want to do]". In your example "winapi start executable" and you will find functions like "CreateProcess" and "ShellExecute".
Perhaps there is a misunderstanding here (if so, I apologize), but the standard way to "further interact with cmd prompt" is via command-line commands, and the standard way "to write a program to control the windows cmd prompt" is via a Batch file. For example, the following Batch file open the cmd prompt (when it is executed via a double click in the Explorer), go to a specific directory (C:/Program Files/) and run an exe in that folder:
#echo off
cd "C:/Program Files/"
nameOfTheProgram.exe

How do I stop the Console Window from appearing when making system calls?

I am using C and GTK+ for a gui project. For my project I have to make a lot systems calls. e.g system("copy myfile urfile"); or system("mp3player -embed filename") etc. and whenever my program calls the system an annoying console window appears and stays visible until the command is completely carried out. How do I hide that console window? Thanks.
NOTE: For my project I can use GTK+ , the C Standard Library , GLib, WinApi (not recommended) and system calls.
SCREENSHOT:
Using system() to create a new process does this by first starting a new command interpreter, which then in turn executes the command passed to system().
The command interpreter opens the console window.
Thus to avoid opening such a console windows you need to avoid starting the command interpreter. To do the latter try a function out of the spawn family (http://msdn.microsoft.com/en-us/library/20y988d2.aspx) or use the win32 api function CreateProcess() (http://msdn.microsoft.com/en-us/library/windows/desktop/ms682425) to directly start your application.
A side effect on doing so might be, that your application starts faster and also uses less system resourses.
In fact the above mentioned solutions will not work for system calls which explicitly need a command interpreter as in one of your examples (copy src dst).
Use the GLib processes spawning functions instead of platform-specific functions. For file copy you can use g_file_copy from GIO (shipped with GTK) instead of calling the cp or copy command. This makes your code more portable too.

Resources