Need to retrieve the path of an invoking shortcut.
This is a Qt application, but I suspect I'm going to have to go native to do this, primarily on win. I can come up with a scheme for Mac..
Is there a way to get this? The win terminal application seems to be able to do this, for instance.
(it needs to work for a moved shortcut, so I can't embed the path in an arg.)
When a process is started, there is no information passed that identifies the shortcut that was used to invoke the new process. You need to use command-line arguments to pass startup parameters to the new process.
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 currently have a resource light "unmanaged" Windows C++ application using:
CreateMutex to ensure there is at most a single instance of the application.
COPYDATASTRUCT to pass command line parameters over to that single instance, should another instance attempt to start (after sending data, it will then quit).
The use case is a simple one: launch a new application instance to open a file specified on the command line, or otherwise open the file in a previously-launched application instance.
How could I achieve the same behaviour in a Haskell program?
It looks like CreateMutex isn't offered in the Win32 package that comes with GHC. You'll need to either bind to it yourself using the FFI or emulate it in a cross-platform way. One trick commonly used on Linux is to choose a particular filename to act as the "mutex"; if it doesn't exist, you create it and write down how to contact you then delete it when you exit, while if it does, you read the contact information out of it to find out how to connect to the already running process. This approach does have downsides: if either your app or the computer as a whole goes down, you'll have stale contact information.
For IPC, I think there's a number of cross-platform interfaces. Wikipedia has an excellent list; especially suitable for doing this task in Haskell are sockets, (named) pipes, and dbus. For the latter two, you may need Cygwin, since they ultimately depend on getting the unix package installed.
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.
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?