CommandLine args to linux

What is the solution for Linux for " function returns the passed arguments to a Desktop application as a String array"

What is the problem?

Get @Jeremy Cowgar 's Option Parser from here:

https://github.com/jcowgar/xojo-option-parser

It contains a function that will properly return the command line arguments on all platforms, and the classes will let you properly handle them as a bonus.

For linux , the applications can not be invoked with parameters like the console applications.
For windows, i use like this :

[b] if TargetWin32

declare function GetCommandLineW lib "kernel32.dll" () as Ptr
declare function CommandLineToArgvW lib "shell32.dll" (lpCmdLine As Ptr, ByRef pNumArgs As Integer) As Ptr
declare sub LocalFree Lib"kernel32.dll" (p as Ptr)

dim cl as Ptr = GetCommandLineW()
dim n as Integer
dim argList as Ptr = CommandLineToArgvW (cl, n)

for idx as Integer = 0 to ..
  
  dim mb as MemoryBlock = argList.Ptr(idx*4)

  dim len as Integer
  
  while mb.UInt16Valu(len) <> 0
    len = len + 2
  wend
  
  dim s as String = mb.StringValue(0,len)
  
  args.Append s
  
next

[/b]

I would like the solution for linux,
Thanks

You can start your app from the Linux terminal with:

/path/to/MyApp params

I have another application used with my application and that why I want this command line . for windows works very well with the above code . and I need code as above for linux

Please see my earlier post about the Option Parser. The code you seek is there.

What you could do is to use a Console app as launcher that passes the arguments to the main app through IPCSocket, or simply by creating a small text file that the main app will read.

@ Kem Tekinay I still use RB , but not Xojo

Kem Tekinay
your earlier post about the /path/to/MyApp params is interesting
but how to get the parameters on Linux? thanks

The code you need is in the project I mentioned. I’m not in a position to copy and paste it, but you can download it, open it, and copy what you need, even in the latest RB. The classes themselves may even work in the latest RB, but I don’t think we ever tested that.

 Shared Function CommandLineArgs() As String()
  // Return an array of command-line arguments
  
  const kDebugDeclares = false
  
  dim args() as string
  
  #if DebugBuild and not kDebugDeclares then 
    //
    // Not perfect, but will emulate what you'll get in the built app
    //
    
    args = ParseStringValue(System.CommandLine)
    
  #elseif TargetMacOS then
    const kCocoaLib = "Cocoa.framework"
    
    declare function NSClassFromString lib kCocoaLib (aClassName as CFStringRef) as Ptr
    declare function defaultCenter lib kCocoaLib selector "processInfo" (class_id as Ptr) as Ptr
    declare function arguments lib kCocoaLib selector "arguments" (obj_id as Ptr) as Ptr
    declare function m_count lib kCocoaLib selector "count" (obj as Ptr) as UInteger
    declare function objectAtIndex lib kCocoaLib selector "objectAtIndex:" (theArray as Ptr, idx as Integer) as CFStringRef
    
    static c as Ptr = defaultCenter(NSClassFromString("NSProcessInfo"))
    dim nsArrayRef as Ptr = arguments(c)
    dim ub as integer = m_count(nsArrayRef) - 1
    for i as integer = 0 to ub
      dim s as string = objectAtIndex(nsArrayRef, i)
      args.Append s
    next
    
  #elseif TargetWin32 then
    //
    // Windows and Linux code from Thomas Tempelmann
    //
    
    declare function GetCommandLineW lib "kernel32.dll" () as Ptr
    declare function CommandLineToArgvW lib "shell32.dll" (lpCmdLine As Ptr, ByRef pNumArgs As Integer) As Ptr
    declare sub LocalFree Lib "kernel32.dll" (p as Ptr)
    
    dim cl as Ptr = GetCommandLineW()
    dim n as Integer
    dim argList as Ptr = CommandLineToArgvW (cl, n)
    for idx as Integer = 0 to n-1
      dim mb as MemoryBlock = argList.Ptr(idx*4)
      // mb points to a UTF16 0-terminated string. It seems we have to scan its length ourselves now.
      dim len as Integer
      while mb.UInt16Value(len) <> 0
        len = len + 2
      wend
      dim s as String = mb.StringValue(0,len).DefineEncoding(Encodings.UTF16)
      s = s.ConvertEncoding(Encodings.UTF8)
      args.Append s
    next
    LocalFree(argList)
    
  #elseif TargetLinux then
    // read from "/proc/self/cmdline", each item is 0-terminated
    
    const SystemLib = "libc.so"
    declare function open lib SystemLib (path as CString, flags as Integer) As Integer
    declare function read lib SystemLib (fd as Integer, data as Ptr, n as Integer) as Integer
    
    // first, read the entire cmdline into a string
    dim fd as Integer = open ("/proc/self/cmdline", 0)
    dim s as String
    do
      dim mb as new MemoryBlock(1000)
      dim n as Integer = read (fd, mb, mb.Size)
      s = s + mb.StringValue (0, n)
      if n < mb.Size then exit
    loop
    args = s.Split(Chr(0))
    call args.Pop // remove last array item because of extra 00 byte at end of string
    
    for i as integer = 0 to args.Ubound
      dim thisArg as string = args(i)
      if Encodings.UTF8.IsValidData(thisArg) then
        args(i) = thisArg.DefineEncoding(Encodings.UTF8)
      else
        args(i) = thisArg.DefineEncoding(Encodings.ISOLatin1)
      end if
    next
    
  #endif
  
  return args
End Function

Kem Tekinay

I’ll test it. thanks a lot, see you

Except System.CommandLine only gives you the raw string without quotes. If you start your app with something like this:

myapp —display ‘this is some —text’

System.CommandLine would contain “—display this is some —text”, and that’s essentially useless.

OK

Seems like that’s the linux shell resolving things on the command line. Try escaping the quotes?

[quote=202076:@Kem Tekinay]Except System.CommandLine only gives you the raw string without quotes. If you start your app with something like this:

myapp —display ‘this is some —text’

System.CommandLine would contain “—display this is some —text”, and that’s essentially useless.[/quote]

Under Linux Mint, I get the app path and then

 —display 'this is some —text'

Looks to me extremely easy to parse. But I don’t know, maybe I should change glasses…

This is in a compiled app? It’s different in the debug build.

Indeed the quotes disappear in the build.

Should not a bug report be filed ?