How to detect from console or GUI app was run? - user-interface

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.

Related

Golang detect if in focus or minimized

How would I go about detecting if my go CLI program is in focus or minimized?
Current program based off https://github.com/jroimartin/gocui
I require the functionality as it is a chat program and I would like to send OS notifications but only when the program is not in focus or is minimized.
Your help/direction is much appreciated as of right now unsure where to start.
This is not possible from the library itself. A command line program does now have a focus, but the terminal program it is running in.
To implement that (if possible at all) would be dependent on os, window manager etc.
To refine the answer provided by #mbuechmann, I suggest the OP not to try to resort to APIs etc.
The reasoning is simple.
"Contemporary" users are used to running programs in terminal emulators which are typically presented as separate windows, and so the users naturally think of these programs as not really different from GUI apps.
But the reality is different: a terminal emulator—whether graphical or not (for instance, so-called "virtual consoles" provided by the Linux kernel running on an x86/amd64 hardware are terminal emulators as well)—really emulates a typical work session on a real hardware terminal, and there, a program would work in foreground solely, and the only means of "switching" to another program was using the shell's job control (those jobs, bg and fg commands).
In other words, the whole concept of a program working in a terminal has an inbuilt assumption that the terminal is always "foreground"—since at the time the concept was developed, a terminal was a physical device.
Now please also consider that "terminal emulation" may be more pervasive on a contemporary system than you might think: screen and tmux on a Unix-like OS are multiplexing terminal emulators—which may themselves be run in a terminal emulator, and a console window on Windows™ may be considered to be a terminal emulator of sorts as well.
So, "resorting to APIs" have several technical problems:
Terminal emulation tries to actually decouple the program which uses this facility from being aware of how the facility is actually provided.
To put it simple, there's, say, no easy way on X Window System, to know what window is used by the terminal emulator running your program.
You'd need to cover diverse set of APIs in order for your program to still be useful: X Window System on Unix-like systems, Mac OS, Windows™. And contemporary GUI stacks running on Linux tend to be switching to Wayland instead of X.
In certain cases, like running a program in a "nested" terminal emulation sessions (for example, a pane in a "window" of a tmux running in xterm), figuring out such facts about the environment might be next to impossible.
And still the crucial problem is that if your program really needs to know whether it's focused or not, it actually wants to be aware about the concepts currently hardly accessible to it. I mean, it wants to be GUI. And if so, just make it GUI.
In fact, it may be simpler than you think. The core of your program might still be a CLI app with a thin GUI wrapper around it which uses any sort of IPC to talk with the app (which might be two-way, if needed).
The simplest is to write some (usually line-wise) data to the program's standard input.

Is it's possible make GUI and console app in one exe?

I want to develop App with GUI, that can be run without showing GUI. How I can do it?
If it's possible would this App work on servers that do not have nothing related with GUI (ex: can I work with such App with ssh or so).
Any example please if it's possible.
Yes, it isn't always easy though and might not be worth it. The general idea is to write a console program that attempts to dynamically load the gui libraries and create a window. If that succeeds, it detaches from the console/controlling terminal and becomes a gui program. On Windows, this may pop up a console window briefly when the user double clicks the exe as it would be created first, then quickly destroyed.
You would want to dynamically load the gui with dlopen/LoadLibrary because the libs might not even be present on the computer you're running on, and if you rely on the system to load them at startup, your program won't run at all when they are missing. This is the most painful part - checking the return value of XOpenDisplay or CreateWindow or whatever is easy, and detaching from a console is easy (FreeConsole or fork). But first you need to get your program to actually start in the worst case scenario of no client side gui libraries at all.
If you're ok with ignoring that case - if the libs are present but the display isn't, you just handle it as a regular runtime error - then it isn't too hard at all.

Launching an application from another process

We have an application that we have built as a bundle and we want to launch it from another process.
How should we do it?
From what I understand we can use openUrls(), openFile() or execve()
but I don't know which one better suits us.
Thanks
Since you're talking about an application, you don't want to go through the file association mechanisms. They're for opening documents, images etc. with an appropriate application. Since you don't seem to be sure what to ask, I'd say keep it simple:
The exec* family launches an executable directly. But note that it replaces the launching process with the launched application. Your launcher will stop executing at that point. If you want the launcher to continue to run, you want to use something that launches a subprocess. The low-level way is fork/vfork followed by exec, but it's far simpler to launch your app with system, which takes care of all that behind the scenes. (Assuming there are no security concerns about users on the other side of the world injecting execution paths).
If the launcher does not terminate as soon as it launches your app, you'll want to think about whether it "blocks" until the launched application terminates, or whether it launches the app asynchronously-- so that they then run in parallel. The launcher might also "wait" for the return value of the app, to check whether it succeeded and maybe do something afterwards. There are ways to do all that, but since we don't know what you need, I won't go into details.
In short: If the only job of your launcher is to start your app, use execl. If your launcher needs to do more, use system. If neither one quite fits your needs, you'll need to provide more information-- starting with the language your launcher is written in.
PS. Both of these have the advantage of generality and portability. They work for GUI and commandline applications, and they'll work on any Unix-like system, and to some extent on Windows. There's no need to lock yourself into Cocoa for something so simple.
If you're using Cocoa, you can use NSWorkspace's -launchApplication:.
From OSX documentation on NSWorkspaces:
openFile: Opens the specified file specified using the default application associated with its type.
openURL: Opens the location at the specified URL.
With url you can open also file on ftp, or http for example.

