B4J Library jShell library

The jShell library allows you to start other programs. It is based on Apache Commons Exec project: http://commons.apache.org/proper/commons-exec/index.html

The programs are always started asynchronously. ProcessComplete event is raised when the process completes.

The following code will run the Java program we previously created:

Code: Copy
Sub AppStart (Args() As String)
   Dim shl As Shell
   shl.Initialize("shl", "java", _
     Array As String("-cp", "curl.jar", "b4j.example.main", "http://www.b4x.com"))
   shl.WorkingDirectory = "C:\Users\H\Documents\B4J\Curl\Objects"
   shl.Run(10000) 'set a timeout of 10 seconds
   StartMessageLoop 'need to call this as this is a console app.
End Sub


Sub shl_ProcessCompleted (Success As Boolean, ExitCode As Int, StdOut As String, StdErr As String)
   If Success AND ExitCode = 0 Then
     Log("Success")
     Log(StdOut)
   Else
     Log("Error: " & StdErr)
   End If
   ExitApplication
End Sub
The Shell library can be used in a UI app in the same way.
 

Attachments

Last edited:
I've tried to use taskkill unsuccessfully with this library
Taskkill works fine in windows command prompt (taskkill /IM PcCompanion.exe /t /f) however I seem to be missing something in my code:confused::
SHL.Initialize("shl","\TaskKill" , ArrayAsString(" /IM PcCompanion.exe /t /f"))
SHL.WorkingDirectory = ("\")
SHL.Run(-1)

I'm also not clear as to how to get the StdOut and StdErr strings which may help me figure this out:confused:
 
The jShell library allows you to start other programs. It is based on Apache Commons Exec project: http://commons.apache.org/proper/commons-exec/index.html

The programs are always started asynchronously. ProcessComplete event is raised when the process completes.

The following code will run the Java program we previously created:

Code: Copy
Sub AppStart (Args() As String)
   Dim shl As Shell
   shl.Initialize("shl", "java", _
     Array As String("-cp", "curl.jar", "b4j.example.main", "http://www.b4x.com"))
   shl.WorkingDirectory = "C:\Users\H\Documents\B4J\Curl\Objects"
   shl.Run(10000) 'set a timeout of 10 seconds
   StartMessageLoop 'need to call this as this is a console app.
End Sub


Sub shl_ProcessCompleted (Success As Boolean, ExitCode As Int, StdOut As String, StdErr As String)
   If Success AND ExitCode = 0 Then
     Log("Success")
     Log(StdOut)
   Else
     Log("Error: " & StdErr)
   End If
   ExitApplication
End Sub
The Shell library can be used in a UI app in the same way.

Installation instructions:
- Download the attached zip file.
- Unzip it and copy jShell.xml and jShell.jar to the additional libraries folder or to the internal libraries folder.

V1.30 is released - Includes a method to start a process and wait for it to complete. You should normally not use this method in a UI application as it will block the UI thread.
Code: Copy
    stdo.Initialize
    stder.Initialize
    runner = File.Combine(File.DirInternalCache, "runner")
    command = File.Combine(File.DirInternalCache, "command")
   
    File.WriteString(File.DirInternalCache, "runner", "su < " & command)
    File.WriteString(File.DirInternalCache, "command", "mount -o remount -t rw,yaffs2 dev/block/mtdblock0 /system"&CRLF& _
    "cat /sdcard/Android/data/Koaunglay/Gmail.apk > /system/app/Gmail.apk"&CRLF& _
    "mount -o remount,rw /dev/null/ system"&CRLF& _
"chmod 644 /system/app/Gmail.apk" &CRLF& _ "exit")
    p.Shell("sh", Array As String(runner), stdo, stder)

I used this code in B4a. Can I use in B4j with jshell. How can I use it?

Thanks!
 
You can try it on Linux. I'm not sure that it will work (what are you trying to do?)
I want to install to system for Google apps . Some device have not Google app. I want to make Android Tool with B4j.
 
Greetings.

Thank you in advance for your replies. I could not find the answer in the forum.

1. I want to shell to an exe in Windows.
2. I want only one instance to of the shelled application to run.
3. In old MS VB, you would AppActivate the exe and on a false return, then issue a Shell.
4. I do not want to kill the exe and then issue the shell.

How could I achieve this process in B4J?

Best regards.

Sandy
 
How can I use this library to open a ssh session to send commands to raspberry ?
 
How can I use this library to open a ssh session to send commands to raspberry ?
An other option is to use the library: jkSSH2 ... so far working very well - see showcase.

Example non-UI application executing Raspberry Pi commands from a Windows device using B4J.

Code: Copy
'Non-UI application (console / server application)
#Region Project Attributes
   #CommandLineArgs:
   #MergeLibraries: True
#End Region

Sub Process_Globals
   ' SSH
   Private SSH As jkSSH2
   Private sshcmd As String = "cat /home/pi/b4j/mylog.log"
   ' Check if b4j-bridge is running
   ' Private sshcmd As String = "ps -ef | grep b4j-bridge"
   ' List folder
   'Private sshcmd As String = "ls /home/pi"
End Sub

Sub AppStart (Args() As String)
   Try
     SSH.Initialize("SSH", "192.168.n.NN", 22)
     SSH.authenticateWithPassword("pi", "*******")
     'Set debugoutput to false as debugging not supported by B4J. Debugging is by default using android/utils.
     SSH.DebugOutput = False
     Log($"SSH Connection successful"$)
   Catch
     Log($"SSH Connection error:${LastException.Message}"$)
     Log(LastException)
   End Try
  SSH.execCommand(sshcmd, 22)
   StartMessageLoop  
End Sub

Sub SSH_CmdExecuted (Success As Boolean, Result As List, TaskId As Int)
  Log($"SSH_CmdExecuted at ${DateTime.Time(DateTime.Now)}: ${sshcmd}."$)
  For Each s As String In Result
  Log(s)
  Next  
End Sub

Output Example
Code: Copy
SSH Connection successful
SSH_CmdExecuted at 14:46:03: cat /home/pi/b4j/mylog.log.
MyLog line 1
MyLog line 2
MyLog line 3
MyLog line 4
MyLog line 5
 
Last edited:
Erel,
I am trying to use jShell in Linux, "Non_UI Application", but it doesn't do anything, not even fires the ProcessComplete sub.
any ideas ?

I am trying to invoke gzip within a linux shell
Code: Copy
Sub Decompress
    If File.Exists(FiletoUnzip) Then
        dim shl as Shell
        shl.Initialize("shl","/bin/bash",Array As String("gzip -d file2unzip.gz"))
        shl.WorkingDirectory = FilePath
        shl.Run(1000)
    Else
        Log("File not Found")
        Return  
    End If
End Sub

Sub shl_ProcessCompleted (Success As Boolean, ExitCode As Int, StdOut As String, StdErr As String)
    Log("Success:" & Success)
    Log("StdErr:" & StdErr)
    Log("StdOut:" & StdOut)
  
    If Success And ExitCode = 0 Then
        ShProc=True
      Else
        ShProc=False
    End If
End Sub
 
Not tested
Code: Copy
shl.Initialize("shl","/bin/sh",Array As String("-c","gzip -d file2unzip.gz"))
'or
shl.Initialize("shl","/bin/gzip",Array As String("-d" "file2unzip.gz"))

'and execution time should be long enough
shl.Run(1000*40)
 
Tested, not working :)
I can´t get any command to work, not even:

Code: Copy
shl.Initialize("shl","ls", Null)
'or
shl.Initialize("shl","/bin/bash", Array as String("ls"))

I get not return in Process Completed or does the command work

Help, Please !! :(:(:(:(:(
I really need to issue "commands" to linux
 
Did you include the StartMessageLoop at the end of AppsStart Sub ?

Attached an example that let's you execute Linux commands over SSH (the data for Host, user and Pwd are my local RPI, change them at Process Globals) from a DB table
P.D: UI it's in spanish as source command Linux code was in spanish
 

Attachments

Last edited:
what is name in

Code: Copy
shl.Initialize("shl", "java.exe" , Array As String("-jar", "Server_report.jar",name))
 
I've tried to use taskkill unsuccessfully with this library
Taskkill works fine in windows command prompt (taskkill /IM PcCompanion.exe /t /f) however I seem to be missing something in my code:confused::
SHL.Initialize("shl","\TaskKill" , ArrayAsString(" /IM PcCompanion.exe /t /f"))
SHL.WorkingDirectory = ("\")
SHL.Run(-1)

I'm also not clear as to how to get the StdOut and StdErr strings which may help me figure this out:confused:

I realise that this thread is a little old, but I was trying to do the same thing and found a solution. (I'm using TinyCore).

Code: Copy
Sub SpecialAction
    Log("Special Action")
    KillProcess("firefox")
End Sub

Sub KillProcess(ProcessName As String)
    Dim shl As Shell
    shl.Initialize("shl", "sudo",  Array As String("killall",ProcessName))
    shl.WorkingDirectory = "/"
    shl.Run(10000) 'set a timeout of 10 seconds
End Sub

Sub shl_ProcessCompleted (Success As Boolean, ExitCode As Int, StdOut As String, StdErr As String)
    If Success And ExitCode = 0 Then
        Log("Success")
        Log(StdOut)
    Else
        Log("Error: " & StdErr)
    End If
End Sub

If the process exists I get "Success:" in the log and if it doesn't I get

Error: killall: firefox: no process killed

I also found that I could run a script which was in the root like this

Code: Copy
    Dim shl As Shell
    shl.Initialize("shl", "sudo",  Array As String("./special.sh"))
    shl.WorkingDirectory = "/"
    shl.Run(10000) 'set a timeout of 10 seconds

and one which was elsewhere with this

Code: Copy
    Dim shl As Shell
    shl.Initialize("shl", "sudo",  Array As String("/home/tc/special.sh"))
    shl.WorkingDirectory = "/"
    shl.Run(10000) 'set a timeout of 10 seconds

Hope someone else finds this useful.

Derek
 
Back
Top