• How to call a Windows executable from Ada?

    From Marius Amado-Alves@21:1/5 to All on Wed Dec 8 15:04:38 2021
    Any *effectively working* solution for calling an external Windows executable, with arguments, from inside Ada?

    For example, the following command runs fine when given on the Windows command line:

    "C:\Program Files\Microsoft Office\root\Office16\WINWORD.EXE" /f "C:\long path\with spaces\and accented letters\like in the words\declaração de autorização.docx" /mSave_As_Txt

    The same command FAILS when called from inside Ada with any of the know "solutions" on GNAT gem [1] and Rosetta Code [2].

    But there must be a way!

    Share your good code.

    Thanks.

    [1] https://www.adacore.com/gems/gem-54
    [2] https://rosettacode.org/wiki/Execute_a_system_command#Ada

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Randy Brukardt@21:1/5 to All on Wed Dec 8 23:09:55 2021
    It's hard to say anything definitive without seeing the code that you tried.
    I haven't found a program that you couldn't run from Ada (using the
    Janus/Ada facilities; GNAT's are more extensive so I wouldn't expect any difference there), but some things require care. I've definitely never found anything that you can't run by starting a command line processor; that
    doesn't allow the real-time capture of the results by the calling program
    but that wouldn't make sense with Winword.exe anyway.

    Randy.

    "Marius Amado-Alves" <amado.alves@gmail.com> wrote in message news:71f3752c-40a2-4678-9451-1223a776b384n@googlegroups.com...
    Any *effectively working* solution for calling an external Windows
    executable, with arguments, from inside Ada?

    For example, the following command runs fine when given on the Windows
    command line:

    "C:\Program Files\Microsoft Office\root\Office16\WINWORD.EXE" /f "C:\long path\with spaces\and accented letters\like in the words\declarao de autorizao.docx" /mSave_As_Txt

    The same command FAILS when called from inside Ada with any of the know "solutions" on GNAT gem [1] and Rosetta Code [2].

    But there must be a way!

    Share your good code.

    Thanks.

    [1] https://www.adacore.com/gems/gem-54
    [2] https://rosettacode.org/wiki/Execute_a_system_command#Ada

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dmitry A. Kazakov@21:1/5 to Marius Amado-Alves on Thu Dec 9 08:29:19 2021
    On 2021-12-09 00:04, Marius Amado-Alves wrote:
    Any *effectively working* solution for calling an external Windows executable, with arguments, from inside Ada?

    For example, the following command runs fine when given on the Windows command line:

    "C:\Program Files\Microsoft Office\root\Office16\WINWORD.EXE" /f "C:\long path\with spaces\and accented letters\like in the words\declaração de autorização.docx" /mSave_As_Txt

    The same command FAILS when called from inside Ada with any of the know "solutions" on GNAT gem [1] and Rosetta Code [2].

    I doubt very much that GNAT.OS_Lib.Non_Blocking_Spawn does not work. You
    do something wrong, like passing quotation marks etc. Remember, Windows
    does not have argument lists Linux have. So all UNIX-esque calls like Non_Blocking_Spawn are ultimately assembled back into a single
    command-line which is then split back again inside the process. Thus
    dealing with quotation marks you must make it sure that they are not get
    eaten or introduced.

    As for other ways, if you need access to input/output/error of the
    process you can use GLib primitives:

    http://www.dmitry-kazakov.de/ada/gtkada_contributions.htm#10

    --
    Regards,
    Dmitry A. Kazakov
    http://www.dmitry-kazakov.de

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Vadim Godunko@21:1/5 to amado...@gmail.com on Wed Dec 8 23:26:44 2021
    On Thursday, December 9, 2021 at 2:04:40 AM UTC+3, amado...@gmail.com wrote:
    Any *effectively working* solution for calling an external Windows executable, with arguments, from inside Ada?

    For example, the following command runs fine when given on the Windows command line:

    "C:\Program Files\Microsoft Office\root\Office16\WINWORD.EXE" /f "C:\long path\with spaces\and accented letters\like in the words\declaração de autorização.docx" /mSave_As_Txt

    The same command FAILS when called from inside Ada with any of the know "solutions" on GNAT gem [1] and Rosetta Code [2].

    But there must be a way!

    Share your good code.

    See https://github.com/AdaCore/spawn

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Marius Amado-Alves@21:1/5 to All on Thu Dec 9 01:28:59 2021
    Thanks all.

    Yeah, it's probably the quotation marks. I found no way around it with GNAT.OS_Lib. The quotes are needed because the names have spaces.

    Only way I found that works is with the command inside a .BAT file, then call that with GNAT.OS_Lib.Spawn

    Arguments : Argument_List :=
    ( 1=> new String'("C:\Test\save_as_txt.bat"),
    2=> new String'("")
    );
    begin
    Spawn
    ( Program_Name => "C:\Test\save_as_txt.bat",
    Args => Arguments,
    Output_File_Descriptor => Standout,
    Return_Code => Result
    );

    Also the BAT file *must* start with the magic incantation

    chcp 65001

    on the first line, in order for the accented characters to work.

    So, a pragmatical solution exists, but ugly and irritating and hard to find. Hope these tips may save someone as many hours as I wasted with OS_Lib nonsense.
    Still a clean documented solution is to be found.
    Share your good code.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dennis Lee Bieber@21:1/5 to All on Thu Dec 9 13:38:23 2021
    On Thu, 9 Dec 2021 01:28:59 -0800 (PST), Marius Amado-Alves <amado.alves@gmail.com> declaimed the following:

    Thanks all.

    Yeah, it's probably the quotation marks. I found no way around it with GNAT.OS_Lib. The quotes are needed because the names have spaces.


    Have you tried /building/ those strings using character literals? Or doubled quotes...

    wulfraed@debian:~/Scratch$ cat stringtest.adb
    with Text_IO; use Text_IO;

    procedure stringtest is
    begin
    Put_Line("String with spaces");
    Put_Line('"' & "String with spaces, delimited" & '"');
    Put_Line("""String with doubled quotes""");
    end stringtest;
    wulfraed@debian:~/Scratch$ gnatmake stringtest.adb
    x86_64-linux-gnu-gcc-8 -c stringtest.adb
    x86_64-linux-gnu-gnatbind-8 -x stringtest.ali
    x86_64-linux-gnu-gnatlink-8 stringtest.ali
    wulfraed@debian:~/Scratch$ ./stringtest
    String with spaces
    "String with spaces, delimited"
    "String with doubled quotes"
    wulfraed@debian:~/Scratch$


    --
    Wulfraed Dennis Lee Bieber AF6VN
    wlfraed@ix.netcom.com http://wlfraed.microdiversity.freeddns.org/

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dmitry A. Kazakov@21:1/5 to Marius Amado-Alves on Thu Dec 9 20:27:39 2021
    On 2021-12-09 10:28, Marius Amado-Alves wrote:

    Yeah, it's probably the quotation marks. I found no way around it with GNAT.OS_Lib. The quotes are needed because the names have spaces.

    Only way I found that works is with the command inside a .BAT file, then call that with GNAT.OS_Lib.Spawn

    Arguments : Argument_List :=
    ( 1=> new String'("C:\Test\save_as_txt.bat"),
    2=> new String'("")
    );
    begin
    Spawn
    ( Program_Name => "C:\Test\save_as_txt.bat",
    Args => Arguments,
    Output_File_Descriptor => Standout,
    Return_Code => Result
    );

    Also the BAT file *must* start with the magic incantation

    chcp 65001

    on the first line, in order for the accented characters to work.

    Try to put arguments with spaces in quotation marks. E.g.

    3 => new String'("""a b c d""");

    Another potential issue is with non-ASCII characters. I do not know what
    call GNAT.OS_Lib uses internally. If that is CreateProcessA then you are
    out of luck. If it calls to CreateProcessW then the question how
    GNAT.OS_Lib converts arguments to UTF-16. There are two most likely possibilities:

    1. The arguments are treated as Latin-1 encoded

    2. The arguments are treated as UTF-8 encoded

    In both cases (and always) never ever use anything but ASCII in the
    source code. Do not trust the compiler, do not trust the file system, do
    not trust GPS.

    Encode your funny letters explicitly. Use Character'Val with the codes
    you want (or Characters.Latin_1). First for Latin-1, then if that does
    not work, try UTF-8.

    P.S. Note that GLib solution consistently uses CreateProcessW and UTF-8
    in the strings and never ever Latin-1.

    P.P.S. You can just call CreateProcessW, it is not a big deal. Remember
    to use Wide_String with UTF-16 encoded content. Windows is
    little-endian, so use UTF-16LE.

    --
    Regards,
    Dmitry A. Kazakov
    http://www.dmitry-kazakov.de

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)