Can one detect how .exe was launched? - winapi

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.

Related

How to detect from console or GUI app was run?

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.

Get invoking shortcut

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.

Win GUI App started from Console => print to console impossible?

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?

What's the best way to stop multiple instances of a Windows app being launched?

Many Windows apps (like Skype or MSN for instance) don't let you start multiple instances, rather trying to run it a 2nd time just leaves the existing version running.
Is this typically done in some simple way - the start-menu shortcut is a 'wrapper' app around the main app - or is there some registry magic you can do to delegate the problem to Windows itself?
Specifically dealing with Win32 here (unmanaged C++) but happy to hear more general solutions as long as they are workable on Windows XP or later.
EDIT: this seems the best duplicate.
Named Mutex or similar OS-specfic named object. If it exists - app is running.
Lock file somewhere (in temporary directory, etc - create it on program start, remove on program end). Linux software frequently operates this way (some programs store PID in lockfile), but it isn't safe - if you suddenly lose power (electricity cut off), it is possible that lock file won't be deleted.
And you can always enum all running processes and try to find yourself.
There could be more ways to do it, but those are the first ones I could think of.
As far as i remember, there exist system-wide Mutexes. Set Mutex on first launch, if on launch already set, immediately exit.
Use CreateMutex() call an prepend the name with "Global\" should to the trick.
I just check to see if the process is already running: if it's not start the application, if it's already running bring the window to foreground. The check is done in the Main method.
I get the process name with System.Diagnostics.Process.GetCurrentProcess().ProcessName and check if it's already running System.Diagnostics.Process.GetProcessesByName(). If there are more than 1 processes focus the first of them and then exit.

chdir programmatically

In Windows -- and probably Unix for that matter -- using the chdir() function in a (32-bit) program doesn't change the directory when the program exits. (It does in a 16-bit Windows program.)
Does anybody know how to do that in a Windows 32-bit program?
Uhm... IMHO it's exactly one of the things that the OS must guarantee not to happen. The current dir is a per-process property, a child process usually inherits it from the parent process, but the reverse should not happen (and it doesn't).
To obtain what you want, the parent could actively watch some information (message, file, shared memory...) in which the child process stores the new directory, and then call chdir() with the new value.
As far as I know, Windows' cmd.exe doesn't have any mechanism like that.
Actually, by using code injection techniques (e.g. CreateRemoteThread) on the parent process it could be possible to force it to do something unexpected, but it's a very dirty trick, not at all good neither general.
Win16 was different: there was a single "msdos" state for all the programs, but it was a limitation, not a feature.
It sounds like you're asking one process (your Win32 program) to change the CWD of another process (your shell). As far as I know, this is impossible without the latter process providing an API for such a purpose. The nearest I can come to any sort of reference for this assertion, however, is the following quote from MSDN:
A parent process can directly alter the environment variables of a child process during process creation. This is the only situation when a process can directly change the environment settings of another process.
Well yeah it's true the popular API calls to change directory change it for the process. ... BUT ...
(1.) 16-bit windows programs can change the global directory; probably because they run in the same process as the command.com thing. That's what I've been happily using for years; I assume XP somehow emulates this? ... But now Windows 7 64-bit won't run 16-bit programs anymore! (?)
(2.) Both Windows and Unix "cd" commands can of course change directories for the calling process -- presumably because they are built-in commands of the command shell. But successor Windows shells manage to accomplish this, or at least I hope PowerShell can do that. All built-ins?
(3.) The way I've wound-up doing it is modifying my programs that used to call the API to simply emit "cd \dst\directory" to stdout, then in a procedure do
chdirprogram >t~.bat
call T~.bat
Which works great. And of course the usual point of a change-directory program is to provide the functionality in a batch procedure with a computed destination. Which of course you can do in Unix with Bash etc. variables, but not in Windows batch files, although maybe (?) in the numerous successor Windows procedure things, which I don't want to use. ... Since this functionality is obviously useful, I was hoping someone knew of a sneaky Windows call what'd do it. The explanation that it's somehow wrong for a process to change the directory for a calling process is one of those bogus, "you're not supposed to do that and I won't tell you why" excuses. ... But I guess I'll just stick to my pitiful little batch files.
Are you talking about the SetCurrentDirectory function of Windows API? The article says that the function "changes the current directory for the current process". In for instance Delphi, there is a function ChDir that actually calls this API function.

Resources