Script "Execution"

Just starting out? Need help? Post your questions and find answers here.
Phollyer
Enthusiast
Enthusiast
Posts: 143
Joined: Sat Jun 03, 2017 3:36 am
Location: USA, Texas
Contact:

Script "Execution"

Post by Phollyer »

I fear the answer to my question is not the one I want to read...but, as you man know, I'm putting a GUI Front end onto the Auto-It DLL project; and It's almost complete. And last night I had a thought, I want to Execute the Script on the fly from the GUI Project using a separate thread.

My Idea is to Launch a PureBasic EXE and use a command line Parameter to pass the script via a Temporary File.

Inside this EXE it opens to file parses the individual script lines, so here is the question: is there some magical way to execute these lines of code?

Here's the code so far....

Code: Select all

Procedure CheckCmdLineParms()
  Protected X, K, Result, CmdLine$, Path$, Name$, Script$, Format
  
  Result = CountProgramParameters()
  If Result = 1
    NewList ScriptLine.s()
    CmdLine$ = ProgramParameter(0)
    Path$ = GetPathPart(CmdLine$)
    Name$ = GetFilePart(CmdLine$)
    
    If FileSize(CmdLine$) > 1
      OpenFile(6, CmdLine$)
      Format = ReadStringFormat(0)
      While Eof(6) = 0
        Script$ = ReadString(6, Format)
      Wend
      CloseFile(6)   
    EndIf
    
    K = CountString(Script$, #LF$)
    For X = 1 To K+1
      AddElement(ScriptLine())
      ScriptLine() = StringField(Script$, X, #LF$)
    Next
    
    
    FreeList(ScriptLine())
  EndIf
EndProcedure
Here is a sample Script

Code: Select all

AUTOIT::Run("C:\Windows\System32\notepad.exe", "C:\Windows\System32\", 1) 
AUTOIT::WinWait("Untitled - Notepad", "")
Delay(2000)

AUTOIT::AutoItSetOption("MouseCoordMode", 0) 
Delay(500)

AUTOIT::MouseClick("left", 614, 50, 1)
Delay(500)

AUTOIT::MouseClick("left", 16, 14, 1)
Delay(500)
My thought was to Parse Each Line at the Open Parenthesis "(" using the Left half in an ugly massive IF Left$="AUTOIT::RUN" then parse the right half into their parameters....oh but that hurts just thinking about it, there are a possible 125 or so commands and 3X that in Parameters.

I've also considered using the code which generates the script to alternatively execute it...which would be considerably easier than the other option...BUT then I'm NOT really running or testing the script

A third option would be to Generate code and insert code into a pre-created PureBasic project. And then launch the PB Compiler to Compile and execute the script, then run a cleanup step resetting the project back to Zero ready for next test. This has my current vote, but it's a lot of moving parts, and a lot of "stuff" to laydown with an install, where it can be modified, compiled, and executed...could be problematic with virus protection and permissions

In the old days, FoxPro had a parameter to add to a variable containing code to execute it! Java code can be retrieved from DB Queries and executed. I don't suppose PureBasic has a similar feature?

It's just a pain to continuously jump between the Script Creator and the Script Runner, even if it IS the safest answer...

--------------------------------------------------------

After further work on this, See code. This compiles. it May be "A" Solution.
It allows for up to 10 Fields/Parameters...It's just going to be one huge If..ElseIf......EndIf

Code: Select all


;========================================================
;====           AutoItX Script Testing
;====
;====  Author: Pete Hollyer
;====
;====   Notes: If EXE is called with CMDLine of Script
;====   Run Script
;====
;========================================================

Procedure ParseParams(Vars$, Array Fields.s(1) )
  Protected X, K, Y, Var$, Piece$
  
  Vars$ = ReplaceString(Vars$, "(", "")
  Vars$ = Trim(ReplaceString(Vars$, ")", ""))
  ; "C:\Windows\System32\notepad.exe", "C:\Windows\System32\", 1
  K = CountString(Vars$, ",")
  
  For X = 1 To K +1
    Piece$ = Trim(StringField(Vars$, X, ","))
    ;If String...
    If CountString(Piece$, Chr(34)) = 2
      Fields(K) = ReplaceString(Piece$, Chr(34), "")
    Else
      Fields(K) = Piece$
    EndIf
  Next 
  For Y = K+1 To 10
    Fields(Y)=""
  Next
 
EndProcedure  

Procedure CheckCmdLineParms()
  Protected X, K, Result, CmdLine$, Path$, Name$, Script$, Cmd$, Vars$, Line$
  
  Result = CountProgramParameters()
  If Result = 1
    NewList ScriptLine.s()
    CmdLine$ = ProgramParameter(0)
    Path$ = GetPathPart(CmdLine$)
    Name$ = GetFilePart(CmdLine$)
    
    If FileSize(CmdLine$) > 1
      ReadFile(6, CmdLine$)
      While Eof(6) = 0
        Script$ = Script$ + ReadString(6)
      Wend
      CloseFile(6)   
    EndIf
    
    K = CountString(Script$, #LF$)
    For X = 1 To K+1
      AddElement(ScriptLine())
      ScriptLine() = StringField(Script$, X, #LF$)
    Next
    
    
    For X = 0 To ListSize(ScriptLine())-1
      SelectElement(ScriptLine(), X)
      If Len(Trim(ScriptLine())) < 1
        Continue
      EndIf
      Dim Fields.s(10)
      Line$=Trim(ScriptLine())
      Debug Line$
      Cmd$ = StringField(Line$, 1, "(")
      Vars$ = StringField(Line$, 2, "(")
      If Cmd$="Delay"
        Vars$ = ReplaceString(Vars$, "(","")
        Vars$ = ReplaceString(Vars$, ")","")
        Delay(Val(Vars$))
      Else
        ParseParams(Vars$, Fields())
        
        If Cmd$ = "AUTOIT::Run"
          ; "C:\Windows\System32\notepad.exe", "C:\Windows\System32\", 1
          AUTOIT::Run(Fields(1), Fields(2), Val(Fields(3)))
  
        EndIf  
      EndIf
    Next
      
    FreeArray(Fields())    
    FreeList(ScriptLine())
  EndIf
EndProcedure
A couple More Bug fixes and this DOES Work.

Code: Select all

;========================================================
;====           AutoItX Script Testing
;====
;====  Author: Pete Hollyer
;====
;====   Notes: If EXE is called with CMDLine of Script
;====   Run Script
;====
;========================================================

Procedure ParseParams(Vars$, Array Fields.s(1) )
  Protected X, K, Y, Var$, Piece$
  
  Vars$ = ReplaceString(Vars$, "(", "")
  Vars$ = Trim(ReplaceString(Vars$, ")", ""))
  ; "C:\Windows\System32\notepad.exe", "C:\Windows\System32\", 1
  K = CountString(Vars$, ",")
  
  For X = 1 To K +1
    Piece$ = Trim(StringField(Vars$, X, ","))
    ;If String...
    If CountString(Piece$, Chr(34)) = 2
      Fields(X) = ReplaceString(Piece$, Chr(34), "")
      Debug Fields(X)
    Else
      Fields(X) = Piece$
    EndIf
  Next 
  For Y = X+1 To 10
    Fields(Y)=""
  Next
 
EndProcedure  

Procedure CheckCmdLineParms()
  Protected X, K, Result, CmdLine$, Path$, Name$, Script$, Cmd$, Vars$, Line$
  
  Result = CountProgramParameters()
  If Result = 1
    NewList ScriptLine.s()
    CmdLine$ = ProgramParameter(0)
    Path$ = GetPathPart(CmdLine$)
    Name$ = GetFilePart(CmdLine$)
    
    If FileSize(CmdLine$) > 1
      ReadFile(6, CmdLine$)
      While Eof(6) = 0
        AddElement(ScriptLine())
        ScriptLine() = ReadString(6)
        Debug ScriptLine()
      Wend
      CloseFile(6)   
    EndIf
    
;     K = CountString(Script$, #LF$)
;     For X = 1 To K+1
;       AddElement(ScriptLine())
;       ScriptLine() = StringField(Script$, X, #LF$)
;     Next
    
    Dim Fields.s(10)
    For X = 0 To ListSize(ScriptLine())-1
      SelectElement(ScriptLine(), X)
      Debug ScriptLine()
      If Trim(ScriptLine()) = ""
        Continue
      EndIf
      
      Line$=Trim(ScriptLine())
      Debug Line$
      Cmd$ = StringField(Line$, 1, "(")
      Vars$ = StringField(Line$, 2, "(")
      If Cmd$="Delay"
        Vars$ = ReplaceString(Vars$, "(","")
        Vars$ = ReplaceString(Vars$, ")","")
        Delay(Val(Vars$))
      Else
        ParseParams(Vars$, Fields())
        
        If Cmd$ = "AUTOIT::Run"
          ; "C:\Windows\System32\notepad.exe", "C:\Windows\System32\", 1
          AUTOIT::Run(Fields(1), Fields(2), Val(Fields(3)))
  
        EndIf  
      EndIf
    Next
      
    FreeArray(Fields())    
    FreeList(ScriptLine())
  EndIf
EndProcedure
User avatar
idle
Always Here
Always Here
Posts: 5888
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Script "Execution"

Post by idle »

I probably don't understand the problem your solving, can you use an IPC method?
If you have a program with a window that's loaded the autoit.dll and you want it to process a script you can use win32 copydatastructure method to transfer the script between exes.

run it twice once with debugger once without

Code: Select all



EnableExplicit 

Global mhwnd,apphwnd 

Procedure SendToApp(hwnd,type,*mdata)

Protected *cds.COPYDATASTRUCT,str.s   

*cds = AllocateMemory(SizeOf(COPYDATASTRUCT))
 Select type 
    Case #PB_String 
      str = PeekS(*mdata,-1)  
      *cds\dwData = type  
      *cds\cbData = StringByteLength(str) 
      *cds\lpData = @str 
 EndSelect    
   
 SendMessage_(hwnd, #WM_COPYDATA, mhwnd, *cds)
    
 FreeMemory(*cds)
 
EndProcedure 

Procedure WinCallback(hWnd, uMsg, WParam, LParam) 
  
  Protected *cds.COPYDATASTRUCT
    
  Select umsg 
    Case #WM_COPYDATA 
      *cds = LParam 
      
      Select *cds\dwData 
          Case #PB_String 
          SetGadgetText(0,PeekS(*cds\lpData,-1))  
      EndSelect 
   EndSelect    
      
   ProcedureReturn #PB_ProcessPureBasicEvents 
   
EndProcedure   

Procedure FindWindowByName(name.s) 
  
  Protected hwnd,TitleSize.l,Title.s  
  
  hwnd = GetWindow_(GetDesktopWindow_(), #GW_CHILD)
  While hwnd
	TitleSize.l = GetWindowTextLength_(hwnd) + 2
	Title = Space(TitleSize)
	GetWindowText_(hwnd, Title, TitleSize)
	If FindString(LCase(Title), LCase(name))
		If hwnd <> WindowID(mhwnd) 
		   ProcedureReturn hwnd
		EndIf   
	EndIf
	hwnd = GetWindow_(hwnd, #GW_HWNDNEXT)
Wend

EndProcedure   

Procedure SendString() 
  
  Protected  str.s = GetGadgetText(0) 
  If apphwnd = 0 
     apphwnd = FindWindowByName("Sendit")
  EndIf 
  If apphwnd 
    SendToApp(apphwnd,#PB_String,@str)
    SetGadgetText(0,"")
  EndIf  
  
EndProcedure  

mhwnd = OpenWindow(#PB_Any,0,0,200,100,"Sendit") 
apphwnd = FindWindowByName("Sendit")

EditorGadget(0,10,10,180,30) 
ButtonGadget(1,10,50,60,30,"Send url")
BindGadgetEvent(1,@SendString(),#PB_EventType_LeftClick) 
SetWindowCallback(@WinCallback(),mhwnd) 

Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
 



 
Phollyer
Enthusiast
Enthusiast
Posts: 143
Joined: Sat Jun 03, 2017 3:36 am
Location: USA, Texas
Contact:

Re: Script "Execution"

Post by Phollyer »

Thanks for your reply

What I am trying to do Generate Code into Variable, then execute the Variable in another thread

myCode$ = "Debug " + #DOUBLEQUOTE$ + "Hello World" + #DOUBLEQUOTE$ + #LF$

So now I have a valid PureBasic line of code inside MyCode$, Is there a way to execute the code inside the Variable?

Does that make better sense?

I think the only way would be to save the Variable code to a temp file, then launch PureBasic Compiler to Compile and execute it

Pete
User avatar
idle
Always Here
Always Here
Posts: 5888
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Script "Execution"

Post by idle »

Phollyer wrote: Tue May 27, 2025 5:09 pm Thanks for your reply

What I am trying to do Generate Code into Variable, then execute the Variable in another thread

myCode$ = "Debug " + #DOUBLEQUOTE$ + "Hello World" + #DOUBLEQUOTE$ + #LF$

So now I have a valid PureBasic line of code inside MyCode$, Is there a way to execute the code inside the Variable?

Does that make better sense?

I think the only way would be to save the Variable code to a temp file, then launch PureBasic Compiler to Compile and execute it

Pete

you can do it by running the compiler in standby, this might get you started
for more info on the compiler interface see the file "\PureBasic\SDK\CompilerInterface.txt"

Code: Select all

CompilerIf #PB_Compiler_OS =#PB_OS_Windows
  #Compiler = #PB_Compiler_Home+"compilers\pbcompiler.exe"
CompilerElse 
  #Compiler = #PB_Compiler_Home+"compilers/pbcompiler"
CompilerEndIf 

Procedure StartCompiler()
  Protected cmd.s 
  CompilerIf #PB_Compiler_OS =#PB_OS_Windows
    cmd = "/STANDBY"
  CompilerElse 
    cmd = "-sb"
  CompilerEndIf  
  Debug cmd 
  
  ProcedureReturn RunProgram(#Compiler,cmd,"",#PB_Program_Open|#PB_Program_Read|#PB_Program_Write|#PB_Program_Hide)
EndProcedure

Procedure StopCompiler(compiler)
  
  Protected cmd.s 
  
  CompilerIf #PB_Compiler_OS =#PB_OS_Windows 
    cmd = "END" 
  CompilerElse 
    cmd = "END"
  CompilerEndIf  
  
  WriteProgramStringN(compiler,cmd)
  WaitProgram(compiler,5000)
  CloseProgram(compiler)
EndProcedure

Procedure SendCompilerCommand(compiler,command$)
  If ProgramRunning(compiler)
    WriteProgramStringN(compiler, command$)
  EndIf
EndProcedure

Procedure.s GetCompilerOutput(compiler)
  If AvailableProgramOutput(compiler)
    ProcedureReturn ReadProgramString(compiler)
  EndIf
EndProcedure

Procedure WaitCompilerReady(compiler)
  Protected out$
  While out$<>"READY" And Left(out$,5)<>"ERROR"
    out$ = GetCompilerOutput(compiler)
    If out$
      Debug out$
    EndIf
  Wend
EndProcedure

Procedure.s CheckSyntax(compiler,code$,bProgress=0) 
  Protected temp$ = GetTemporaryDirectory() 
  Protected source$ = temp$ + "checkcode" 
  Protected out$,error$
  Protected fn = CreateFile(-1,source$+".pb") 
  If fn 
    WriteString(fn,code$,#PB_UTF8)
    CloseFile(fn) 
    SendCompilerCommand(Compiler, "SOURCE"+Chr(9)+source$+".pb")
    SendCompilerCommand(Compiler, "TARGET"+Chr(9)+source$+".exe")
    SendCompilerCommand(Compiler, "COMPILE"+Chr(9)+"PROGRESS"+Chr(9)+"SYNTAX")
    
    While out$ <> "SUCCESS" And Left(out$,5)<>"ERROR"
      out$ = GetCompilerOutput(compiler) 
      If out$ <> "" 
        If bProgress
          PrintN(out$) 
        EndIf   
      EndIf   
    Wend
    
    If Left(out$,5)="ERROR" 
       While out$<>"OUTPUT"+#TAB$+"COMPLETE" 
        out$ = GetCompilerOutput(compiler) 
        If (out$ <> "" And Left(out$,6) <> "OUTPUT")
          error$ + out$  
          If bProgress
            PrintN(out$)
          EndIf   
        EndIf   
      Wend 
      out$ = error$ 
    EndIf 
    
    ProcedureReturn out$  
  EndIf 
  
EndProcedure   

Procedure CompileWithDebug(compiler,code$,bProgress=0) 
  Protected temp$ = GetTemporaryDirectory() 
  Protected source$ = temp$ + "checkcode" 
  
  Protected fn = CreateFile(-1,source$+".pb") 
  If fn 
    WriteString(fn,code$,#PB_UTF8)
    CloseFile(fn) 
    SendCompilerCommand(Compiler, "SOURCE"+Chr(9)+source$+".pb")
    SendCompilerCommand(Compiler, "TARGET"+Chr(9)+source$+".exe")
    SendCompilerCommand(Compiler, "COMPILE"+Chr(9)+"PROGRESS"+Chr(9)+"DEBUGGER")
    
     While out$ <> "SUCCESS" And Left(out$,5)<>"ERROR"
      out$ = GetCompilerOutput(compiler) 
      If out$ <> "" 
        If bProgress
          PrintN(out$) 
        EndIf   
      EndIf   
    Wend
    
    If out$ = "SUCCESS" 
      RunProgram(source$+".exe") 
      RunProgram(source$+".pb") 
    EndIf  
    
  EndIf 
  
EndProcedure   

OpenConsole()
Global code$,result$,compiler = StartCompiler() 
If compiler 
  
  code$ = ~"OpenConsole(\"test\")" + #CRLF$ 
  code$ + ~"PrintN(\"Hello World\")" + #CRLF$ 
  code$ + ~"Inpu()" + #CRLF$  ;error here 
  
  PrintN("Result")
  PrintN(CheckSyntax(compiler,code$,1))  
  
  code$ = ~"OpenConsole(\"test\")" + #CRLF$ 
  code$ + ~"PrintN(\"Hello World\")" + #CRLF$ 
  code$ + ~"Debug \"Hello\"" + #CRLF$ 
  code$ + ~"Input()" + #CRLF$  
  
  PrintN("Result") 
  PrintN(CheckSyntax(compiler,code$)) 
  CompileWithDebug(compiler,code$,1) 
  Input()
  StopCompiler(compiler) 
EndIf 
Input() 
CloseConsole()  


Phollyer
Enthusiast
Enthusiast
Posts: 143
Joined: Sat Jun 03, 2017 3:36 am
Location: USA, Texas
Contact:

Re: Script "Execution"

Post by Phollyer »

Oh! Wow! Idle, Thanks!
This is going to be FUN!!!

Thank You SO Much!!

Pete
Post Reply