comp.lang.ada
 help / color / mirror / Atom feed
* How to call a Windows executable from Ada?
@ 2021-12-08 23:04 Marius Amado-Alves
  2021-12-09  5:09 ` Randy Brukardt
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Marius Amado-Alves @ 2021-12-08 23:04 UTC (permalink / raw)


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

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: How to call a Windows executable from Ada?
  2021-12-08 23:04 How to call a Windows executable from Ada? Marius Amado-Alves
@ 2021-12-09  5:09 ` Randy Brukardt
  2021-12-09  7:26 ` Vadim Godunko
  2021-12-09  7:29 ` Dmitry A. Kazakov
  2 siblings, 0 replies; 7+ messages in thread
From: Randy Brukardt @ 2021-12-09  5:09 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 1361 bytes --]

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\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


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: How to call a Windows executable from Ada?
  2021-12-08 23:04 How to call a Windows executable from Ada? Marius Amado-Alves
  2021-12-09  5:09 ` Randy Brukardt
@ 2021-12-09  7:26 ` Vadim Godunko
  2021-12-09  7:29 ` Dmitry A. Kazakov
  2 siblings, 0 replies; 7+ messages in thread
From: Vadim Godunko @ 2021-12-09  7:26 UTC (permalink / raw)


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

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: How to call a Windows executable from Ada?
  2021-12-08 23:04 How to call a Windows executable from Ada? Marius Amado-Alves
  2021-12-09  5:09 ` Randy Brukardt
  2021-12-09  7:26 ` Vadim Godunko
@ 2021-12-09  7:29 ` Dmitry A. Kazakov
  2021-12-09  9:28   ` Marius Amado-Alves
  2 siblings, 1 reply; 7+ messages in thread
From: Dmitry A. Kazakov @ 2021-12-09  7:29 UTC (permalink / raw)


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

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: How to call a Windows executable from Ada?
  2021-12-09  7:29 ` Dmitry A. Kazakov
@ 2021-12-09  9:28   ` Marius Amado-Alves
  2021-12-09 18:38     ` Dennis Lee Bieber
  2021-12-09 19:27     ` Dmitry A. Kazakov
  0 siblings, 2 replies; 7+ messages in thread
From: Marius Amado-Alves @ 2021-12-09  9:28 UTC (permalink / raw)


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.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: How to call a Windows executable from Ada?
  2021-12-09  9:28   ` Marius Amado-Alves
@ 2021-12-09 18:38     ` Dennis Lee Bieber
  2021-12-09 19:27     ` Dmitry A. Kazakov
  1 sibling, 0 replies; 7+ messages in thread
From: Dennis Lee Bieber @ 2021-12-09 18:38 UTC (permalink / raw)


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/

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: How to call a Windows executable from Ada?
  2021-12-09  9:28   ` Marius Amado-Alves
  2021-12-09 18:38     ` Dennis Lee Bieber
@ 2021-12-09 19:27     ` Dmitry A. Kazakov
  1 sibling, 0 replies; 7+ messages in thread
From: Dmitry A. Kazakov @ 2021-12-09 19:27 UTC (permalink / raw)


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

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2021-12-09 19:27 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-12-08 23:04 How to call a Windows executable from Ada? Marius Amado-Alves
2021-12-09  5:09 ` Randy Brukardt
2021-12-09  7:26 ` Vadim Godunko
2021-12-09  7:29 ` Dmitry A. Kazakov
2021-12-09  9:28   ` Marius Amado-Alves
2021-12-09 18:38     ` Dennis Lee Bieber
2021-12-09 19:27     ` Dmitry A. Kazakov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox