freeWrap as a TCL/TK wrapper program
freeWrap as a single-file WISH interpreter
Using the DDE and Registry packages (Windows only)
Naming and referring to wrapped files
Wrapping and using TCL/TK extension (packages)
Special variables, procedures and commands defined by freeWrap
Stdin/stdout redirection and pipes (using the exec and open commands) (Windows only)
freeWrap can wrap TCL/TK applications that consist of multiple script and binary image files. freeWrap combines all the files together into a single executable file. The syntax for wrapping an application is described below.
Calling Syntax: |
freewrap mydir/prog.tcl [-e] [-f FileLoadList] [-p WrappedFile] [-w WrapStub] File1 ... FileN |
|
where:
|
mydir/prog.tcl FileN -e -f -w |
file path to main TCL/TK program script name of a text or binary file to include. specifies that code encryption should be turned off specifies that the following named file (FileLoadList) contains a list of files to wrap specifies that the following named file (WrapStub) is the name of the file to use as the freeWrap stub |
output: |
prog (Linux) Note : the output file will be placed in the current directory from which freeWrap is called. |
The names of the files being wrapped may include either relative or full paths. The resulting executable program can access the wrapped files by either refering to them by their full path as they existed at the time of wrapping or adding the paths to TCL's auto_path variable. If the auto_path method is used, the appropriate tclIndex or pkgIndex.tcl files should also be wrapped into the application. Please see the information on how to wrap a package extension. Please see Naming and referring to wrapped files for more details on how to refer to wrapped files within the application.
Both text and binary files can be wrapped.
FreeWrap automatically encrypts files that have either a tcl, tk or tsh file extension (e.g myprog.tcl, myprog.tk, myprog.tsh) unless the -e option is used.
For larger wrap projects, the user may wish to use freeWrap's -f option to specify a file which contains a list of files to wrap. The specified text file must contain one file name per line. Each file name listed in the file will be added to the wrapping. Use of the -f option does not preclude the specification of individual files on the freeWrap command line. The -f option may also be used several times on the same command line.
Example: freewrap myprog.tcl logo.gif -f projlist.txt code2.tcl -f special.txt
By default, freeWrap attaches the wrapped files to a copy of the freeWrap program you use to do the wrapping. The -w option allows attaching the wrapped files to a different copy of freeWrap. Since freeWrap is available for multiple operating systems, this feature is useful for assembling freeWrapped applications for other operating systems while on a single computer.
Example (assembling a Windows version while running freeWrap on Linux):
freewrap myprog.tcl -w freewrap.exe
Example (assembling a Linux version while running freeWrap on Windows):
freewrap myprog.tcl -w freewrap
Even files previously generated by freeWrap can be wrapped into another freeWrap application. However, the repetitive inclusion of freeWrap's TCL/TK code would produce fairly large application files. Therefore, the freeWrap program has been designed to provide efficient packaging of previously wrapped applications. FreeWrap removes a wrapped program's freeWrap core prior to storing it in the wrapped application. Only the application's archive section is stored in the new freeWrap application. This archive section is given a name starting with the string fwpkg_ followed by its original file name and having an extension of ZIP . It is the responsibility of the programmer to use the ::freewrap::reconnect command to later reattach the freeWrap core and copy the full application to a disk file.
Example (assume firstApp is a freeWrap generated application)
freewrap myprog.tcl firstApp.exe
creates a file named fwpkg_firstApp.zip inside the application myprog.exe. To restore and copy the original application (firstApp.exe) to disk the myprog.exe program should use a TCL command similar to:
::freewrap::reconnect fwpkg_firstApp.zip c:/myprog/bin/firstApp.exe
Renaming the freewrap program to some other file name causes freewrap to behave as a a stand-alone, single-file WISH that can be used to run any TCL/TK script. This can be done in the following manner.
Copy freewrap.exe to a new file name
Example: copy freewrap.exe wishrun.exe
Use the new file as you would normally use WISH
Example: wishrun script_name.tcl
Under freeWrap, the console command is available for both Windows and UNIX. The console window is the location that will receive any STDOUT or STDERR output. The console can also be used to interactively enter TCL/TK commands. Use console show to display the window and console hide to remove it.
The DDE and Registry packages have been compiled into freeWrap. There is no need to load them with a package require command. Simply use the dde and registry commands without any preceding package require command.
Wrapping
When running a wrapped application, the first file specified on the command line at the time of wrapping will be executed as a TCL/TK script. All other files specified on the command line or in a file load list are available to this executing script.
You can do the following with the wrapped files.
- Source them
- Open them
- Read them
- Close them
- Use the file open and file close commands
- Use them with the image create command
- Specify them for -bitmap widget options.
You CANNOT do the following with the wrapped files.
- File delete them (since they exist in the application, not on disk)
- Expect the glob command to display them.
- Use the load command on them. However, you can write them to disk first then use the load command on the new disk file. You may also wish to consider providing any load-able extension as a separate file instead of wrapping it.
TCL's package search mechanism uses the "glob" command to recursively search directories specified in the auto_path variable to find packages. Unfortunately the glob command does not work on wrapped files or their directories. This means TCL's package require command will not descend subdirectories when searching for packages. However, the fix for this is simple. Add the desired package's file path to the auto_path variable before using the package require command. This can be done with two lines of code similar to:
lappend auto_path /tcl/lib/mypkg1.0 ;# Ensure our application can find the files
package require mypackage
Script only extensions
Packages consisting only of TCL/TK scripts are generally easy to wrap.
As an example, let us consider the Efftcl 1.0 extension with the following files.
c:\tcl\lib\efftcl1.0\efftcl.tcl
c:\tcl\lib\efftcl1.0\pkgIndex.tcl
c:\tcl\lib\efftcl1.0\scripts\AFTER.TCL
c:\tcl\lib\efftcl1.0\scripts\ANIMATE.TCL
c:\tcl\lib\efftcl1.0\scripts\APPOINT.TCL
c:\tcl\lib\efftcl1.0\scripts\BALLOON.TCL
c:\tcl\lib\efftcl1.0\scripts\BIND.TCL
c:\tcl\lib\efftcl1.0\scripts\BUSY.TCL
c:\tcl\lib\efftcl1.0\scripts\CALENDAR.TCL
c:\tcl\lib\efftcl1.0\scripts\CANVAS.TCL
c:\tcl\lib\efftcl1.0\scripts\CLRDIAL.TCL
c:\tcl\lib\efftcl1.0\scripts\CLRMENU.TCL
c:\tcl\lib\efftcl1.0\scripts\CONFIRM.TCL
c:\tcl\lib\efftcl1.0\scripts\DIALOG.TCL
c:\tcl\lib\efftcl1.0\scripts\EMAIL.TCL
c:\tcl\lib\efftcl1.0\scripts\FILESEL.TCL
c:\tcl\lib\efftcl1.0\scripts\FONT.TCL
c:\tcl\lib\efftcl1.0\scripts\GAUGE.TCL
c:\tcl\lib\efftcl1.0\scripts\HIERLIST.TCL
c:\tcl\lib\efftcl1.0\scripts\NOTEBOOK.TCL
c:\tcl\lib\efftcl1.0\scripts\NOTICE.TCL
c:\tcl\lib\efftcl1.0\scripts\PANEDWIN.TCL
c:\tcl\lib\efftcl1.0\scripts\PERCENT.TCL
c:\tcl\lib\efftcl1.0\scripts\PLACARD.TCL
c:\tcl\lib\efftcl1.0\scripts\PRINTER.TCL
c:\tcl\lib\efftcl1.0\scripts\RADIOBOX.TCL
c:\tcl\lib\efftcl1.0\scripts\SCRLFORM.TCL
c:\tcl\lib\efftcl1.0\scripts\TABNBOOK.TCL
c:\tcl\lib\efftcl1.0\scripts\TCLINDEX
c:\tcl\lib\efftcl1.0\scripts\TEXTDISP.TCL
c:\tcl\lib\efftcl1.0\scripts\TOOLBAR.TCL
c:\tcl\lib\efftcl1.0\images\flag.gif
c:\tcl\lib\efftcl1.0\images\back.xbm
c:\tcl\lib\efftcl1.0\images\arrow.xbm
c:\tcl\lib\efftcl1.0\images\fwd.xbmCreate a text file containing this list of files (one file name per line). For our example, we will name the file effList.txt.
Add the following two lines to our application, ourprog.tcl, in order to use the efftcl package.
lappend auto_path /tcl/lib/efftcl1.0 ;# Ensure our application can find the files
package require Efftcl
Remember, TCL's use of the package name is case sensitive
Wrap the application using the following command line.
freewrap ourprog.tcl -f effList.txt
Extensions containing binary files
Wrapped applications can load TCL/TK shared binary extensions that have been compiled with the new TEA (i.e. stubs) interface. This is done using either a package require or load command. It is easiest if the shared library is used as a file separate from the wrapped program.
As an alternative (not necessarily recommended), it is possible to include shared binary libraries in the wrapping, but they cannot be directly loaded from their wrapped state. They must first be written to disk, then loaded from the new disk location. This task of course, is the responsibility of the application programmer. Following is an example of how this might be done.
Use the following procedure in your application, teststub.tcl, to load the wrapped binary extension.
proc freewrap_load {libfile args} {
# This procedure should be used instead of the normal LOAD command when
# using binary extensions with freeWrap.
#
# Returns: On success, the full file path to the shared library on the local file system.
# On failure, an error message starting with the text "Load Error: "
#
global env
set rtnval {}
set fpath [::freewrap::unpack $libfile]
if {[string length $fpath] == 0} {
set rtnval "Load Error: Copying of shared library $libfile failed."
} {
if {[file mtime $libfile] > [file mtime $fpath]} {
# The wrapped library file is newer than the existing one on disk.
# Let's delete the existing one first, then copy the newer file.
if {[catch {file delete -force $fpath}]} {
set fpath {}
set rtnval {Load Error: Unable to delete older copy of shared library.}
} {
set fpath [::freewrap::unpack $filetemp]
if {[string length $fpath] == 0} {
set rtnval {Load Error: Unable to replace older copy of shared library.}
}
}
}
}
if {[string length $rtnval] == 0} {
# No errors, so far. Let's load the shared library.
if {[catch "load \{$fpath\} $args" result]} {
set rtnval "Load Error: $result"
} { set rtnval $fpath }
}
return $rtnval
}The example code above will copy the file expressed by the variable libfile to a temporary directory then load it from there.
Create the executable program and include the shared library file.
freewrap teststub.tcl example.dll
The wm iconbitmap command can even load an icon that is contained within a wrapped application. Assuming that the icon file /myproject/libfiles/myicon.ico has been wrapped into your application, the following command can be used to display it as the icon of the main window.
Example: wm iconbitmap . /myproject/libfiles/myicon.ico
::freewrap namespace
FreeWrap now has a namespace which contains all of the freeWrap specific variables, commands and procedures. These variables, commands and procedures may be referenced using the ::freewrap:: prefix or imported into any other namespace.
Variables
The following variables are defined in the ::freewrap namespace of each wrapped application.
Name
Description
encrypted
Set to 1 if attached scripts are encrypted. Otherwise, set to 0.
patchLevel
Revision level of the freeWrap program used to wrap the application.
progname
The proper name for the freeWrap program for the current operating system. This is normally freewrap.exe under Windows and freewrap under UNIX.
scriptFile
This variable contains a list of executing script files when freeWrap's source replacement procedure is used. The last file name in the list is the currently running script name and will be returned by an [info script] command.
It is important to note that all freeWrapped applications contain a copy of the freeWrap program itself. The first part of a wrapped application consists of this freeWrap "stub". Therefore, knowing the size of this freeWrap stub, it is possible to extract freeWrap from the wrapped application and copy it to another file.
Procedures
The following procedures are defined in the ::freewrap namespace of each wrapped application. The commands names starting with shell_ are only available under the Windows operating system.
Name
Arguments
Description
getStubSize
[execname]
Retrieves the current size of the freeWrap stub associated with the file execname . This function returns the size in bytes or 0, if the stub size cannot be determined.
isSameRev
file_name
Checks whether the specified file contains a copy of the same freeWrap revision as the currently executing program.
Returns: 0, if file does not contain a copy and 1, if file contains a copy.
iswrapped
file_name
Determines whether the file named file_name is a freeWrapped application.
If file_name is a freeWrapped application this procedure returns a value of 1.
If file_name is NOT a freeWrapped application this procedure returns a value of 0.
pkgName, appName
Reattaches the freeWrap core to pkgName, a file included in the current freeWrapped application. The recombined freeWrapped application is copied to the file appName. pkgName must be the archive portion of a freeWrapped application.
shell_assoc_exist
extension
Check whether a key exists for an extension
Example: shell_assoc_exist .txt => 1
Example: shell_assoc_exist .NEVER => 0shell_fileType_exist
fileType
Determine whether a file type exists
Example: shell_fileType_exist txtfile => 1
Example: shell_fileType_exist NEVER => 0shell_fileExtension_setup
extension, fileType
Creates a file extension and associates it with fileType.
Example: shell_fileExtension_setup .txt txtfileRemove connection between extension and fileType
Example: shell_fileExtension_setup .txt ""shell_fileType_setup
fileType, title
Creates a file type.
Example: shell_fileType_setup txtfile "Text Document"shell_fileType_open
fileType, openCommand
Creates a open command. Sets action for double click.
Example: shell_fileType_open txtfile "C:\\WINDOWS\\NOTEPAD.EXE %1"shell_fileType_print
fileType, printCommand
Creates a print command for right mouse button menu.
Example: shell_fileType_print txtfile "C:\\WINDOWS\\NOTEPAD.EXE /p %1"}shell_fileType_icon
fileType, icon
Sets an icon for a fileType.
Example: shell_fileType_icon txtfile "C:\\WINDOWS\\SYSTEM\\shell32.dll,-152"
Example: shell_fileType_icon txtfile "C:\\mydir\\myicon.ico"We can give a name.ico file or a dll or exe file here. If a dll or exe file is used the index for the resource inside the file must be specified
shell_fileType_quickView
fileType, quickViewCmd
Sets the command to execute to perform a quick view for a fileType.
Example: shell_fileType_quickView txtfile "write.exe %1"shell_fileType_addAny_cmd
fileType, cmdName, cmd
Adds any command you want to a fileType.
Example: shell_fileType_addAny_cmd scrfile config "%1"shell_fileType_setMenuName
fileType, cmdName, str
Change description in right mouse menu for a command associated with a fileType.
Example: shell_fileType_setMenuName txtfile print "Print file"shell_fileType_showExt
fileType, yesOrNo
Always show the extension on the fileType.
Example: shell_fileType_showExt txtfile 1Turn off "Always show" of extension on the fileType
Example: shell_fileType_showExt txtfile 0shell_fileType_setCmdOrder
fileType, cmds
Over-ride the default ordering of commands on right mouse menu.
Example: shell_fileType_setCmdOrder txtfile {print open}shell_fileType_neverShowExt
fileType, yesOrNo
Never show extension on fileType.
Example: shell_fileType_neverShowExt txtfile 1Turn off "Never show" of extension on the fileType.
Example: shell_fileType_neverShowExt txtfile 0shell_getCmds
file
Retrieves all the commands assocated with an extension.
Example: shell_getCmds file.txt => open printshell_getCmd_imp
file, cmd
Retrieves the implimentation of a command given a file extension and command.
Example: shell_getCmd_imp test.txt open => C:\\WINDOWS\\NOTEPAD.EXE %1
unpack
file_name, [destdir]
This function unpacks file_name from a freeWrapped application's ZVFS archive into a file system directory. The destination directory for the file may be specified with the optional destdir argument. If this optional argument is not specified, the function will select a temporary directory appropriate for the operating system. Unpack, on success, returns the full path to the newly created file and on failure, an empty string. This function is useful for creating local copies of wrapped shared libraries (e.g. DLLs) that can then be loaded into your wrapped TCL/TK application.
Commands
The following TCL commands are defined in the ::freewrap namespace of each wrapped application. The encrypt and decrypt commands are used by freeWrap in the performance of its tasks.
Name
Arguments
Description
decrypt
string_to_decrypt
Decrypts a string that has been encrypted by the freewrap_encrypt command.
Returns the decrypted string.
encrypt
string_to_encrypt
Encrypts the specified string using a simple algorithm.
Returns the encrypted string.
getSpecialDir
dirType
Find "Start Menu", "Desktop" and similar directory locations under Windows. DirType must be one of the following strings:
DESKTOP
INTERNET
PROGRAMS
CONTROLS
PRINTERS
PERSONAL
FAVORITES
STARTUP
RECENT
SENDTO
BITBUCKET
STARTMENU
DESKTOPDIRECTORY
DRIVES
NETWORK
NETHOOD
FONTS
TEMPLATES
COMMON_STARTMENU
COMMON_PROGRAMS
COMMON_STARTUP
COMMON_DESKTOPDIRECTORY
APPDATA
PRINTHOOD
ALTSTARTUP
COMMON_ALTSTARTUP
COMMON_FAVORITES
INTERNET_CACHE
COOKIES
HISTORY
shortcut
linkPath
?-objectPath objectPath?
?-description description?
?-workingDirectory dir?
?-icon path index?
?-arguments args?
Creates a Windows shortcut. The only required parameter is the linkPath. This means you can create a shortcut with no target, which probably isn't useful. The icon of the shortcut will default to the icon of the target item if not specified.
Argument
Explanation
linkPath
The path to the shortcut file (including the extension .lnk)
objectPath
The target of the link
description
Shortcut description
workingDirectory
Working (startup) directory for the target of the shortcut
path index (icon)
Specifies the path to a file and the index of the icon in that file to use for the shortcut
args
Arguments passed to the target of the shortcut when started.
source
file_name
The TCL source command has been renamed and placed into the ::freewrap namespace. The source command has been redefined by freeWrap to handle encrypted ZVFS script files as well as normal scripts. Therefore, ::freewrap::source should not normally be used.
The numerous encoding files available with the TCL distribution have not been compiled into the freeWrap application. Including all the encoding files into freeWrap would have significantly increased the size of freeWrap executables. Only a single encoding file, cp1252.enc, has been included (as the default encoding) in freeWrap.
For single language, non-english TCL/TK applications the programmer many wish to use the computer system's default encoding. This can be done with the following TCL command:
encoding system identity
However, for those people wishing to use several alternate encodings, the TCL encoding files can be wrapped along with the program scripts. The character encoding files themeselves are available from the normal TCL distribution. Instructions on how to use the encoding files follow.
Simply wrap the desired encoding file into your application. At wrap time you must make sure to specify the full path to the encoding file.
Example: freewrap myprog.tcl C:\tcl\lib\tcl8.3\encoding\cp1250.enc
Ensure that the path to the encoding file's directory is included in your auto_path variable. Remember, that freeWrap strips the drive letter from the path before storing the file.
Example : lappend auto_path /tcl/lib/tcl8.3/encoding
Use the full path name, excluding the file extension, when referring to the encoding file.
Example : encoding system /tcl/lib/tcl8.3/encoding/cp1250
Under freeWrap, the encoding names command is not able to list your wrapped encoding file. However, the other encoding commands will work correctly.
The Windows version of freeWrap now includes the tcl84pip.dll file from the normal TCL distribution. This file is necessary when running scripts that redirect stdin/stdout through pipes using the open or exec commands. Tcl84pip.dll is actually an executable program that helps do the redirection of stdin and stdout when exec ing programs under Windows. Make sure that tclpip84.dll can be found in a location that TCL normally looks (e.g the current directory, the Windows directory or the same directory as the executable program).
Here is some documentation for ZVFS as used in freeWrap. This information has been modified from that provided by D. Richard Hipp for his ZVFS.
Send comments to freewrapmgr@users.sourceforge.net