Version | Date | Author | Comment |
---|---|---|---|
v0.1 |
2017-05-06 |
Pascal COMBIER |
Initial release |
v0.2 |
2022-07-17 |
Pascal COMBIER |
Optimizations |
Plainstarter is a lightweight starter for Microsoft Windows programs. The purpose is to help software developers to expose a simple executable file to end-user, hiding the fact that the application is implemented using third-party’s interpreters such as Python or Java. It can be used in place of batch scripts, allowing developers to focus on the implementation of their software instead of learning batch commands. Plainstarter is a native Windows program which is directly exposed to the end-user. When executed, it reads a configuration file and start the real program as configured by the developer. The executable filename and icon are expected to be changed by the developer to match the application purpose.
-
Start programs in an accurate and consistent way
-
Simple behavior regarding spaces, quotes, parameters, long-filenames and Unicode
-
Configure environment variables (e.g. PATH, APPDATA) and export them to underlying process
-
Hide terminal console for GUI programs implemented using third-party interpreters (e.g. Python, Java, Lua, Tcl/Tk, Common Lisp)
-
Easy access to directory name and program name
-
-
Small binary size
-
Permissive license allowing cost-free commercial use [1]
Let’s see an example of plainstarter usage, more examples are available in the release area (Lua, Tcl/Tk, Common Lisp, etc). Let’s implement the UNIX cat command using Lua on Windows.
A trivial UNIX cat implementation will take a list of filenames in the parameters and print the files content on the standard output.
local Filenames = arg
for Index = 1, #Filenames do
for Line in io.lines(Filenames[Index]) do
io.write(Line)
io.write("\n")
end
end
There are 2 binary files in the bin64
directory of plainstarter:
plainstarter-x86-64-console.exe
plainstarter-x86-64-gui.exe
The program UNIX cat is a command-line program, so we simply copy
plainstarter-x86-64-console.exe
and rename it into lua-cat.exe
. When
lua-cat.exe
will start, it will look for the configuration file
configs/lua-cat.cfg
, then config/lua-cat.cfg
, and finally lua-cat.cfg
. The
first configuration file found will be used, the others will be ignored.
To run Lua scripts, we need to get the Lua binaries files. To
make it clear that these binary files are outside the scope of lua-cat project,
we copy them in the directory third-party
.
lua-cat
├───lua-cat.exe (duplicate of plainstarter-x86-64-console.exe)
│
├───config
│ └─── lua-cat.cfg
│
├───sources
│ └─── cat.lua
│
└───third-party
└───bin
├─── lua54.dll
├─── lua54.exe
├─── luac54.exe
└─── wlua54.exe
The configuration file need to override the %PATH%
variable to make Lua
binaries available to lua-cat.exe
. To make it more portable, third-party\bin
is prefixed to %PATH%
instead of postfixed.
PLAINSTARTER_OPTIONS=monitor-process show-console
PATH=%PLAINSTARTER_DIRECTORY%\third-party\bin;%PATH%
PLAINSTARTER_CMD_LINE=lua54 sources\cat.lua
PLAINSTARTER_CMD_LINE
defines the command line to execute. Note that all the
parameters provided to plainstarter will be appended to PLAINSTARTER_CMD_LINE
implicitly. If lua-cat.exe PARAM1 PARAM2 PARAM3
is executed, the command line
lua54 sources\cat.lua PARAM1 PARAM2 PARAM3
will be executed.
In this chapter, we will consider that the Plainstarter binary file has been renamed to "cmd-example.exe" and stored in the directory "example".
example\cmd-example.exe
is started, the following steps are executed:-
Find a configuration file
-
Try to open
example\configs\cmd-example.cfg
-
Try to open
example\config\cmd-example.cfg
-
Try to open
example\cmd-example.cfg
-
-
Read the configuration file, line per line
-
If the line start with
#
, the line is considered as a comment and is ignored -
If the line is a variable affectation such as
PATH=%PATH%;subdir
, the variable is registered in the local environment -
If the line is a command line such as
PLAINSTARTER_CMD_LINE=cmd.exe
, the command line is executed with the current environment
-
Note
|
Only the first configuration file which is found is considered. The other configuration files are ignored. |
These variables can be used in Plainstarter configuration file. They will not be exported to the child processes. If needed, it’s straight-forward to export these special variables:
MYAPP_DIR=%PLAINSTARTER_DIRECTORY%
MYAPP_PROGNAME=%PLAINSTARTER_PROGNAME%
MYAPP_OPTIONS=%PLAINSTARTER_OPTIONS%
PLAINSTARTER_CMD_LINE=cmd.exe /K echo "%PLAINSTARTER_DIRECTORY%" "%PLAINSTARTER_PROGNAME%"
This is the command line to execute. All the parameters given to Plainstarter will be appended to PLAINSTARTER_CMD_LINE. This behavior is required to transmit command line options to the underlying programs.
This is the name of the executable without the filename extension ".exe". This can be used when the behavior of the underlying program depends on the name of the executable (e.g. busybox-w32).
Plainstarter can be dynamically configured using the special variable named PLAINSTARTER_OPTIONS. This variable should contain a list of keywords separated by spaces. Keywords are case-sensitive and described below.
-
Show the terminal console cmd.exe
-
Default: disabled
-
This option should be used when the end-user program is requesting the standard input. A typical example is a Lua or Common Lisp REPL, which is waiting for the user to input commands from a terminal. Programs exposing Graphical User Interface should probably not activate this option. When activated, this option also activates the option monitor-process.
-
Try to enable Windows Visual Styles
-
Default: disabled
-
This option is used for Graphical User Interface programs which are using Microsoft Windows native widgets. When using this option, the native widgets will be drawn using new graphical styles. This is implemented by calling the Win32 function InitCommonControls.
-
Monitor the child process return code
-
Default: disabled
-
By default, Plainstarter simply spawns new processes according to PLAINSTARTER_CMD_LINE. The child process is started and Plainstarter process is closed, returning 0 as process return code. When activated, this option makes Plainstarter wait for the end of execution of the child process. If the child process ends abnormally, the process error code will be notified to the user. The error code of the child process will be returned by Plainstarter process.
Plainstarter is a Unicode program, it supports non-ascii characters in the filenames and configuration files. To keep the software simple and avoid run-time strings conversions, Plainstarter request to have UTF-16 LE encoded files containing a Unicode Byte Order Mark.
This can be achieved by using notepad.exe to save the file:
static const TCHAR PS_CONFIG_DIR_1[8] = _T("configs\\"); static const TCHAR PS_CONFIG_DIR_2[7] = _T("config\\"); static const TCHAR PS_CONFIG_DIR_3[1] = _T("");
NTFS long-filenames are supported by default, allowing filenames up to 32767 characters. More information is available on the MSDN.
static const size_t PS_MAX_FILENAME_LENGTH_CHAR = (size_t)32767;
The icon is located in art\plainstarter.ico
. The source code needs to be recompiled.
It is possible to change the icon present in the Plainstarter executable file without recompiling the program. The cost-free proprietary program Resource Hacker v4.5.30 has been reported working with Plainstarter executable files.
Batches files are often used to start programs based on third-party interpreters such as Python.
As referenced on StackOverflow, Visual Basic Scripts can be used to start other programs.
Eclipse is a development environment for Java programming language. This IDE is shipped with their own launcher named Eclipse Launcher (eclipse.exe).
Eclipse contains a native executable launcher that is used to start Eclipse. There is more to the launcher than just the eclipse executable in the root of the install. The launcher and its shared library The launcher executable comes in 2 pieces: the executable (eclipse.exe), and a shared library (eclipse_1017.dll). The executable lives in the root of the eclipse install. The shared library is in a platform specific fragment, org.eclipse.equinox.launcher.[config], in the plugins directory. Having the majority of the launcher code in a shared library that lives in a fragment means that that portion of the launch code can now be updated from an update site. Also, when starting from java, the shared library can be loaded via JNI in order to display the splash screen.
Eclipse Project Documentation (source)
Plainstarter is licensed using the permissive Open Source license known as Simplified BSD License.
Copyright 2014-2022 Pascal COMBIER Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.