Windows application that optionally remains attached to console

I've got a Windows application (written in C, compiled with MSVC Express edition, 32-bit mode), which has two main modes of operation:
Windowed mode -- create a window, and draw stuff in it (namely, a fractal).
Benchmark mode -- when run with --benchmark as an argument, don't make a window but just print some benchmark statistics to stdout.
During development I've compiled as a Console app, and used SDL to create the window and perform other GUI functions. So benchmark mode runs fine (no window is created), and graphical mode just has a lingering console window.
However for my release compilation I've enabled the Windows subsystem instead of Console. (As explained in this question). This works great except I've suddenly discovered I can't run benchmarks any more. :o
I'm just wondering, is there a way for an application to choose at run time (e.g. based on the command line it's given) which kind of subsystem behaviour to use?
I've done some experimentation with EXE files in Windows (explorer, notepad, winword) and none of them seem to print anything to the console when run with an argument like "/?" (which most Windows console apps support). So it doesn't look like it, but I thought it's worth asking here in case there's a special trick.
Update. It looks like, no, you can't. Thanks for the answers guys.
Additional academic question. Does this mean that the subsystem choice is marked in the EXE header, and it's the operating system that examines this and sets up the Window or connects it to the console it's run from? I don't know much about EXE loading, but I would be curious to learn a few details here.
Conclusion. I think there are four good solutions (plus two semi-solutions, making five total :p) to choose from:
Use the console subsystem, but use FreeConsole when running in GUI mode.
Use the windows system, and use AllocConsole when running in benchmark mode. Not perfect if fractal.exe is run from an existing console, so I'll count this as half a solution ;-).
Just have one executable for each subsystem, fractal.exe and fractalgui.exe.
Have two (or more) executables, one of which does the work and passes it to the other to be displayed on the console or in a Window as appropriate. Needs some thought on how to divide the programs and how to communicate between them.
Another half-solution: have fractalgui.exe print the benchmark to standard out, and pipe that to a utility that will simply print it.
I haven't yet chosen, but I'm leaning towards #3.
Thanks to Matteo and smerlin for the ideas!
There is no way a application can choose her subsystem at runtime (well there are some really ugly workarounds, but those are full of quirks).
Then general solution for this problem is to have a console application, which starts your gui application if necessary
For your benchmark case, it would just print your benchmark statistics.
example setup:
- fractalgui.exe (subsystem: windows)
- fractal.exe (subsystem: console)
* the shortcut on the user desktop links to your fractalgui.exe
* if the user starts fractal.exe from the console, fractal exe starts fractalgui.exe
* if the user starts fractal.exe --benchmark, it either does the benchmark itself (if its possible to add this benchmark logic to another executable) and prints the information directly to console, or - if thats not possible - it will need to start fractalgui.exe --nogui --benchmark. The tricky case here is to get your output from fractalgui.exe to fractal.exe, so you can print it on the appropriate console. There are several ways to do this, e.g. named pipes (there are ways to start fractalgui.exe in a way, that you can just use stdout / cout there, and the data will be piped to the stdout of fractal.exe, but i dont recall how excactly this works anymore (edit: maybe this works)). The easiest way would be to start fractalgui.exe --nogui --benchmark > mylogfile and then print mylogfile after fractalgui.exe finished (since stdout/cout of fractalgui.exe will work if the output is redirected to a file), however you wont get "live" output, since all the output will be printed on the console when fractalgui.exe is already finished.
To add to #smerlin's answer, the other oft-seen method (cited into the articles I linked inside the comment) is to mark your application as a console application, but free the console (using FreeConsole) when you determine that you don't need it.
This is how ildasm does it, but it has the disadvantage of flashing the console for a brief moment between the start of the application and the call to FreeConsole.
Additional academic question. Does this mean that the subsystem choice is marked in the EXE header, and it's the operating system that examines this and sets up the Window or connects it to the console it's run from? I don't know much about EXE loading, but I would be curious to learn a few details here.
Yes, the loader checks the PE header and sets up everything according to the subsystem specified here.
Contrast with the *NIX approach: no executable is "special", and everyone has a working stdin/stdout/stderr; applications that want to display something will call the appropriate functions of Xlib. The drawback is that GUI applications have no clue if the application you are starting normally uses the console, so the system has to ask if you want to spawn also a terminal emulator or to discard the standard streams and just wait for it to spawn a window (obviously shortcuts store this information).
I described a technique for achieving this in my question here.
Matteo already mentioned the .com trick, but that's only part of a viable solution.

Can one detect how .exe was launched?

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.

Resources