I am trying to tidy up a process that uses multiple system calls from inside a ruby script executed using rubyw.exe (1.8.7).
As far as I can understand the main reason for rubyw.exe is that it doesn't pop up a command prompt to distract the user. However it appears that the system calls from within that process still do generate these popups which is very distracting for the users of this process script.
Does anyone know how to do this?
There are lots of questions similar to this on SO but none which quite answers this, if I was using python this questions/answer would help (http://code.activestate.com/lists/python-list/46042/) but so far my searching hasn't found a way to accomplish this with ruby.
UPDATE: There is this thread here Hiding curl Window on Windows which is close but the only working solution there doesn't also allow you to get the standard output.
I ended up going with the win32-open3 gem. Because fork isn't implemented on windows systems you can't use the built in open3 and you'll need to do a
gem install win32-open3
However this comes with flags that you can pass to the call method, in particular
There are a couple of differences in the Windows version for open3
(which
also apply to Open4.popen4) - the mode flag and the show flag. For the
mode, you can specify either 't' (text, the default) or 'b' (binary) as a
second argument. For the show flag, you can specify either true or false,
which will show the console window, or not, depending on the value you
pass. The default is false.
Users of this particular script are no longer bombarded with 15 cmd windows that constantly steal focus, so .... win?
Related
Is it's possible to detect inside app from where it was run? From cmd/bash or from GUI? Assume that we are working in graphical mode, not in pure console.
Not really, but sort of. Short answer: better not to try, get the user to tell you via an argument, which you can pre-fill in a shortcut.
Long answer:
In both cases, the program is launched in a similar way: the shell application (whether cmd/bash or Windows explorer/whatever gui launcher linux has) call CreateProcess or ShellExecute on Windows or fork+exec on Linux and the way the user executed it gets lost.
However, the process does have a parent ID which might be useful.... but it isn't reliable either for a few reasons: telling if it is a gui or command line shell isn't easy (best you can do is look at the image name) and the parent might terminate as soon as you launch, so there'd be no parent! (Linux gui apps often fork themselves to detach from the terminal. Of course, if you do this you'd probably know, but if you use a library it might happen without you realizing it.)
Well, the fact that I'm going off on parenthetical asides after every sentence shows how unreliable and complicate that is. If you want to try though, looking at your parent process ID before doing any fork/detaching might be helpful.
BTW looking for a parent console isn't very helpful: a Windows GUI subsystem program won't attach to the parent console even if one exists and a Linux GUI program may attach to the controlling tty of the X window manager.
What I'd actually recommend though is passing an argument to your function to tell it how it got started. When you create the GUI shortcut, make it automatically pass the "started by gui" argument to you. Then you can check args for it and react accordingly.
It still isn't perfect, but it is fairly easy to implement and probably good enough - gui launchers would probably use a shortcut anyway and you can pass arguments through them, so the user doesn't need to know about how it is implemented.
Or you could install two programs, one which is convenient from the command line and one which is optimized for the gui environment.
But I think that's the best you can do.
I have a GUI Ruby tool that needs to spawn a child command-line process, for example ping. If i do this on Windows, the console window will appear and dissapear for console process, that is very annoying. Is it possible to start a process from GUI Ruby script with no console window visible? If i use backtick operator or Kernel#system, the console window will appear, see example below:
require 'Tk'
require 'thread'
Thread.new { `ping 8.8.8.8` }
TkRoot.new.mainloop
The issue is that every executable on Windows is defined to be either a GUI executable or a Console executable (well, there's more detail than that but it doesn't matter here) at the time it is built. The executable that's running your Ruby script is a GUI executable (it also happens to use Tk to actually build a GUI, even if only a very simple one in your screenshot) and the ping executable is a Console executable. If a GUI executable starts a Console executable, a console is automatically created to run the executable in; you can't change this.
Of course, the picture is more complex than that. That's because a console application can actually work with the GUI (it just needs to do the right API calls) and you can use a whole catalogue of tricks to cause the console window to stay out of the way (such as starting ping through an appropriately-configured shortcut file) but such things are rather awkward. The easiest way is to have the console window be there the whole time by making Ruby itself be a console app (through naming your script with the .rb suffix, not .rbw). Yes, it doesn't really get rid of the problem, but it stops any annoying flashing.
If you were using ping as the purpose of your app (i.e., to find out if services were up) then I'd as whether it is possible/advisable to switch to writing the checking code directly in Ruby by connecting to the service instead of pinging it, as ping just measures whether the target OS kernel is alive, and not the service executable. This is a fine distinction, but I've seen machines get into a state where no executables were running but the machine was still responding to pings; this was very strange and can totally break your mental abstractions but can happen. But since you're only using ping as an example, I think you can just focus on the (rather problematic) console handling. Still, if you can do it without running a subprocess then definitely choose that method (on Windows; if you were on any sort of Unix you wouldn't have this problem at all).
It is indeed possible to spawn processes with Ruby. Here is a couple of ways to do it. I am not sure what you mean with
the console window will appear and dissapear for console process
but I think the best way for you to do it is to simply grab out and err and show it to your user in your own window. If you want the native windows console to appear wou probably need to something fancy with windows scripting.
One way to keep a spawned console alive is to have it run a batch file with a PAUSE command at the end:
rungping.bat:
ping %1
pause
exit
In your ruby file:
Thread.new {`start runping.bat 8.8.8.8`}
I want to be able to detect whether a given exe was shellex'd programmatically or if it was entered and executed interactively in, say, CMD.EXE.
Is there anything about the way an exe is launched that indicates the mechanism that was used to launch it?
Context: Windows XP, Visual Studio 6 languages.
There might be an easier way, but the only way I can think of is to check the parent process name, which involves a few steps:
Get the ID of the parent process.
Get the handle of the process, using the ID.
Use GetModuleFileNameEx with the handle found (and NULL as the module) to get the executable's name.
Check if the executable's name is cmd.exe or whatever.
Bear in mind that the parent process might already be gone when (or while) you do this check.
Edit:
If your program is a console application, you can also check the console it's running in. If it was run from cmd, it will usually use the same console. So, you can use GetConsoleTitle, for instance, and see if it's "Command Prompt". This might not work on localized or different versions of Windows, but it's easy if you have limitated cases. You can also use GetConsoleWindow and GetWindowThreadProcessId instead of steps 1 and 2.
You can differ between say CMD and Explorer by inspecting the parent process, but you can't tell if it happened due to user action or not. Also AFAIK all ways to launch a process result in the same NtCreateProcess/PspCreateProcess call, so you can't tell which API was used either.
this is not yet another "I need a console in my GUI app" that has been discussed quite frequently. My situation differs from that.
I have a Windows GUI application, that is run from a command line. Now if you pass wrong parameters to this application, I do not want a popup to appear stating the possible switches, but I want that printed into the console that spawned my process.
I got that far that I can print into the console (call to AttachConsole(...) for parent process) but the problem is my application is not "blocking". As soon as I start it, the command prompt returns, and all output is written into this window (see attached image for illustration).
I played around a bit, created a console app, ran it, and see there, it "blocks", the prompt only re-appears after the app has terminated. Switching my GUI app to /SUBSYSTEM:Console causes strange errors (MSVCRTD.lib(crtexe.obj) : error LNK2019: nonresolved external Symbol "_main" in function "___tmainCRTStartup".)
I have seen the pipe approach with an ".exe" and a ".com" file approach from MSDEV but I find it horrible. Is there a way to solve this prettier?
This is not behaviour that you can change by modifying your application (aside from re-labelling it as already discussed). The command interpreter looks at the subsystem that an executable is labelled with, and decides whether to wait for the application to terminate accordingly. If the executable is labelled as having a GUI, then the command interpreter doesn't wait for it to terminate.
In some command interpreters this is configurable. In JP Software's TCC/LE, for example, one can configure the command interpreter to always wait for applications to terminate, even GUI ones. In Microsoft's CMD, this is not configurable behaviour, however. The Microsoft answer is to use the START command with the /WAIT option.
Once again: This is not the behaviour of your application. There is, apart from relabelling as a TUI program, no programmatic way involving your code to change this.
Maybe write a console-based wrapper app that checks the parameters, prints the error message on bad parameters, and calls/starts up the actual program when the parameters are correct?
I'm working on a GUI for Windows XP. Everything works great, except when I run an external command through backticks, %x(), IO.popen, etc, I get a DOS window that pops up for a split second. I know this doesn't happen when I've developed on OS X and Linux. Any ideas on how to get rid of it? (Or at least hide it?)
I'm using rubyw 1.8.6 (the "GUI version" of Ruby for Windows) and GTK2 for the interface.
You can use the Win32API module, and call the windows api CreateProcess Function. It ain't pretty.
As mentioned in a comment, I never found a solution to this. In this particular circumstance, the information I needed was actually already stored on the filesystem (so I just read it in as a file). This wasn't immediately obvious before, and isn't likely to come up in all circumstances.
If anyone finds a "true" solution, I would be interested in hearing about it.