How to control cmd-window in win32 from Ada-code?
Question
I've made a simple Lua-execution in Ada, it cooly run everything I need via Lua.Load_Buffer("os.execute('wxlua.exe wx.lua')")
but I don't need win32 cmd.exe-window, which is default opens on program's start-up. Is there any way to control this event directly from Ada?
P.S. os.execute() sends commands directly to Windows, not via cmd.exe.
Solution
To help see what's going on, try creating a desktop shortcut that executes that command.
If double-clicking on it also brings up the win32 cmd.exe window, then that means they compiled wxlua.exe to be a windows console app. You can try reading their docs or poking around in their exe directory to see if there's a Win32 version instead. If that doesn't do it for you, your best remaining option I know of is to call Win32's CreateProcess with the CREATE_NO_WINDOW or DETACHED_PROCESS flag set instead of using os.execute
.
If the shortcut doesn't bring up a console window, that means os.execute
is doing it to you. In that case, you'll have to go directly to the CreateProcess solution mentioned above.
Gnat should come with the Win32 bindings you need to call CreateProcess. If you'd like a cleaner interface to that routine, I have some thicker bindings I created to some of the Win32 calls, including that one and some other calls associated with creating Win32 services. I released them to the Public Domain (or tried to...) They are available in the source distribution of my old SETI@Home Service, and I believe they are somewhere in the examples directory of AWS (at least it used to be before ACT took it over).
OTHER TIPS
Standard Lua os.execute
calls the standard C function system()
. The C standard only requires that system()
do something platform dependent, and specifically avoids saying what that might be. On Unix-like platforms, system()
usually invokes the shell /bin/sh
. On Windows it usually invokes cmd.exe
.
Of course, its exact implementation could depend on exactly which toolchain you are using. You haven't said where you got your Lua (or for that matter, who's Ada compiler you have). One likely and recommended source is Lua for Windows, which is linked to the C runtime library from VC8, aka VS2005. Quoting from VS2005's documentation:
int system(const char *command);
.... The system function passes command to the command interpreter, which executes the string as an operating-system command.
system
refers to theCOMSPEC
andPATH
environment variables that locate the command-interpreter file (the file namedCMD.EXE
in Windows NT and later). Ifcommand
isNULL
, the function simply checks to see whether the command interpreter exists.
Since os.execute
calls system
which invokes cmd.exe
, you will get the console window. The way to avoid that is to not use os.execute
.
If the program being executed is compiled for Windows Console Mode, then you will get a console window, regardless. However, wxlua.exe
is almost certainly not compiled as a console application since it is intended to host GUI applications written in Lua based on the wxWidgets library.
Edit:
Naturally, if your lua.exe is built in a way that replaces either the implementation of os.execute
or the standard library routine system()
with a different implementation then you might see different results.
To demonstrate that standard Lua's os.execute()
eventually invokes cmd.exe
, try the following:
C:\Documents and Settings\Ross>lua -e "os.execute[[pause]]" Press any key to continue . . . C:\Documents and Settings\Ross>wlua -e "os.execute[[pause]]" C:\Documents and Settings\Ross>
This invokes a simple Lua script from the standard Lua interpreter, first the usual one that is a console application, and second from the variation supplied with Lua for Windows who's only difference is that it is linked to be a Windows GUI application.
Both cause the "Press any key" message to appear. The first in the same console window where I invoked Lua, and the second in a separate console.
Before hitting a key, I used PsList
from Sysinternals in a separate console to show the process tree, with the command pslist -t
. I've excerpted out only the relevant bits below:
C:\Documents and Settings\Ross>pslist -t pslist v1.29 - Sysinternals PsList Copyright (C) 2000-2009 Mark Russinovich Sysinternals Process information for LAMPWORK: Name Pid Pri Thd Hnd VM WS Priv Idle 0 0 2 0 0 16 0 System 4 8 79 1208 1884 220 0 ... explorer 3592 8 17 1263 115968 33964 25816 ... cmd 4300 8 1 96 35032 4448 2260 PsList 4688 13 2 109 29556 2776 1248 cmd 5208 8 1 33 30340 2704 1984 lua 5592 8 1 17 8528 1564 400 cmd 5680 8 1 30 30144 2428 1956
Notice that the instance of CMD that invoked Lua has a CMD as a child.
Repeating the experiment with wlua -e "os.execute[[pause]]"
and pslist -t again:
C:\Documents and Settings\Ross>pslist -t .... Name Pid Pri Thd Hnd VM WS Priv Idle 0 0 2 0 0 16 0 ... explorer 3592 8 16 1251 115712 33956 25752 ... cmd 4300 8 1 96 35032 4448 2260 PsList 4888 13 2 109 29556 2780 1248 procexp 4800 13 7 328 108492 33232 29464 cmd 5208 8 1 32 30340 2704 1984 wlua 3272 8 1 15 8536 1576 400 cmd 5104 8 1 30 30144 2440 1956
Again, wlua
has a CMD as a child.
Using ProcessExplorer, also from Sysinternals, I can see the command line of the child CMD
process. It is CMD.EXE /C pause
. In effect, system()
prepends CMD /C
to its argument and passes the result to spawn()
for execution in a child process.