RunProgram Java tool multiple times in the same instance

Just starting out? Need help? Post your questions and find answers here.
THCM
Enthusiast
Enthusiast
Posts: 276
Joined: Fri Apr 25, 2003 5:06 pm
Location: Gummersbach - Germany
Contact:

RunProgram Java tool multiple times in the same instance

Post by THCM »

Hi, I'm running a Java tool to convert data multiple times from my Purebasic app. When I run the Java tool from the windows shell only the first run is quite slow (more than 10 seconds). All following runs in the same shell window are a lot faster, running nearly instant. Running the Java tool from PureBasic using RunProgam every run is slow. There seems to be some caching in the background from Windows or Java which gets lost when using RunProgram. Any ideas how to overcome this?

Code: Select all

JavaParameter.s = "-cp " + Chr(34) + GetCurrentDirectory() + "javamod.jar" + Chr(34) + " de.quippy.javamod.converter.Converter " + Chr(34) + ModFile.s + Chr(34) + " -o:" + Chr(34) + WorkingDir.s + "thc_channel" + Chr(34)
Java = RunProgram("Java.exe", JavaParameter.s, GetCurrentDirectory(), #PB_Program_Open|#PB_Program_Read|#PB_Program_Hide)
The Human Code Machine / Masters' Design Group
DarkDragon
Addict
Addict
Posts: 2344
Joined: Mon Jun 02, 2003 9:16 am
Location: Germany
Contact:

Re: RunProgram Java tool multiple times in the same instance

Post by DarkDragon »

Simple solution: you could create a cmd.exe process, keep it always running in the background and run the java application by writing the corresponding command into the command prompt.
bye,
Daniel
THCM
Enthusiast
Enthusiast
Posts: 276
Joined: Fri Apr 25, 2003 5:06 pm
Location: Gummersbach - Germany
Contact:

Re: RunProgram Java tool multiple times in the same instance

Post by THCM »

I thought about using OpenConsole, but I wasn't sure if this works from a windows gui app. Your suggestion would be using RunProgram with cmd.exe and sending my commands using WriteProgramStringN?
The Human Code Machine / Masters' Design Group
#NULL
Addict
Addict
Posts: 1497
Joined: Thu Aug 30, 2007 11:54 pm
Location: right here

Re: RunProgram Java tool multiple times in the same instance

Post by #NULL »

Did you try if multiple calls of RunProgram within one instance of your PB program makes any difference? I don't know but I would check that first.
THCM
Enthusiast
Enthusiast
Posts: 276
Joined: Fri Apr 25, 2003 5:06 pm
Location: Gummersbach - Germany
Contact:

Re: RunProgram Java tool multiple times in the same instance

Post by THCM »

The program is open the whole time.
The Human Code Machine / Masters' Design Group
DarkDragon
Addict
Addict
Posts: 2344
Joined: Mon Jun 02, 2003 9:16 am
Location: Germany
Contact:

Re: RunProgram Java tool multiple times in the same instance

Post by DarkDragon »

THCM wrote:I thought about using OpenConsole, but I wasn't sure if this works from a windows gui app. Your suggestion would be using RunProgram with cmd.exe and sending my commands using WriteProgramStringN?
Exactly that's what I meant.
bye,
Daniel
User avatar
oreopa
Enthusiast
Enthusiast
Posts: 283
Joined: Sat Jun 24, 2006 3:29 am
Location: Edinburgh, Scotland.

Re: RunProgram Java tool multiple times in the same instance

Post by oreopa »

Nice to see THCM using PB! And kinda hoping this is C64 related ;)

MDG forever! <3 *tips hat*
Proud supporter of PB! * Musician * C64/6502 Freak
THCM
Enthusiast
Enthusiast
Posts: 276
Joined: Fri Apr 25, 2003 5:06 pm
Location: Gummersbach - Germany
Contact:

Re: RunProgram Java tool multiple times in the same instance

Post by THCM »

oreopa wrote:Nice to see THCM using PB! And kinda hoping this is C64 related ;)

MDG forever! <3 *tips hat*
Yes, I‘m using Purebasic for more than 17 years now, but only from time to time and mainly for small tools generating c64 demostuff. Still WIP is my THCMod Protracker Converter written in Purebasic and I‘ve converted my game Orb to Purebasic, but I have to adapt the code from PB 3.93 to the current build. Thx for the help!
The Human Code Machine / Masters' Design Group
THCM
Enthusiast
Enthusiast
Posts: 276
Joined: Fri Apr 25, 2003 5:06 pm
Location: Gummersbach - Germany
Contact:

Re: RunProgram Java tool multiple times in the same instance

Post by THCM »

I did some tests and can't get it work as I wanted:

Code: Select all

If OpenWindow(0, 320, 320, 422, 250, "DOS-Output", #PB_Window_SystemMenu)
 
  EditorGadget(0, 8, 8, 406, 233)
 
    DOS = RunProgram(GetEnvironmentVariable("comspec"), "/k", "", #PB_Program_Open | #PB_Program_Read | #PB_Program_Write )
 
  If DOS
    Output.s = ""
    
       WriteProgramStringN(DOS,"dir c:")
    
      While  AvailableProgramOutput(DOS)
        Output.s + ReadProgramString(DOS) + Chr(13)
      Wend
      
    CloseProgram(DOS)
    AddGadgetItem(0, -1, Output.s)
  EndIf
 
  Repeat 
  Until WaitWindowEvent() = #PB_Event_CloseWindow
 
It looks like WriteProgramStringN doesn't exectute the dir command in the cmd window. It works when I directly send the dir command:

Code: Select all

DOS = RunProgram(GetEnvironmentVariable("comspec"), "dir c: /k", "", #PB_Program_Open | #PB_Program_Read | #PB_Program_Write )
 
But I need to send a command more than once. What am I doing wrong?
The Human Code Machine / Masters' Design Group
ZX80
Enthusiast
Enthusiast
Posts: 361
Joined: Mon Dec 12, 2016 1:37 pm

Re: RunProgram Java tool multiple times in the same instance

Post by ZX80 »

Hi, THCM.

Hope this wonderful code will help you (by JHPJHP):

Code: Select all

#SystemProcessInformation = 5

Structure UNICODE_STRING Align #PB_Structure_AlignC
  Length.w
  MaximumLength.w
  Buffer.i
EndStructure

Structure VM_COUNTERS
  PeakVirtualSize.l
  VirtualSize.l
  PageFaultCount.l
  PeakWorkingSetSize.l
  WorkingSetSize.l
  QuotaPeakPagedPoolUsage.l
  QuotaPagedPoolUsage.l
  QuotaPeakNonPagedPoolUsage.l
  QuotaNonPagedPoolUsage.l
  PagefileUsage.l
  PeakPagefileUsage.l
EndStructure

Structure IO_COUNTERS
  ReadOperationCount.LARGE_INTEGER
  WriteOperationCount.LARGE_INTEGER
  OtherOperationCount.LARGE_INTEGER
  ReadTransferCount.LARGE_INTEGER
  WriteTransferCount.LARGE_INTEGER
  OtherTransferCount.LARGE_INTEGER
EndStructure

Structure SYSTEM_THREAD
  KernelTime.LARGE_INTEGER
  UserTime.LARGE_INTEGER
  CreateTime.LARGE_INTEGER
  WaitTime.l
  StartAddress.l
  UniqueProcess.l
  UniqueThread.l
  Priority.l
  BasePriority.l
  ContextSwitchCount.l
  State.l
  WaitReason.l
  Reserved1.l
EndStructure

Structure SYSTEM_PROCESS_INFORMATION
  NextEntryOffset.l
  NumberOfThreads.l
  Reserved1.LARGE_INTEGER[3]
  CreateTime.LARGE_INTEGER
  UserTime.LARGE_INTEGER
  KernelTime.LARGE_INTEGER
  ModuleName.UNICODE_STRING
  BasePriority.i
  ProcessID.l
  InheritedFromProcessId.l
  HandleCount.l
  Reserved2.l[2]
  VirtualMemoryCounters.VM_COUNTERS
  PrivatePageCount.l
  IOCounters.IO_COUNTERS
  ThreadInfo.SYSTEM_THREAD[0]
EndStructure

Prototype protoAttachConsole(dwProcessId)

Procedure cmdGetProcessId(ModuleName.s)
  *spi.SYSTEM_PROCESS_INFORMATION
  *spi = AllocateMemory(1024 * 1024)
  NtQuerySystemInformation_(#SystemProcessInformation, *spi, MemorySize(*spi), #Null)
  *spi\ModuleName\Buffer = AllocateMemory(#MAX_PATH)

  While *spi\NextEntryOffset
    If LCase(PeekS(*spi\ModuleName\Buffer, *spi\ModuleName\Length, #PB_Unicode)) = ModuleName
      dwProcessId = *spi\ProcessID : Break
    Else
      *spi + *spi\NextEntryOffset
    EndIf
  Wend
  ProcedureReturn dwProcessId
EndProcedure

Procedure.l cmdOpenConsole(dwProcessId)
  Protected AttachConsole.protoAttachConsole

  kernel32 = OpenLibrary(#PB_Any, "kernel32.dll")

  If IsLibrary(kernel32)
    AttachConsole = GetFunction(kernel32, "AttachConsole")

    If AttachConsole(dwProcessId) : hStdInput.l = GetStdHandle_(#STD_INPUT_HANDLE) : EndIf

    CloseLibrary(kernel32)
  EndIf
  ProcedureReturn hStdInput
EndProcedure

Procedure cmdAddAlias(Source.s, Target.s)
  ProcedureReturn AddConsoleAlias_(Source, Target, "cmd.exe")
EndProcedure

Procedure cmdRunScript(hStdInput.l, ScriptText.s, RunAndWait = #False)
  ScriptText + Chr(13)
  nLength = Len(ScriptText) + 1

  If nLength > 1
    Dim lpBuffer.INPUT_RECORD(nLength)

    For rtnCount = 0 To nLength - 2
      ascKey = Asc(Mid(ScriptText, rtnCount + 1, 1))
      vkKey = VkKeyScanEx_(ascKey, GetKeyboardLayout_(0)) & $FF
      lpBuffer(rtnCount)\EventType = #KEY_EVENT
      lpBuffer(rtnCount)\Event\KeyEvent\bKeyDown = #True
      lpBuffer(rtnCount)\Event\KeyEvent\dwControlKeyState = 0
      lpBuffer(rtnCount)\Event\KeyEvent\uChar = ascKey
      lpBuffer(rtnCount)\Event\KeyEvent\wRepeatCount = 1
      lpBuffer(rtnCount)\Event\KeyEvent\wVirtualKeyCode = vkKey
      lpBuffer(rtnCount)\Event\KeyEvent\wVirtualScanCode = MapVirtualKey_(vkKey, 0)
    Next
    lpBuffer(nLength - 1)\EventType = #KEY_EVENT
    lpBuffer(nLength - 1)\Event\KeyEvent\bKeyDown = #True
    lpBuffer(nLength - 1)\Event\KeyEvent\dwControlKeyState = 0
    lpBuffer(nLength - 1)\Event\KeyEvent\uChar = #VK_RETURN
    lpBuffer(nLength - 1)\Event\KeyEvent\wRepeatCount = 1
    lpBuffer(nLength - 1)\Event\KeyEvent\wVirtualKeyCode = #VK_RETURN
    lpBuffer(nLength - 1)\Event\KeyEvent\wVirtualScanCode = MapVirtualKey_(#VK_RETURN, 0)
    WriteConsoleInput_(hStdInput, @lpBuffer(), nLength, @lpNumberOfCharsWritten)

    If RunAndWait
      Repeat
        Result = WaitForSingleObject_(hStdInput, 100)

        Select Result
          Case #WAIT_ABANDONED : Break
          Case #WAIT_OBJECT_0 : Delay(100)
          Case #WAIT_TIMEOUT : Break
          Case #WAIT_FAILED : Break
        EndSelect
      ForEver
    EndIf
  EndIf
EndProcedure

dwProcessId = cmdGetProcessId("cmd.exe")

If Not dwProcessId : RunProgram("cmd") : Delay(200) : dwProcessId = cmdGetProcessId("cmd.exe") : EndIf

If dwProcessId
  hStdInput.l = cmdOpenConsole(dwProcessId)

  If hStdInput
    con = FindWindow_("ConsoleWindowClass",0)
    SetForegroundWindow_(con)
    Sleep_(1000)
    If cmdAddAlias(".", "cls&&cd c:\&&dir c:") : cmdRunScript(hStdInput, ".") : EndIf
    Sleep_(1000)
    If cmdAddAlias(".", "cd d:\&&dir d:") : cmdRunScript(hStdInput, ".") : EndIf
  EndIf
EndIf
[/size]
Note: replace "." with non-printable/invisible character if it's critical.

------------------------
Or use this:

Code: Select all

ImportC "msvcrt.lib"
  system(str.p-ascii)
EndImport

OpenConsole()
system("cd c:\&&dir c:")
system("dir d:")
Input()
[/size]
Good luck!
infratec
Always Here
Always Here
Posts: 7576
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: RunProgram Java tool multiple times in the same instance

Post by infratec »

You made one big mistake:

The command needs time to be executed. You simply closed the program until the result was ready.

Code: Select all

Define DOS.i, Output$, Timeout.i

If OpenWindow(0, 320, 320, 422, 250, "DOS-Output", #PB_Window_SystemMenu)
  
  EditorGadget(0, 8, 8, 406, 233)
  
  DOS = RunProgram("cmd", "/k", "", #PB_Program_Open | #PB_Program_Read | #PB_Program_Write )
  If DOS
    
    *Buffer = AllocateMemory(1024, #PB_Memory_NoClear)
    If *Buffer
      
      WriteProgramStringN(DOS, "dir c:")
      
      Timeout = 10
      Repeat
        
        Len = AvailableProgramOutput(DOS)
        If Len
          Len = ReadProgramData(DOS, *Buffer, Len)
          If Len
            Output$ + PeekS(*Buffer, Len, #PB_UTF8|#PB_ByteLength) + #LF$
          EndIf
          
        EndIf
        
        Delay(100)
        
        Timeout - 1
        
      Until Timeout = 0
      FreeMemory(*Buffer)
    EndIf
    
    CloseProgram(DOS)
    AddGadgetItem(0, -1, Output$)
  EndIf
  
  Repeat
  Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
THCM
Enthusiast
Enthusiast
Posts: 276
Joined: Fri Apr 25, 2003 5:06 pm
Location: Gummersbach - Germany
Contact:

Re: RunProgram Java tool multiple times in the same instance

Post by THCM »

I tried your example and it works if the execution time is short enough for the selected delay, but how can I check if the called program is finished? The exectution time ist more than a few seconds and differs a lot from PC to PC and the selected conversion data I called.
infratec wrote:You made one big mistake:

The command needs time to be executed. You simply closed the program until the result was ready.

Code: Select all

Define DOS.i, Output$, Timeout.i

If OpenWindow(0, 320, 320, 422, 250, "DOS-Output", #PB_Window_SystemMenu)
  
  EditorGadget(0, 8, 8, 406, 233)
  
  DOS = RunProgram("cmd", "/k", "", #PB_Program_Open | #PB_Program_Read | #PB_Program_Write )
  If DOS
    
    *Buffer = AllocateMemory(1024, #PB_Memory_NoClear)
    If *Buffer
      
      WriteProgramStringN(DOS, "dir c:")
      
      Timeout = 10
      Repeat
        
        Len = AvailableProgramOutput(DOS)
        If Len
          Len = ReadProgramData(DOS, *Buffer, Len)
          If Len
            Output$ + PeekS(*Buffer, Len, #PB_UTF8|#PB_ByteLength) + #LF$
          EndIf
          
        EndIf
        
        Delay(100)
        
        Timeout - 1
        
      Until Timeout = 0
      FreeMemory(*Buffer)
    EndIf
    
    CloseProgram(DOS)
    AddGadgetItem(0, -1, Output$)
  EndIf
  
  Repeat
  Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
The Human Code Machine / Masters' Design Group
THCM
Enthusiast
Enthusiast
Posts: 276
Joined: Fri Apr 25, 2003 5:06 pm
Location: Gummersbach - Germany
Contact:

Re: RunProgram Java tool multiple times in the same instance

Post by THCM »

@ZX80 Both of your examples seem to work. Is it possible to open a hidden console window? Does it close automatically after exiting the purebasic app?
The Human Code Machine / Masters' Design Group
User avatar
mk-soft
Always Here
Always Here
Posts: 6202
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: RunProgram Java tool multiple times in the same instance

Post by mk-soft »

I don't know if you can call Java Tools (.jar) from JavaScript (Script).

If so, try ActiveScript.
Don't reinitialize every time (NewActiveScript), but create a java function and call it as needed. So you don't have to recompile everything every time.

Code: Select all

XIncludeFile "Modul_ActiveScript.pb"

UseModule ActiveScript

Define js.s, Message.s
Runtime Message
Message = "Hello World"

js = ~"var shell = new ActiveXObject(\"WScript.Shell\");" + #LF$
js + ~"var msg = Runtime.String(\"Message\");" + #LF$
js + ~"shell.Popup(msg);" + #LF$

Debug "*** New ActiveScript ***"
*Control = NewActiveScript("JScript")
If *Control
  Debug "*** Parse ScriptText ***"
  r1 = ParseScriptText(*Control, js)
  If r1 = #S_OK
    Debug "Code Ready."
  EndIf
  Debug "*** Free ActiveScript ***"
  FreeActiveScript(*Control)
  Debug "*** Finished ActiceScript ***"
EndIf
[/size]

Link: Module ActiveScript
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Post Reply