How does AutoHotkey determine which executable is launchable with a mere `.exe` name? - windows

In my experience, #f::Run mailmaster will launch mailmaster.exe when pressing #f, but throws when doing #f::Run QQMusic:
I had to provide the full path for QQMusic.exe whereas I didn't have to provide the full path for mailmaster.exe.
According to the documentation:
Run can launch Windows system programs from any directory. Note that executable file extensions such as .exe can be omitted.
Run notepad
Since both mailmaster.exe and QQMusic.exe are non-system programs and they are not included in the Path environment variable, why AutoHotkey is giving different behaviors for them?
And performance-wise, providing the full path versus just the .exe name, which is faster?

It's specified in the documentation:
Target
A document, URL, executable file (.exe, .com, .bat, etc.), shortcut (.lnk), or system verb to launch (see remarks). If Target is a local file and no path was specified with it, A_WorkingDir will be searched first. If no matching file is found there, the system will search for and launch the file if it is integrated ("known"), e.g. by being contained in one of the PATH folders.
So pretty much if it's found in PATH.
You can try this for example by typing notepad, mailmaster and QQMusic in cmd or powershell. Notepad is found in PATH, and on your system I'm assuming mailmaster is as well, and QQMusic isn't.
You should get the same results as with the AHK Run command.
As for performance, I don't know, I guess this is something you could benchmark.
I'd guess that providing the full path is more efficient.
But maybe finding something from PATH is very well optimized on the the Windows side of things, so maybe there is little to no difference.

Related

Windows, relative paths and elevation

I'm getting mad with what (in my mind) should be an easy task:
On my desktop (but could be anywhere) I have a folder "project", a "console.msc" and another folder "files" inside.
"console.msc" have a task that runs file1.bat and it works if I use full paths but it doesn't with relative ones.
c:\users\user1\Desktop\project\files\file1.bat WORKS
.\files\file1.bat
DOESN'T WORK
I see that all the time, the custom mmc is lauched with elevated privileges (good, I want it) but the relative path used to call file1.bat just doesn't work and the error returned is "Windows cannot find [..]"
Does anybody know how to tell Windows to keep the current folder the mmc is run? Any clues welcomed! :-)
Running a process with elevated privileges might result in different working directory for that process, that's why relative paths are not working.
If you do not want to use absolute paths, you have to find a way to get path to a directory where your application is located, and then append the relative paths to that.
You don't specify how you are running your tasks, but if it's from another .BAT file, then full path to the batch file's directory is stored under %~dp0 variable. You can look up answers to this question for more details.
And you can also always use tool like Process Explorer to view information about your running process, including working directory (it's called Current directory there).

Prevent Program (.exe) from starting DIRECTLY (Only allow execution from shortcut)?

Is there a way to prevent direct startup of a .exe program, and only start up when a shortcut is run? I'd like this to work also when opening up a filetype that is assigned to a program.
The only thing that comes close to what you want is checking for certain command line parameters. This is actually a rather common way for concealed executions - for instance programs that want you to run a loader program first (online games would be an example).
So you would have to generate a shortcut that privdes the specific command line arguments needed for the start. This ensures that your exe cannot be executed directly, however there are no guaranties that a specific shortcut file is startet as it only provides a link to the exe file.
No, that is not possible, in my knowledge.
This is not possible, the shortcut is executing the program in its location. The .exe has to be executable for the shortcut to work. Assigned file extensions also execute the actual .exe the shortcut is just a symbolic link to the actual file.
If you can give more information as to what your trying to accomplish I could maybe offer another solution.
I'm not aware of any way built in to do this, as an executable is still launched as that user by the shortcut. You can disable shortcut locations, allow only certain executables, etc but not deny access to executable but also allow it via shortcut.

Windows 8.1 Pro MinGW Gfortran Command Prompt 'not recognized command' error

C:\Users\redacted\Documents\redacted>gfortran hibrac.f -o hibrac.exe
'gfortran' is not recognized as an internal or external command,
operable program or batch file.
https://gcc.gnu.org/wiki/GFortranBinariesWindows seems similar to my problem: gfortran.exe is in C:\Windows\MinGW\bin -- except the solution appears not to apply to Windows 8.1 Pro:
Right click on My Computer, Properties, Advanced Tab, Environment Variables.
Instead I tried: Right click on 'This PC' within File Explorer, Properties, Advanced system settings, Advanced Tab -- and I cannot find an equivalent-looking section that allows me to proceed with the advised solution.
As background information:
I had installed MinGW Installation Manager which installed mingw32-gcc-fortran (together with mingw32-base, -gcc-g++, and -gcc-objc) in the recommended C:\Windows\MinGW folder, without any apparent error message.
Isn't it acceptable -- standard practice -- to have one's code in a folder separate from this MinGW folder? i.e. a subdirectory of my Users\account rather than a subdirectory of MinGW. This isn't the problem, is it? What do I need to do to get it to recognize the gfortran.exe, or call it correctly?
Please tell me what to do to get it working. If it's relevant, I have a Japanese computer with an English language pack installed (it seems to have some gaps, such as some text in the Settings charm or startup/shutdown text being in Japanese).
This looks very much like you have neglected to add C:\MinGW\bin to the effective PATH for the command window, in which you are attempting to run the gfortran command.
Your question isn't entirely specific on this point, (i.e. you could improve the question), but you hint that you were unable to add the appropriate PATH entry to the global environment variables, because you couldn't find the appropriate control panel applet? I know that this is often recommended as part of a MinGW setup, but the installer will not do it for you, because I, as the maintainer of mingw-get, don't consider that to be best practice; much better, IMO, to add it for each specific command window in which you need it to take effect, by running (once, at the start of each command prompt session) the command:
path %PATH%;C:\MinGW\bin
If you prefer, you may create a batch file to do this for you, along with any other initializations you wish to perform, (or better still, use MSYS as the working shell environment, in which case the PATH initialization is taken care of by the shell's own initialization scripts).

What are the differences between running an executable from a Windows Command Prompt versus from Windows Explorer?

EDIT: This is due to stupidity. It is a multiple monitor issue. It's just that from cmd.exe we always opened in the primary monitor, whilst from explorer, we always opened in the secondary. Thanks all for the help!
We hit a weird bug recently. We have a Qt + osg app that behaves differently if we run it from explorer than if we run it from a command line. Running from explorer is unusable, while running from command line (or by running from the explorer a simple batch file that calls the .exe) works as expected.
We suspect environment variables, because that's all we can think of. But the fact that it runs fine with a one line batch file seems to refute this. I'm not familiar enough with windows to know of any subtle differences in how it loads executables, nor where to look to find out.
Are there any other differences that could explain this? Does windows load different sets of user environment variables in each case? OS is Windows XP Service Pack 3.
The behavior experienced when running from explorer (double click program.exe) is consistent with a driver issue or improper OSG scene setup: image artifacts, flashing, and weird colors.
The behavior experienced when running the same executable from cmd.exe (or by double clicking a .bat file next to the .exe containing only a line to run the .exe) is the correct, expected behavior: the scene is correct, no flashing, etc.
To rule out potential library load path issues, try using dot-local DLL redirection.
Towards that end, create an (empty) file in the same directory as your executable and give it the same name as your binary, except with .local appended. I.e., if your binary is named yourbinary.exe, name that file yourbinary.exe.local. That will force the PE loader to first look in that directory to resolve LoadLibrary calls (and that includes DLLs loaded indirectly via system DLLs or via COM, no matter how many indirection levels are involved.) Place as many supporting DLLs (including Qt DLLs) in that directory. If you're using Qt plugins, also place the plugins directory there (or use a custom trolltech.conf.)
More details on dot-local redirection here, for example.
This thread looks like it might have the answer to your question:
http://forum.soft32.com/windows/Start-Run-Command-Prompt-ftopict353085.html
In short, I think it might be looking for your executable in different places depending on which method you attempt to use to run it. Perhaps you have 2 different versions hiding somewhere that explorer uses instead of the one you want?
You have not given enough details so I will give you a general answer. In order to use QT and its tools you need 2 environment variables. *QTDIR, and PATH * Make sure you have these variables set instructions are below. I have taken them from this site. See also this link for deployment on windows.
Setup the QTDIR environmental
variable.
1) Create a new System variable
called: QTDIR
a. Right click on My Computer -> Properties -> Advanced Tab ->
Environment Variables button
b. Find System variables -> New -> Type in "QTDIR" 2) Set the value to: C:\your\Qt\directory (NOTICE: No
trailing '\' character!!!)
Now, add the QTDIR on to your PATH
variable.
1) Edit your PATH variable, add onto
the end of it a ';' if one isn't
already on the end. 2) Now add on:
%QTDIR%\bin;
Example:
Before
PATH=%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem;
After,
PATH=%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem;%QTDIR%\bin;
That will make sure that our Qt
application(s) will be able to find
the Qt DLL files when you go to run
it.
I hope this helps.
Perhaps there is a difference caused by the way Explorer launches an executable vs directly running it from the console. I think that Explorer uses ShellExecute or ShellExecuteEx and I doubt that executing an application from a console or batch file does the same.
I would create a test app that tries some of the ShellExecute variants and use different parameters to see if the Explorer behavior can be reproduced in order to try to diagnose what parameters passed to ShellExecute might be causing the problem.
There is an interesting community note on the ShellExecuteEx page that may or may not be applicable:
ShellExecuteEx ignores the current input desktop. It always uses winsta0\default. Instead use ShellExecute or CreateProcess.
I would also investigate whether or not AppCompatFlags affect console executed applications (or see if any AppCompatFlags have been set for your application).

