Running a shell command

I’m trying to run a command line tool from within a Shell in a desktop app. I’m on a Mac.

The tool is definitely installed on my Mac in my PATH. The tool is called rtl_433.

In the macOS Terminal if I run:

which rtl_433

I get:

/opt/homebrew/bin/rtl_433

If I put this code in the Opening event of my app:

Var sh As New Shell
sh.ExecuteMode = Shell.ExecuteModes.Synchronous
sh.Execute("which ls")
Var result As String = sh.Result ' bin/ls

sh.Execute("which rtl_433")
result = sh.Result ' Empty. Shell returns error 1
Break

The Shell can’t find rtl_433. The execute command is working though because it finds the ls tool which is bundled with macOS.

Does anyone have any code that will run a CLI from a Shell? I’m guessing this has something to do with the incorrect PATH in Xojo’s Shell class but I’m not sure how to address it.

1 Like

Call the utility with the complete path.

sh.Execute "/path/to/cli"

And just like that, the problem is solved. Thanks.

Out of interest, any idea why you have to use the full path?

You have to use the full path because the Xojo shell is not the Terminal and therefore doesn’t know the new CLI.

2 Likes

When you log into your account, it gets a lot of information from the environment. When you run a shell script, or run a shell from xojo, you don’t have all that information. Both shell scripts and xojo shells have to be more explicit.

2 Likes

in the terminal, if you run the ‘env’ command you will see the PATH variable. On my machine it’s this long mess:

PATH=/opt/local/bin:/opt/local/sbin:/opt/local/bin:/opt/local/sbin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/Apple/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin

(apparently the Cryptexes and codex stuff is new in Ventura, ugh)

In Xojo if you run this code:

dim sh as new shell
sh.Execute("env")
MessageBox sh.Result

the PATH is quite different:

PATH=/usr/bin:/bin:/usr/sbin:/sbin

2 Likes

FYI, you can use something like this on Mac or Linux to get the path to the utility you want:

Private Function FindCliApp(cli As String) As FolderItem
  dim f as FolderItem
  
  #if TargetMacOS or TargetLinux then
    dim sh as new shell
    sh.Execute "/bin/bash -lc " + ShellQuote("which " + cli.Trim)
    if sh.ErrorCode = 0 then
      dim path as string = sh.Result
      path = ReplaceLineEndings(path, EndOfLine).Trim
      path = path.NthField(EndOfLine, path.CountFields(EndOfLine))
      f = new FolderItem(path, FolderItem.PathTypeNative)
    end if
  #endif
  
  return f
  
End Function

Private Function ShellQuote(s As String) As String
  s = s.ReplaceAll("'", "'\''")
  s = "'" + s + "'"
  return s
  
End Function
2 Likes