Installer is sometimes unable to find running TC instances
Moderators: Hacker, petermad, Stefan2, white
Installer is sometimes unable to find running TC instances
There are some scenarios, in which TC installer is unable to find running TC instances.
Steps to reproduce (1):
1) Launch TC installer and install TC to "c:\Total Commander" (exactly to this path!)
2) Launch cmd.exe and execute: c:\totalc~1\totalcmd.exe (most probably, short name for "Total Commander" folder will be "totalc~1"; you may try also with "totalc~2" in case of failure)
3) Launch TC installer and install TC to "c:\Total Commander" - installer will not be able to find the running TC instance, so it will fail when overwriting files
Steps to reproduce (2):
1) Launch TC installer and install TC to "c:\Total Commander" (exactly to this path!)
2) Launch cmd.exe and execute: "c:\Total Commander\totalcmd.exe" (with double quotes!)
3) Launch TC installer and install TC to c:\totalc~1 - installer will not be able to find the running TC instance, so it will fail when overwriting files
Solution: It seems that calling GetLongPathName API for both paths being compared (i.e. for the installation path and for the running executable path) should help.
Additional improvement, to make the algorithm even more robust: The current algorithm in the installer, when obtaining an executable path from a process ID, is:
1) call OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, .. ,ProcessID)
2) if failed then exit
3) try with GetModuleFileNameExA
4) if failed then try with QueryFullProcessImageNameA
Calling OpenProcess for GetModuleFileNameExA requires more access rights than calling OpenProcess for QueryFullProcessImageNameA. So a better algorithm would be:
1) call OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, .. ,ProcessID)
1b) if failed then OpenProcess(PROCESS_QUERY_INFORMATION, .. ,ProcessID)
1c) if failed then OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, .. ,ProcessID)
2) if failed then exit
3) try with GetModuleFileNameExA
4) if failed then try with QueryFullProcessImageNameA
For a process handle opened with PROCESS_QUERY_INFORMATION or with PROCESS_QUERY_LIMITED_INFORMATION, GetModuleFileNameExA call will always fail, but QueryFullProcessImageNameA should succeed.
Regards
Steps to reproduce (1):
1) Launch TC installer and install TC to "c:\Total Commander" (exactly to this path!)
2) Launch cmd.exe and execute: c:\totalc~1\totalcmd.exe (most probably, short name for "Total Commander" folder will be "totalc~1"; you may try also with "totalc~2" in case of failure)
3) Launch TC installer and install TC to "c:\Total Commander" - installer will not be able to find the running TC instance, so it will fail when overwriting files
Steps to reproduce (2):
1) Launch TC installer and install TC to "c:\Total Commander" (exactly to this path!)
2) Launch cmd.exe and execute: "c:\Total Commander\totalcmd.exe" (with double quotes!)
3) Launch TC installer and install TC to c:\totalc~1 - installer will not be able to find the running TC instance, so it will fail when overwriting files
Solution: It seems that calling GetLongPathName API for both paths being compared (i.e. for the installation path and for the running executable path) should help.
Additional improvement, to make the algorithm even more robust: The current algorithm in the installer, when obtaining an executable path from a process ID, is:
1) call OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, .. ,ProcessID)
2) if failed then exit
3) try with GetModuleFileNameExA
4) if failed then try with QueryFullProcessImageNameA
Calling OpenProcess for GetModuleFileNameExA requires more access rights than calling OpenProcess for QueryFullProcessImageNameA. So a better algorithm would be:
1) call OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, .. ,ProcessID)
1b) if failed then OpenProcess(PROCESS_QUERY_INFORMATION, .. ,ProcessID)
1c) if failed then OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, .. ,ProcessID)
2) if failed then exit
3) try with GetModuleFileNameExA
4) if failed then try with QueryFullProcessImageNameA
For a process handle opened with PROCESS_QUERY_INFORMATION or with PROCESS_QUERY_LIMITED_INFORMATION, GetModuleFileNameExA call will always fail, but QueryFullProcessImageNameA should succeed.
Regards
- ghisler(Author)
- Site Admin
- Posts: 50541
- Joined: 2003-02-04, 09:46 UTC
- Location: Switzerland
- Contact:
Currently the installer does not handle short names. But you will get an error when overwrite fails, so you can close the program manually.
Author of Total Commander
https://www.ghisler.com
https://www.ghisler.com
Ok, my examples were a bit artificial...
But I had similar problems sometimes, even without using short names (at least intentionally). I was not able to reproduce the problem, but I suppose that it might be due to the code that I described above.
Please consider improving it - adding two OpenProcess calls and two GetLongPathName calls should be a two-minute work.
Regards
But I had similar problems sometimes, even without using short names (at least intentionally). I was not able to reproduce the problem, but I suppose that it might be due to the code that I described above.
Please consider improving it - adding two OpenProcess calls and two GetLongPathName calls should be a two-minute work.
Regards
- ghisler(Author)
- Site Admin
- Posts: 50541
- Joined: 2003-02-04, 09:46 UTC
- Location: Switzerland
- Contact:
I prefer not to use GetLongPathName, because it will access the file system and go through all parts of the path. TC checks all running process locations, and it could cause a lot of problems and slow speed.
Author of Total Commander
https://www.ghisler.com
https://www.ghisler.com
Well, it's not so bad...
TC installer enumerates all top-level windows on the desktop - but only for those windows, that have class names and titles like TC, installer performs further actions - i.e. checks for the window executable's path.
So, in practice, this gives one GetLongPathName call per every running TC instance, plus one initial call for the installer's destination path, that has been entered by the user. In practice - ein Augenblick ;)
TC installer enumerates all top-level windows on the desktop - but only for those windows, that have class names and titles like TC, installer performs further actions - i.e. checks for the window executable's path.
So, in practice, this gives one GetLongPathName call per every running TC instance, plus one initial call for the installer's destination path, that has been entered by the user. In practice - ein Augenblick ;)
- ghisler(Author)
- Site Admin
- Posts: 50541
- Joined: 2003-02-04, 09:46 UTC
- Location: Switzerland
- Contact:
OK, I have added it now for test purposes to beta 2. If anyone encounters a problem with the installer now, please let me know!
Author of Total Commander
https://www.ghisler.com
https://www.ghisler.com
- ghisler(Author)
- Site Admin
- Posts: 50541
- Joined: 2003-02-04, 09:46 UTC
- Location: Switzerland
- Contact:
I'm only calling QueryFullProcessImageNameA in 32-bit. Why? GetModuleFileNameExA does not work for 64-bit modules accessed from a 32-bit program. However, the reverse works: A 64-bit program can actually see the name of a 32-bit process with GetModuleFileNameExA.
Why should the 64-bit installer call QueryFullProcessImageNameA? Is there a specific case where this is needed?
Why should the 64-bit installer call QueryFullProcessImageNameA? Is there a specific case where this is needed?
Author of Total Commander
https://www.ghisler.com
https://www.ghisler.com
There is one case, where QueryFullProcessImageNameA may be helpful - if OpenProcess failed with PROCESS_QUERY_INFORMATION + PROCESS_VM_READ, but then succeeded with PROCESS_QUERY_INFORMATION or with PROCESS_QUERY_LIMITED_INFORMATION.
GetModuleFileNameExA will fail in the latter two cases, but QueryFullProcessImageNameA will do the work.
Regards
GetModuleFileNameExA will fail in the latter two cases, but QueryFullProcessImageNameA will do the work.
Regards
- ghisler(Author)
- Site Admin
- Posts: 50541
- Joined: 2003-02-04, 09:46 UTC
- Location: Switzerland
- Contact:
In which case would it fail with PROCESS_QUERY_INFORMATION + PROCESS_VM_READ? The installer is always run elevated.
Author of Total Commander
https://www.ghisler.com
https://www.ghisler.com
- ghisler(Author)
- Site Admin
- Posts: 50541
- Joined: 2003-02-04, 09:46 UTC
- Location: Switzerland
- Contact:
OK, I have added this call to beta 3 64-bit now...
Author of Total Commander
https://www.ghisler.com
https://www.ghisler.com