file path portability

I have a program that I need to run under *nix and windows. because the program takes file paths from files the issue is what to do about the \ vs / issue.
My current thought is to put in a regex that converts the wrong one to the right one depending on what system I'm on. This will have the effect of letting either type work on either system. Aside from the fact that now I have two problems, does anyone see any other problems?
(Other better solutions are more than welcome)
Edit: the primary issue is getting windows paths to work on unix rather than the other way around.
The / is fully supported in win32 too.
Also see this related question
Windows will generally accept either \ or /,so standardizing on / may make your problem simpler as long as you have complete control over the filenames.
Have you considered creating a "file manager" class that will handle all of the file pathing issues for you? That way in your mail application, when you're loading a data file, you can call something like this.
LoadApplicationData(FileManager.GetDataFilePath)
Then your file manager will detect the environment that it is in and return the proper file path option. That way you can also accomodate for Win32 vs. Unix locatio standards (like Program Files vs /usr or whatever) as well.
Note that Win32 paths are complex when you consider drive letters (no analog on Unix) and the special 'forks' (MacOS pre-X term - likewise no analog on Unix in general, though MacOS X has them - surprise, surprise) that can be provided. Be careful.
Create a parser for your input to create a tree structure of nodes representing directories. Then you can 'save' by walking the tree and writing whatever delimiters you want or optionally doing different things, like checking if the directory exists or writing meta files. This is actually something that I am just now thinking would be useful for my own application :-)
You didn't say what language you are using, so I'm going to selfishly assume c/c++. boost, if you are willing to use it, has a filesystem library. Of course, if you are using a dynamic language, FS abstraction libraries probably already exist there too (e.g. in perl, File::Spec is quite standard).
You haven't told us what sort of files you are reading paths in from. I am going to assume that they are config files. In which case, there are many ways, IMHO the correct answer is to design your program to avoid manipulating paths, if possible. I posted an answer here: https://stackoverflow.com/a/40980510/2345997 which is relevant.
ways:
Add a command line option which allows a user to specify the path in question instead of reading it from a config file.
Add a command line option so that the user can specify a base path. Paths in the config file will be interpreted as located under this base path.
Split your config file into three. One file will have cross platform configuration, another file will have windows only configuration and a final file will have Linux only configuration. Then the user can specify the correct path for both Windows and Linux. On windows your program will read the cross-platform config file and the windows only config file. On Linux it will read the cross-platform file and the Linux only config file.
Add preprocessing to your config file parsing. This will allow you to have one config file where the user can make your program ignore some of the lines in the file depending on which OS the program is running on. Therefore, the user will be able to specify the path to the file twice. Once for Linux, and once for Windows.
Change the design so that the files are always located in the same directory as your executable - then the user only specifies file names in the config file rather than paths to files.
Use a simple function that switches "/" to "\". Then document to the user that they must specify paths as Linux paths and this transformation will be applied for windows.
Create your own path mini-language for this and document it to the user. E.g: "/" - specifies a directory separator, {root} - expands to the root of the filesystem, {cwd} - expands to the current directory, {app} - expands to the path to your application etc... Then the user can specify file paths like: {root}/myfiles/bob.txt on both platforms.
Some paths will work on both platforms. E.g: relative paths like ../my files/bill.txt. Restrict your application to only work with these paths. Document this limitation and how your application handles paths to the user.

Resources