HOWTO Build standalone executables in Lianja on Windows
by
, 2022-01-04 at 00:50 (25731 Views)
Lianja provides the ability to build standalone executables on Windows.
This has been a popular request, so we have added in this functionality.
These executables can only be built for Apps that have been hand coded in LianjaScript, Python, JavaScript, TypeScript or Babel using the Lianja UI Framework.
This functionality is primarily for building small GUI Apps not for business Apps running under the Lianja App Center under the control of Permissions and Roles.
After installing Lianja 7.0 (beta or later).
Open the example_timeclock app which is included with Lianja 7.0.
This app uses the new "Camera" UI framework class and is a small App to handle clocking in and out of employees in a company.
Feel free to enhance this to suit your own needs by adding support for storing the clock in/out date and time along with the employees photo.
Unsurprisingly there is very little code required to build this App and very few differences between the code for LianjaScript, Python and JavaScript due to the brevity (low-Code) of the Lianja UI Framework usage in all supported Scripting languages.
Building standalone LianjaScript executables
Let's look at the LianjaScript code.
Note the READ EVENTS at the end of the code which is needed for a standalone App.
Building standalone Python executablesCode:local oform = createObject("Form") oform.resize(600, 600) oform.closable = 1 oform.caption = "Time clock" oform.minwidth = 600 oform.minheight = 600 oform.addObject("ocont", "container") ocont.margin = 10 ocont.autosize = 1 ocont.layout = "V" ocont.backcolor = "black" ocont.addObject("obadgenolab", "label") obadgenolab.fixedheight = 24 obadgenolab.autowidth = 1 obadgenolab.alignment = "center" obadgenolab.caption = "Enter Badge Number" obadgenolab.backcolor = "darkgray" obadgenolab.forecolor = "white" obadgenolab.fontbold = 1 obadgenolab.fontsize = 10 ocont.addspacing(10) ocont.addObject("obadgeno", "textbox") obadgeno.fixedheight = 24 obadgeno.autowidth = 1 obadgeno.placeholder = "Enter your badge number, Take a Photo then CLOCK IN or CLOCK OUT" ocont.addspacing(10) ocont.addObject("obadgenolab2", "label") obadgenolab2.fixedheight = 24 obadgenolab2.autowidth = 1 obadgenolab2.alignment = "center" obadgenolab2.caption = "Take a Photo" obadgenolab2.backcolor = "darkgray" obadgenolab2.forecolor = "white" obadgenolab2.fontbold = 1 obadgenolab2.fontsize = 10 ocont.addspacing(10) ocont.addObject("ocamera", "camera") ocamera.autowidth = 1 ocamera.autoheight = 1 ocamera.backcolor = "black" ocamera.stop() ocont.addspacing(10) ocont.addObject("obadgenolab3", "label") obadgenolab3.fixedheight = 24 obadgenolab3.autowidth = 1 obadgenolab3.alignment = "center" obadgenolab3.caption = "Clock in / Clock out" obadgenolab3.backcolor = "darkgray" obadgenolab3.forecolor = "white" obadgenolab3.fontbold = 1 obadgenolab3.fontsize = 10 ocont.addObject("ocont2", "container") ocont2.layout = "H" ocont2.fixedheight = 60 ocont2.backcolor = "black" ocont2.spacing = 10 ocont2.addObject("obtn1", "commandbutton") obtn1.resize(60, 50) obtn1.flat = 1 obtn1.fixedheight = 50 obtn1.caption = "CLOCK IN" obtn1.stylesheet = "btn" ocont2.addObject("obtn2", "commandbutton") obtn2.flat = 1 obtn2.resize(60, 50) obtn2.fixedheight = 50 obtn2.stylesheet = "btn" obtn2.caption = "CLOCK OUT" // event handlers proc clockin() ocamera.takePhoto() thisform.showSuccessMessage("You clocked in on " + dtoc(date()) + " at " + time()) endproc proc clockout() ocamera.takePhoto() thisform.showSuccessMessage("You clocked out on " + dtoc(date()) + " at " + time()) endproc // dynamically assign the click events for the "Clock in" and "Clock out" commandbuttons obtn1.click = clockin obtn2.click = clockout // modal form oform.show() // must put read events at the bottom so the window stays open until closed by user read events
Upgrading pip to the latest version
Open a command prompt.
In the console workspace , create the python3 directory to contain the modules local to the AppCode:cd x:\lianja\bin python -m pip install --upgrade pip --no-warn-script-location
Installing local python modules in the console workspace (you can now use pip in the Lianja/VFP tab)Code:mkdir python3
Specifying the --target command line switch installs the Python modules local to your App so you can import them directly.
e.g.
import numpy
Let's look at the Python code.Code:set backticks on pip install --target=`cd`\python3\ numpy
Building standlone JavaScript executablesCode:import sys import types from datetime import datetime import Lianja class myCommandbutton(Lianja.Commandbutton): pass oform = createObject("form") oform.resize(600, 600) oform.closable = 1 oform.caption = "Time clock" oform.minwidth = 600 oform.minheight = 600 oform.addObject("ocont", "container") ocont.margin = 10 ocont.autosize = 1 ocont.layout = "V" ocont.backcolor = "black" ocont.addObject("obadgenolab", "label") obadgenolab.fixedheight = 24 obadgenolab.autowidth = 1 obadgenolab.alignment = "center" obadgenolab.caption = "Enter Badge Number" obadgenolab.backcolor = "darkgray" obadgenolab.forecolor = "white" obadgenolab.fontbold = 1 obadgenolab.fontsize = 10 ocont.addspacing(10) ocont.addObject("obadgeno", "textbox") obadgeno.fixedheight = 24 obadgeno.autowidth = 1 obadgeno.placeholder = "Enter your badge number, Take a Photo then CLOCK IN or CLOCK OUT" ocont.addspacing(10) ocont.addObject("obadgenolab2", "label") obadgenolab2.fixedheight = 24 obadgenolab2.autowidth = 1 obadgenolab2.alignment = "center" obadgenolab2.caption = "Take a Photo" obadgenolab2.backcolor = "darkgray" obadgenolab2.forecolor = "white" obadgenolab2.fontbold = 1 obadgenolab2.fontsize = 10 ocont.addspacing(10) ocont.addObject("ocamera", "camera") ocamera.autowidth = 1 ocamera.autoheight = 1 ocamera.backcolor = "black" ocamera.minheight = 400 ocamera.stop() ocont.addspacing(10) ocont.addObject("obadgenolab3", "label") obadgenolab3.fixedheight = 24 obadgenolab3.autowidth = 1 obadgenolab3.alignment = "center" obadgenolab3.caption = "Clock in / Clock out" obadgenolab3.backcolor = "darkgray" obadgenolab3.forecolor = "white" obadgenolab3.fontbold = 1 obadgenolab3.fontsize = 10 ocont.addObject("ocont2", "container") ocont2.layout = "H" ocont2.fixedheight = 60 ocont2.backcolor = "black" ocont2.spacing = 10 ocont2.addObject("obtn1", "myCommandbutton") obtn1.resize(60, 50) obtn1.flat = 1 obtn1.fixedheight = 50 obtn1.caption = "CLOCK IN" obtn1.stylesheet = "btn" ocont2.addObject("obtn2", "myCommandbutton") obtn2.flat = 1 obtn2.resize(60, 50) obtn2.fixedheight = 50 obtn2.stylesheet = "btn" obtn2.caption = "CLOCK OUT" # event handlers def clockin(self): ocamera.takePhoto() now = datetime.now() oform.showSuccessMessage("You clocked in at " + now.strftime("%m/%d/%Y %H:%M:%S")) def clockout(self): ocamera.takePhoto() now = datetime.now() oform.showSuccessMessage("You clocked out at " + now.strftime("%m/%d/%Y %H:%M:%S")) # We can dynamically bind events to custom classes in Lianja/Python using the new bindEvent() build-in Lianja/Python function bindEvent(obtn1, clockin, "click") bindEvent(obtn2, clockout, "click") # modal form oform.show() # read_events() is the equivalent of READ EVENTS in Lianja Script read_events()
Howto build a standalone executableCode:var oform = createObject("Form"); oform.resize(600, 600); oform.closable = 1; oform.caption = "Time clock"; oform.minwidth = 600; oform.minheight = 600; oform.addobject("ocont", "container"); ocont.margin = 10; ocont.autosize = 1; ocont.layout = "V"; ocont.backcolor = "black"; ocont.addObject("obadgenolab", "label"); obadgenolab.fixedheight = 24; obadgenolab.autowidth = 1; obadgenolab.alignment = "center"; obadgenolab.caption = "Enter Badge Number"; obadgenolab.backcolor = "darkgray"; obadgenolab.forecolor = "white"; obadgenolab.fontbold = 1; obadgenolab.fontsize = 10; ocont.addspacing(10); ocont.addObject("obadgeno", "textbox"); obadgeno.fixedheight = 24; obadgeno.autowidth = 1; obadgeno.placeholder = "Enter your badge number, Take a Photo then CLOCK IN or CLOCK OUT"; ocont.addspacing(10); ocont.addObject("obadgenolab2", "label"); obadgenolab2.fixedheight = 24; obadgenolab2.autowidth = 1; obadgenolab2.alignment = "center"; obadgenolab2.caption = "Take a Photo"; obadgenolab2.backcolor = "darkgray"; obadgenolab2.forecolor = "white"; obadgenolab2.fontbold = 1; obadgenolab2.fontsize = 10; ocont.addspacing(10); ocont.addObject("ocamera", "camera"); ocamera.autowidth = 1; ocamera.autoheight = 1; ocamera.backcolor = "black"; //ocamera.stop() ocont.addspacing(10); ocont.addObject("obadgenolab3", "label"); obadgenolab3.fixedheight = 24; obadgenolab3.autowidth = 1; obadgenolab3.alignment = "center"; obadgenolab3.caption = "Clock in / Clock out"; obadgenolab3.backcolor = "darkgray"; obadgenolab3.forecolor = "white"; obadgenolab3.fontbold = 1; obadgenolab3.fontsize = 10; ocont.addObject("ocont2", "container"); ocont2.layout = "H"; ocont2.fixedheight = 60; ocont2.backcolor = "black"; ocont2.spacing = 10; ocont2.addObject("obtn1", "commandbutton"); obtn1.resize(60, 50); obtn1.flat = 1; obtn1.fixedheight = 50; obtn1.caption = "CLOCK IN"; obtn1.stylesheet = "btn"; ocont2.addObject("obtn2", "commandbutton"); obtn2.flat = 1; obtn2.resize(60, 50); obtn2.fixedheight = 50; obtn2.stylesheet = "btn"; obtn2.caption = "CLOCK OUT"; // event handlers function clockin() { ocamera.takePhoto() oform.showSuccessMessage("You clocked in on " + new Date().toLocaleString()) }; function clockout() { ocamera.takePhoto(); oform.showSuccessMessage("You clocked out on " + new Date().toLocaleString()) }; // we can assign event handlers like this in JavaScript obtn1.click = clockin; obtn2.click = clockout; // modal form oform.show(); // must put read events at the bottom so the window stays open until closed by user read_events();
1. Select the scripting language in the App settings
2. Check "Standalone" in the UI Presentation rules of the App Settings.
3. Write the "main" script with the same name as the App. In this case example_timeclock.prg or example_timeclock.js or example_timeclock.py. (See code above). You can switch the "Scripting language" in the App settings to test each one.
4. Click the "Desktop App View" icon in the top right of the App Builder window. The standalone executable will be built and run externally.
When building a standalone executable with LianjaScript, all the prg files in the App directory are linked together into a .src file and this is compiled.
The resulting object file is bound onto the end the Lianja runtime executable and the authenticode code signing is adjusted so as to not be affected by the application payload.
All of the supporting Qt libraries etc are included in the standalone application directory.
In this case:
x:\lianja\installers\standalone\example_timeclock
If your application is built in Python there is a python3 directory included which contains the python modules you have installed with pip. This enables the application to be installed anywhere and run by executing the executable (in this case) example_timeclock.exe.
You can study this folder structure in file explorer.