Page 1 of 1
RunProgram Java tool multiple times in the same instance
Posted: Sat Sep 05, 2020 6:02 pm
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)
Re: RunProgram Java tool multiple times in the same instance
Posted: Sat Sep 05, 2020 6:06 pm
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.
Re: RunProgram Java tool multiple times in the same instance
Posted: Sat Sep 05, 2020 6:16 pm
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?
Re: RunProgram Java tool multiple times in the same instance
Posted: Sat Sep 05, 2020 6:32 pm
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.
Re: RunProgram Java tool multiple times in the same instance
Posted: Sat Sep 05, 2020 6:35 pm
by THCM
The program is open the whole time.
Re: RunProgram Java tool multiple times in the same instance
Posted: Sat Sep 05, 2020 7:20 pm
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.
Re: RunProgram Java tool multiple times in the same instance
Posted: Sat Sep 05, 2020 8:58 pm
by oreopa
Nice to see THCM using PB! And kinda hoping this is C64 related
MDG forever! <3 *tips hat*
Re: RunProgram Java tool multiple times in the same instance
Posted: Sat Sep 05, 2020 9:45 pm
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!
Re: RunProgram Java tool multiple times in the same instance
Posted: Tue Sep 15, 2020 3:49 pm
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?
Re: RunProgram Java tool multiple times in the same instance
Posted: Thu Sep 17, 2020 9:28 am
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!
Re: RunProgram Java tool multiple times in the same instance
Posted: Thu Sep 17, 2020 10:44 am
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
Re: RunProgram Java tool multiple times in the same instance
Posted: Sat Oct 03, 2020 1:05 pm
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
Re: RunProgram Java tool multiple times in the same instance
Posted: Sat Oct 03, 2020 1:18 pm
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?
Re: RunProgram Java tool multiple times in the same instance
Posted: Sat Oct 03, 2020 1:51 pm
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