bmitc

bmitc

Hello! I am working on something where I am trying to pass data between .NET, namely F#, and Elixir through the command line. On Windows, I am getting a strange error that I can’t figure out.

Here is my F# function:

let executeProcess name arguments =
    let startInfo = System.Diagnostics.ProcessStartInfo(
        FileName = name,
        Arguments = arguments,
        UseShellExecute = false,
        RedirectStandardError = true,
        RedirectStandardOutput = true
    )
    use p = new System.Diagnostics.Process(StartInfo = startInfo)
    p.Start() |> printfn "Successfull?: %A"
    p.WaitForExit()
    p.StandardOutput.ReadToEnd()

On Ubuntu, this works without issue (you can try by copy and pasting this into a dotnet fsi session after downloading the latest .NET SDK or you can try it in a Polyglot Notebook in VS Code, which requires no install I believe as it installs F# for you):

$ dotnet fsi

Microsoft (R) F# Interactive version 12.4.0.0 for F# 7.0
Copyright (c) Microsoft Corporation. All Rights Reserved.

For help type #help;;

> <copy and paste above function>;;
val executeProcess: name: string -> arguments: string -> string

> executeProcess "dotnet" "--version";;
Successfull?: true
val it: string = "7.0.101
"

> executeProcess "elixir" "--version";;
Successfull?: true
val it: string =
  "Erlang/OTP 25 [erts-13.1.4] [source] [64-bit] [smp:20:20] [ds:20:20:10] [async-threads:1] [jit:ns]

Elixir 1.14.3 (compiled with Erlang/OTP 25)
"

>

However, on Windows, I get a strange Erlang init error but notice that Elixir works just fine on the command line:

PS > elixir.bat --version
Erlang/OTP 25 [erts-13.0.4] [source] [64-bit] [smp:20:20] [ds:20:20:10] [async-threads:1] [jit:ns]

Elixir 1.14.2 (compiled with Erlang/OTP 25)
PS > dotnet fsi

Microsoft (R) F# Interactive version 12.8.0.0 for F# 8.0
Copyright (c) Microsoft Corporation. All Rights Reserved.

For help type #help;;

> <copy and paste above command>;;
val executeProcess: name: string -> arguments: string -> string

> executeProcess "dotnet" "--version";;
Successfull?: true
val it: string = "8.0.100-preview.6.23330.14
"

> executeProcess "elixir.bat" "--version";;
Successfull?: true
val it: string =
  "{"init terminating in do_boot",{undef,[{elixir,start_cli,[],[]},{init,start_em,1,[{file,"init.erl"},{line,1220}]},{init,do_boot,3,[{file,"init.erl"},{line,910}]}]}}
"

This is where I get this weird error of {"init terminating in do_boot",{undef,[{elixir,start_cli,[],[]},{init,start_em,1,[{file,"init.erl"},{line,1220}]},{init,do_boot,3,[{file,"init.erl"},{line,910}]}]}}. Searching and even looking up the line numbers in init.erl, this error seems to be because of Erlang version issues. However, that is not an issue on my machine. Elixir and Erlang via iex and erl work just fine, as does elixir.bat --version from the command line.

There seems to be something in how the .NET process launcher is interacting with the Elixir.bat that one or the other doesn’t like. Does anyone know what’s going on here? Is this an issue with elixir.bat on Windows?

(Note: There is a workaround, and it is to actually make the filename "powershell" with arguments "elixir --version". However, I don’t know why that works and the other doesn’t. The Elixir binaries/scripts are in my path, as are the Erlang binaries.)


Edit: I went ahead and tried this on the latest versions of Elixir 1.15.4 and Erlang/OTP 26. The Erlang "init terminated in do_boot" error seems to have gone away, but nothing is written to standard out when running this code as above. However, if I remove the redirection from standard out and reading, I get the following error in FSI:

> let executeProcess name arguments =
-     let startInfo = System.Diagnostics.ProcessStartInfo(
-         FileName = name,
-         Arguments = arguments
-     )
-     use p = new System.Diagnostics.Process(StartInfo = startInfo)
-     p.Start() |> printfn "Successfull?: %A"
- ;;
val executeProcess: name: string -> arguments: string -> unit

> executeProcess "elixir.bat" "--version";;
Successfull?: true
val it: unit = ()

> Error! Failed to load module 'elixir' because it cannot be found. Make sure that the module name is correct and
that its .beam file is in the code path.

Runtime terminating during boot ({undef,[{init,start_it,1,[{_},{_}]},{init,start_em,1,[{_},{_}]},{init,do_boot,3,[{_},{_}]}]})

Crash dump is being written to: erl_crash.dump...done

Showing Posts 1 to 7

lud

lud

Did you install elixir from something that requires some environment from your shell, like asdf for instance?

bmitc

bmitc OP

The issue appears on Windows, where I installed Erlang and Elixir via the official Windows installers, and asdf is not supported on Windows. I use asdf on Ubuntu, but this works fine there.

This has to somehow be related to how on Windows, Elixir is wrapped via scripts, and one isn’t calling binaries directly. But it’s strange how it works fine on the command line. I’m not sure there’s much else I would need to or can do on the .NET side.

cmo

cmo

I believe you’re right about this. You could call erl.exe with the args that the batch script passes to it.

I presume you don’t want to flip things and have elixir call F# via a port, because that’s not too hard. There is an ETF library in F#.

bmitc

bmitc OP

I presume you don’t want to flip things and have elixir call F# via a port, because that’s not too hard. There is an ETF library in F#.

Haha. :slight_smile: The context of my question is actually to help test and verify an encoding/decoding library I wrote myself in F# for the Erlang External Term Format. My main goal is playing around with some ideas around an Elixir Port and F# interaction, and so I wrote my own ETF library in F# since it’s not too hard and gives me control when integrating it into the port abstraction. This question is to help test the F# encoding/decoding across the various OS platforms using both regular tests and property-based tests. The example function I gave is similar to the real one, which is used in tests to write out a string to Elixir, have Elixir convert it to an Erlang term, then F# decodes it and tests it against what’s expected. Something like this:

[<Fact>]
let ``Decode tuple from stream`` () =
    @"{:ok, :another}" |> writeAndDecode |> should equal (ErlangTerm.Tuple [ErlangTerm.Atom "ok"; ErlangTerm.Atom "another"])

Calling elixir.bat --version as an argument to the powershell command works, but it isn’t entirely clear to me why that works but calling the script directly doesn’t work. Mainly trying to know why to further my understanding of how both Elixir and F# interact with the command line. It also seems like an issue with the Erlang crash dump when simply calling elixir.bat --version.

cmo

cmo

Very well. You do have to think about passing env vars on to child/sub processes, something I discovered when playing with porting elixir.bat to a Zig executable.

ETF library has caused me no issues other than the poor choice of namespaces.

bmitc

bmitc OP

You do have to think about passing env vars on to child/sub processes

It’s possible that that’s what PowerShell is doing properly when I use powershell elixir.bat --version. I have no idea though.

ETF library has caused me no issues other than the poor choice of namespaces.

Which ETF F# library are you using? Last time I checked there were a couple, including one for the BERT term format. My library just does a subset of the base ETF format, since some of them don’t make sense in the context I am thinking of. The encoding/decoding is rather easy, so I’ll probably keep my own, but it would be nice to see other implementations, especially if they’ve been kept up to date.

cmo

cmo

https://github.com/erpuno/etf

After setting things up, I loop over this:

// reply ok on startup
    sendOk (encode "0")
    try
        while true do
            inputBufferSize <- stdin.Read(inputBuffer, 0, 4)
            // input buffer should be size 4, which tells us the size of the message
            match inputBufferSize with
            | 4 -> ()
            | 0 ->
                logger.Debug "Port shutdown, exiting"
                cleanup logger connection
                Environment.Exit(int ReturnCode.Ok)
            | size ->
                logger.Error $"Expected 4 bytes, got {size} containing '{Encoding.UTF8.GetString(inputBuffer)}'"
                cleanup logger connection
                Environment.Exit(int ReturnCode.BadMessageSize)
                
            let msgSizeBytes =
                if BitConverter.IsLittleEndian
                then inputBuffer |> Array.take 4 |> Array.rev
                else inputBuffer |> Array.take 4
            let msgSize = BitConverter.ToInt32(msgSizeBytes, 0)
            
            // read the ETF
            inputBufferSize <- stdin.Read(inputBuffer, 0, msgSize)
            
            // decode the ETF
            let term = ETF.Decoder.decodeTerm inputBuffer
            
            match term with
            | Term.Tuple [Term.Binary requestId; msg] ->
                match decodeMessage msg with
                | SomeMessage(arg1, arg2) -> 
                ...
— All posts loaded —

Where Next? Top

Trending in Questions Top

katta
I having some trouble figuring out if I have set myself too strict of standards for my production server. Currently I can handle 75% of r...
New
peck
Hi everyone. My team and I have been working on a fairly modest app based around video streaming and chat, but we’ve landed a customer t...
New
achenet
Hello, I’m trying to build a basic Phoenix web-app, and I’d like to use Tailwind. However, when I launch mix phx.server, I get an error...
New
bradley
I really like the adapter patterns that ecto, nebulex, waffle, etc. use and would love find something similar for a key management servic...
New
unaware8150
Hello folks! So at work, we are seeing some situations where we have to define some “fixed” strings that are used across the codebase in...
New
Cxx-mlr
I’m working on a small exercise involving update_in/3, and I came up with this solution: data = %{ name: "Periodic Table", category:...
New
Alvinkariuki
How Can I Optimise Compile Time Dependencies I have been building an elixir application for about 2 years now. Many modules and files ha...
New

Other Trending Topics Top

GenericJam
Edit: 2026 May 15 - This post is archived. Mob is alive!! Main docs: mob v0.7.11 — Documentation A bit of explanation for the slightly c...
New
budgie
A little off-topic, but I feel like people here have a good head on their shoulders. I used to be quite good at making software. Was luc...
New
KristerV
Hey. Is there anyone here who creates agents in their apps? Not talking about using agents, but creating them. I’m finding it pretty diff...
New
mudasobwa
I fully migrated to my own harness from Anthropic/Gemini and I think it’s time to share it. Welcome DSH, the DeepSeek Harness, fully writ...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
mcass19
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews