How to properly call system on Windows

58 ビュー (過去 30 日間)
Kylie MacFarquharson
Kylie MacFarquharson 2021 年 7 月 24 日
編集済み: dpb 2021 年 7 月 24 日
I'm trying to make a project cross platform, it already works on Linux systems.
The main problem I am having is that I need to call an external executable qafm / qafm.exe
On Linux I just put the executable on in ~/bin, which is on the PATH for my user, so running
system('qafm --rest-of-arguments')
works nicely.
For instance
system('qafm')
returns 1 and prints usage to the command window, as I'd expect.
However on windows I am having trouble.
First, I don't know how to set a user specific path, so I just copied the executable qafm.exe to a MATLAB folder.
This isn't some broken rpath or anything though, if I run .\qafm or .\qafm.exe in powershell or cmd in that folder I get the expected usage output.
However, if I run in the same folder in MATLAB R2019b
system('.\qafm')
it returns -1.0737e+09 (Not a valid error code for the program I promise) and prints nothing to the command window.
Any idea what the problem might be?
  9 件のコメント
Kylie MacFarquharson
Kylie MacFarquharson 2021 年 7 月 24 日
編集済み: Kylie MacFarquharson 2021 年 7 月 24 日
I think the reason those runtime directories are in the path (in the middle) is because those are actually on the system path (they're added when installed and I guess not removed when uninstalled). Try set PATH from a cmd, they'll be there.
However it seems that when you run system() it also prepends and extra folder to the path, ahead of C:\Windows\System32, so it overwrites the default system dlls like libstdc++ stuff.
To fix, getenv('path') seems to return the actual system path, and I just
system(sprintf('set PATH=%s & qafm.exe'), getenv('path'))
It feels a little hacky but it works so I'm calling it a win.
Should I submit this as an answer for googlers?
dpb
dpb 2021 年 7 月 24 日
That'll work but it seems to me a better way would still be to have the executable on its own rather than adding into a ML directory...but it's your code so your choice on that organization structure.
May as well put it in as an Answer -- that'll indicate to others that watch but may not be around today that there is a solution so that if they're busy don't spend time on Q? that do have at least one acceptable Answer.
As for the other old paths; I grok that; I just would have hoped the older releases would have been cleaned up with the new install -- although I suppose they're needed if one wanted to be able to run older releases as well. I haven't figured out how to keep the license active on them all so while the older installs are still on the system, they're not activated. I suppose if I were to uninstall them, then it would clean things up. But, who knows--I might at some point in the future need one of the earlier releases and have to go figure out the license thingie then... :) As long as "out of sight, out of mind!" I don't guess it hurts too much unless the path reaches whatever its internal length limit is...

サインインしてコメントする。

採用された回答

Kylie MacFarquharson
Kylie MacFarquharson 2021 年 7 月 24 日
編集済み: dpb 2021 年 7 月 24 日
Answering myself as we worked it out in the comments:
When MATLab makes system call with system() or !, it prepends to the PATH environmental variable "C:\Program Files\MATLAB\R2019b\bin\win64". Because the PATH is read left to right, any .dlls in this folder will be found first by the OS as it tries to execute whatever program you are running. This folder includes (somewhere) a .dll which defines libstdc and libstdc++, and these defininitions will be used over the OS versions in C:\Windows\system32. If your executable was compiled with a recent version of c++, like c++20, it won't won't be able to run (assuming it wasn't staticly linked). Apparently on Windows this fails silently, hence the lack of useful error messages.
The solution to this is to change the PATH variable before running the executable.
One option is to write a batch script that sets the PATH and then runs the exec (versetile, but adds another file to keep track of)
Another option is to simply set the path immeditely before executing the exec. Thankfully getenv('PATH') returns the actual system PATH.
system(sprintf('set PATH=%s & qafm.exe'), getenv('PATH'))
  3 件のコメント
Kylie MacFarquharson
Kylie MacFarquharson 2021 年 7 月 24 日
It would probably be easier to edit the PATH in matlab and then set it before running the batch file.
dpb
dpb 2021 年 7 月 24 日
That's what I was suggesting, yes...it's too much grief in CMD. TCC (the JPSoft CMD replacement) would make it trivial exercise, however... :)

サインインしてコメントする。

その他の回答 (0 件)

カテゴリ

Help Center および File ExchangeStartup and Shutdown についてさらに検索

タグ

製品


リリース

R2019b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by