1. Getting start creating WAPT packages¶
1.1. Setting up your WAPT development and test environment¶
1.1.1. Prerequisites¶
Attention
It is required to be a Local Administrator of the host to use WAPT’s integrated environment for developing WAPT packages.
We advise you to create/ edit packages in a fully controlled environment that is safe and disposable.
The usage of a disposable virtual host (like Virtualbox) is recommended.
Import the tis-waptdev package in your local repository and install it on your development computer.
1.1.2. Recommendations regarding the test environment¶
The recommended method to correctly test your WAPT packages is to use representative sample of hosts in your inventory. So the more heterogeneous your installed base of hosts, the larger your sample should be.
This method consists of testing the installation of the package on as many platforms and configurations as possible, so to improve its reliability, before the WAPT package is transferred to production repositories.
1.1.3. Testing method¶
1.1.3.1. Operating systems and architectures¶
Windows XP;
Windows 7;
Windows 10;
Windows Server 2008 R2;
Windows Server 2012 and R2;
x86;
x64;
Physical and virtual hosts;
Laptops.
When possible, RC and Beta version of Operating Systems should be tested.
1.1.3.2. State of Windows Updates¶
Microsoft Windows host without any Windows update installed: the objective is to detect Windows updates that are required for the software to work properly and to adapt the WAPT package accordingly;
Microsoft Windows host with all the latest Windows updates: the objective is to detect Windows updates that break the package and to adapt the WAPT package accordingly;
1.1.3.3. State of software installations¶
Hosts with many installed packages: the objective is to detect a possible dependency with an existing application;
Hosts with many installed packages: the objective is to detect a possible conflict with an existing application;
Install older versions of the software: it is possible that the software installer does not support uninstalling a previous version of the software, in this case, the WAPT package will have to remove older versions of the software before installing the new version;
1.2. Principles of creating package template from the WAPT Console¶
Attention
To create WAPT packages directly from the WAPT Console, it is necessary to have installed the WAPT development environment tis-pyscripter3. It is NOT recommended to use tis-pyscripter4.
We recommand you to download the waptdev package instead and install it on your computer on which you will create WAPT packages.
If you do not remember how to download a package from the Tranquil IT store, please see how to download package in your private repository.
If you do not remember how to install a package, please see how to install a package on a host.
1.2.1. Creating a package template from the WAPT Console¶
In that example, we use the 7-zip MSI setup downloaded from the 7-zip official website.
Create a WAPT package Template from the installer.
In the WAPT Console, click on
:Select the downloaded MSI setup file and fill in the required fields. Verify that the package name does not contains any version number.
Two solutions are available:
Click on Make and edit … (recommended) to verify the WAPT package and customize it to your Organization’s specific needs.
Click on Build and upload to directly build and upload the package into your private repository.
Attention
The button Build and upload directly uploads the package into the private repository without testing.
This method works relatively well with MSI installers because their installation is more standardized.
However, the first method that consists of first testing locally the package before uploading is the recommended method.
1.2.2. Customizing the WAPT package before uploading it to the repository¶
Before uploading a package to your WAPT repository, you may choose to customize its behavior to your Organization’s needs by editing it with PyScripter.
When creating the package template, click on Make and edit ….
The PyScripter IDE launches automatically to allow you to edit files in the WAPT package.
1.2.3. Presentation of PyScripter¶
1.2.3.1. PyScripter project explorer¶
The PyScripter project explorer lists the different files that you might need, notably the control
file and the setup.py
file.
1.2.3.2. Run Configurations¶
The Run option in the project explorer of:program:PyScripter will allow you to launch actions on the packages that you are editing.
1.2.3.3. Editor panel¶
The edition panel in PyScripter allows to edit the setup.py
file and the control
file.
1.2.3.4. Python console¶
This is the Python console visible in PyScripter, it will allow you to display the python output when you execute Run commands.
You can also use it to test/ debug portions of your script setup.py
.
To learn more about the composition of a WAPT package, visit the documentation on the structure of a WAPT package.
1.2.3.5. Testing locally the installation of the WAPT package¶
You can then test the launch of an installation on your development station.
The PyScripter console allows you to check whether the installation went well.
1.2.3.6. Testing locally the uninstallation of the WAPT package¶
You can then test the uninstall script on your development station.
The PyScripter console allows you to check whether the uninstallation went well.
1.3. Creating your first WAPT Packages¶
1.3.1. Packaging .msi packages (example)¶
For this example we will take tightvnc.
You can download it here.
Now, you can then generate your package template, please refer to the documentation for creating packages from the WAPT Console.
Edit the control
file (architecture
, impacted_process
, target_os
, description
, maintainer
…).
For more information, visit the documentation on the control file structure.
Your PyScripter opens, go to your setup.py
:
# -*- coding: utf-8 -*-
from setuphelpers import *
uninstallkey = []
def install():
print('installing tis-tightvnc')
install_msi_if_needed('tightvnc-2.8.5-setup-64bit.msi')
The function will test whether a version of the software is already installed on the host using the uninstall key.
If the uninstall key is already present, the new version of the software will be installed only if the installed version is older.
After the installation, the function will finally test that the uninstall key is present and its version, to ascertain that all went well.
Options (Default Option) |
Description |
---|---|
|
Defines the minimal version above which the software will update. |
|
Lists the programs to kill before installing the package. |
|
Defines the accepted codes other than 0 and 3010 returned by the function. |
|
Defines the maximum installation wait time (in seconds). |
|
Defines the additional properties to pass as arguments to MSI setup file. |
|
Defines the value passed as parameter to control the version number instead of the value returned by the installed_softwares function. Ex |
|
Automatically removes an older version of a software whose uninstall key is identical. |
|
Forces the installation of the software even though the same uninstall key has been found. |
The wapt-get install_msi_if_needed method searches for an uninstall key in the MSI file properties, it is not necessary to fill it manually in the setup.py
file.
You also do not have to fill in killbefore
if the value specified in the impacted_process
field of the control
file is correct.
Note
The setup.py
could have looked like this, but the method is less elegant because it does less checking.
# -*- coding: utf-8 -*- from setuphelpers import * uninstallkey = ["{8B9896FC-B4F2-44CD-8B6E-78A0B1851B59}"] def install(): print('installing tis-tightvnc') run('msiexec /norestart /q /i "tightvnc-2.8.5-setup-64bit.msi"')
Run the installation and see what happens when the software is already installed.
wapt-get -ldebug install C:\waptdev\tis-tightvnc-wapt
Installing WAPT file C:\waptdev\tis-tightvnc-wapt
MSI tightvnc-2.8.5-gpl-setup-64bit.msi already installed. Skipping msiexec
Results:
=== install packages ===
C:\waptdev\tis-tightvnc-wapt | tis-tightvnc (2.8.5.0-1)
1.3.1.1. Passing additional arguments¶
To pass additional arguments, store them in a dict.
# -*- coding: utf-8 -*-
from setuphelpers import *
uninstallkey = []
properties = {
'SERVER_REGISTER_AS_SERVICE': 0,
'SERVER_ADD_FIREWALL_EXCEPTION': 0,
'ADDLOCAL': 'Server,Viewer'
}
def install():
print(u'Installation en cours de TightVNC')
install_msi_if_needed('tightvnc-2.8.5-setup-64bit.msi', properties = properties )
Note
The setup.py
could have looked like this, but the method is less elegant because it does less checking.
# -*- coding: utf-8 -*- from setuphelpers import * uninstallkey = ["{8B9896FC-B4F2-44CD-8B6E-78A0B1851B59}"] def install(): print('installing tis-tightvnc') run('msiexec /norestart /q /i "tightvnc-2.8.5-setup-64bit.msi" SERVER_REGISTER_AS_SERVICE=0 SERVER_ADD_FIREWALL_EXCEPTION=0')
1.3.1.2. Video demonstration¶
1.3.2. Packaging .exe packages (example)¶
Download the .exe installer from a reliable source.
Download the installer in exe format Firefox ESR x64 on https://download.mozilla.org/?product=firefox-esr-latest-ssl&os=win64.
Look up documentation relating to silent flags:
On the Official Mozilla website.
Other methods for finding information on silent flags:
Search on the Internet with the search terms: Firefox silent install.
Then generate your package template, please refer to the documentation for creating packages from the WAPT Console. PyScripter loads up and opens the .exe package project.
Edit the
control
file (architecture
,impacted_process
,target_os
,description
,maintainer
…). For more information, visit the documentation on the control file structure.Check the
control
file content. Mozilla Firefox-ESR does not comply to industry standards and returns an erroneous version number (it appears to be the installer packaging software version number).Original
control
file.package : tis-firefox-esr version : 4.42.0.0-0 architecture : all section : base priority : optional maintainer : user description : automatic package for firefox setup 52.6.0esr impacted_process :
Modified
control
file.package : tis-firefox-esr version : 52.6.0-1 architecture : all section : base priority : optional maintainer : Tranquil-IT Systems description : Mozilla Firefox 52.6.0 ESR impacted_process : firefox.exe
A sub-version -1 has been appended to the software version number; it is the packaging version of the WAPT package.
It allows the Package Developer to release several WAPT package versions of the same software, very useful for very rapid and iterative development.
Using install_exe_if_needed
The function is slightly the same as that used with .msi installers, with some differences:
The function requires to pass the silent flag as an argument.
The function requires to pass the uninstall key as an argument.
# -*- coding: utf-8 -*-
from setuphelpers import *
uninstallkey = []
def install():
print('installing tis-firefox-esr')
install_exe_if_needed("Firefox Setup 45.5.0esr.exe",silentflags="-ms",key='',min_version="4.42.0.0")
Options (Default Option) |
Description |
---|---|
|
Defines the silent parameters to pass as arguments to the installer. |
|
Defines the software uninstall key. |
|
Defines the minimal version above which the software will update. |
|
Lists the programs to kill before installing the package. |
|
Defines the accepted codes other than 0 and 3010 returned by the function. |
|
Defines the maximum installation wait time (in seconds). |
|
Defines the value passed as parameter to control the version number instead of the value returned by the installed_softwares function. Example https://forum.tranquil.it/viewtopic.php?t=1337 |
|
Automatically removes an older version of a software whose uninstall key is identical. |
|
Forces the installation of the software even though the same uninstall key has been found. |
The package will then have this behavior:
Firefox will install only if Firefox is not yet installed or if the installed version of Firefox is less than 45.5.0, unless the
--force
option is passed as argument when installing the package.On installing, the running firefox.exe processes will be killed (with the value indicated in
impacted_process
of thecontrol
file).The function will add by itself the uninstall key, so leave the uninstall key argument empty.
When finishing the installation of the package, the function will check that the uninstall key is present on the host and that the version of Firefox is greater than 45.5.0; if this not the case, the package will be flagged as ERROR.
1.3.2.1. Finding the uninstallation key¶
Unlike .msi files, the key to uninstall an .exe is not in the file properties.
So you need to install the software first to know the uninstall key.
Therefore you MUST start once the installation from PyScripter with the run configuration and then install.
Once the software is installed, go to the WAPT Console, then find your development host.
In the Software inventory tab find the software title and copy the value indicated in the uninstallkey column.
You MUST also check the value of the version with the value indicated in min_version
in your setup.py
.
Modify your setup.py
with the new parameters:
# -*- coding: utf-8 -*-
from setuphelpers import *
uninstallkey = []
def install():
print('installing tis-firefox-esr')
install_exe_if_needed("Firefox Setup 45.5.0esr.exe",silentflags="-ms",key='Mozilla Firefox 45.5.0 ESR (x64 fr)',min_version="45.5.0")
To test that your key works correctly, you MUST run an installation again in PyScripter.
WAPT should not attempt to install the software because it is already present, the following message should display:
>>>
*** Remote Interpreter Reinitialized ***
Command Line : install "c:\waptdev\tis-firefox-esr_x64_PROD_fr-wapt\WAPT\.."
Using config file: C:\Program Files (x86)\wapt\wapt-get.ini
Installing WAPT files c:\waptdev\tis-firefox-esr_x64_PROD_fr-wapt
Exe setup Firefox_Setup_78.7.1esr.exe already installed. Skipping
Results:
=== install packages ===
c:\waptdev\tis-firefox-esr_x64_PROD_fr-wapt | tis-firefox-esr (78.7.1-102)
Now you can now test the uninstallation:
You can now build and upload your package, please refer to the documentation for build and upload packages from the WAPT Console.
Note
If you leave the uninstallkey blank, uninstalling your package will not work.
1.3.2.2. Special case of a non-silent uninstaller¶
In some particular cases, a package using install_exe_if_needed fills in the uninstall key, but the uninstall key points to a non silent uninstaller.
We have to circumvent that problem by using a function that will remove the uninstall key at the end of the installation.
:emphasize-lines: 13
# -*- coding: utf-8 -*-
from setuphelpers import *
uninstallkey = []
def install():
install_exe_if_needed("setup.exe",
silentflags="/s",
key='{D9E87643-0005-447E-9111-78697A9C1595}',
min_version="14.0")
uninstallkey.remove('{D9E87643-0005-447E-9111-78697A9C1595')
def uninstall():
run(r'"C:\Program Files\Kutl\uninstall.exe" /supersilent')
Hint
The uninstall feature can also be used to run code in addition to uninstalling software, ex: delete folder, delete shortcut …
1.3.2.3. Video demonstration¶
1.3.3. Packaging empty packages¶
1.3.4. Building the package and sending it to the WAPT Server¶
Once the package is ready, build it and send it to the WAPT Server.
Select the package in the
c:\waptdev
folder.
Confirm the selected package.
You have just uploaded your first wapt package.
Warning
Once your package has uploaded, refresh the package list using the Refresh packages list button or by pressing F5 on your keyboard.
1.3.4.1. Working with non standard return codes¶
Return codes are used to feed back information on whether a software has installed correctly.
In Windows, the standard successful return code is [0].
If you know that your WAPT packages installs correctly, yet you still get a return code other than [0]
, then you can explicitly tell WAPT to ignore the error code by using the parameter accept_returncodes
.
You can find out how to use the accept_returncodes
parameter by exploring this package code.
# -*- coding: utf-8 -*-
from setuphelpers import *
import re
uninstallkey = []
def is_kb_installed(hotfixid):
installed_update = installed_windows_updates()
if [kb for kb in installed_update if kb['HotFixID' ].upper() == hotfixid.upper()]:
return True
return False
def waiting_for_reboot():
# Query WUAU from the registry
if reg_key_exists(HKEY_LOCAL_MACHINE,r"SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired") or \
reg_key_exists(HKEY_LOCAL_MACHINE,r"SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending") or \
reg_key_exists(HKEY_LOCAL_MACHINE,r'SOFTWARE\Microsoft\Updates\UpdateExeVolatile'):
return True
return False
def install():
kb_files = [
'windows10.0-kb4522355-x64_af588d16a8fbb572b70c3b3bb34edee42d6a460b.msu',
]
with EnsureWUAUServRunning():
for kb_file in kb_files:
kb_guess = re.findall(r'^.*-(KB.*)-',kb_file)
if not kb_guess or not is_kb_installed(kb_guess[0]):
print('Installing {}'.format(kb_file))
run('wusa.exe "{}" /quiet /norestart'.format(kb_file),accept_returncodes=[0,3010,2359302,-2145124329],timeout=3600)
else:
print('{} already installed'.format(kb_file))
if waiting_for_reboot():
print('A reboot is needed!')
Hint
The full list of Windows Installer Error Messages can be found by visiting this page.
2. How to code WAPT packages¶
2.1. Simple examples of commonly used setuphelper functions¶
Presentation of several functions implemented in Setuphelpers and frequently used to develop WAPT packages.
2.1.1. Testing and manipulating folders and files¶
2.1.1.1. Creating a path recursively¶
Command makepath makes the path variable for C:\Program Files (x86)\Mozilla\Firefox
.
makepath(programfiles,'Mozilla','Firefox')
2.1.1.2. Creating and destroying directories¶
Command mkdirs creates the directory C:\test
.
mkdirs('C:\\test')
Command remove_tree destroys the directory C:\tmp\target
.
remove_tree(r'C:\tmp\target')
2.1.1.3. Checking if a path is a file or a folder¶
Command isdir checks whether C:\Program Files (x86)\software
is a directory.
isdir(makepath(programfiles32,'software')):
print('The directory exists')
Command isfile checks whether C:\Program Files (x86)\software\file
is a file.
isfile(makepath(programfiles32,'software','file')):
print('file exist')
2.1.1.4. Checking whether a directory is empty¶
Command dir_is_empty checks that directory C:\Program Files (x86)\software
is empty.
dir_is_empty(makepath(programfiles32,'software')):
print('dir is empty')
2.1.1.5. Copying a file¶
Command filecopyto copies file.txt
into the C:\Program Files (x86)\software
directory.
filecopyto('file.txt',makepath(programfiles32,'software'))
2.1.1.6. Copying a directory¶
Command copytree2 copies the sources
folder into the C:\projet
directory.
copytree2('sources','C:\\projet')
2.1.2. Manipulating registry keys¶
2.1.2.1. Checking the existence of a registry key¶
Command registry_readstring checks if registry key {8A69D345-D564-463c-AFF1-A69D9E530F96} exists in registry path SOFTWARE\Google\Update\Clients
of HKEY_LOCAL_MACHINE.
if registry_readstring(HKEY_LOCAL_MACHINE, "SOFTWARE\\Google\\Update\\Clients\\{8A69D345-D564-463c-AFF1-A69D9E530F96}", 'pv'):
print('key exist')
2.1.2.2. Showing the value of a registry key¶
Command registry_readstring reads the value {8A69D345-D564-463c-AFF1-A69D9E530F96} stored in the registry path SOFTWARE\Google\Update\Clients
of HKEY_LOCAL_MACHINE.
print(registry_readstring(HKEY_LOCAL_MACHINE, r'SOFTWARE\Google\Update\Clients\{8A69D345-D564-463c-AFF1-A69D9E530F96}', 'pv'))
2.1.2.3. Modifying the value of a registry key¶
Command registry_setstring modifies the value of the registry key TOUVersion stored in the registry path SOFTWARE\Microsoft\Windows Live
of HKEY_CURRENT_USER.
registry_setstring(HKEY_CURRENT_USER, "SOFTWARE\\Microsoft\\Windows Live\\Common",'TOUVersion','16.0.0.0', type=REG_SZ)
2.1.3. Creating and destroying shortcuts¶
With WAPT setuphelper it is possible to create different types of shortcuts.
2.1.3.1. Creating a desktop shortcut for all users¶
Command create_desktop_shortcut creates the shortcut WAPT Console Management into C:\Users\Public
directory pointing to C:\Program Files (x86)\wapt\waptconsole.exe
; the shortcut is available for all users.
create_desktop_shortcut(r'WAPT Console Management',target=r'C:\Program Files (x86)\wapt\waptconsole.exe')
2.1.3.2. Removing a desktop shortcut for all users¶
Command remove_desktop_shortcut deletes the WAPT Console Management shortcut from the folder C:\Users\Public
; the shortcut is deleted for all users.
remove_desktop_shortcut('WAPT Console Management')
Firefox places a shortcut on the all users desktop, we are going to delete it.
We will use the remove_desktop_shortcut function:
Modify your
setup.py
and use the function like this.# -*- coding: utf-8 -*- from *SetupHelpers* import * uninstallkey = [] def install(): install_exe_if_needed("Firefox Setup 45.5.0esr.exe",silentflags="-ms",key='Mozilla Firefox 45.5.0 ESR (x64 fr)',min_version="45.5.0") remove_desktop_shortcut('Firefox')
If you restart the installation from PyScripter, you will notice that the “all users” desktop shortcut has disappeared.
2.1.3.5. Creating a desktop shortcut for a logged in user¶
Hint
These functions are used in session_setup context.
Command create_user_desktop_shortcut creates the shortcut WAPT Console Management on user desktop pointing to C:\Program Files (x86)\wapt\waptconsole.exe
.
create_user_desktop_shortcut(r'WAPT Console Management',target=r'C:\Program Files (x86)\wapt\waptconsole.exe')
2.1.3.6. Removing a desktop shortcut for a logged in user¶
Command remove_user_desktop_shortcut deletes the WAPT Console Management shortcut from the logged in user’s desktop.
remove_user_desktop_shortcut('WAPT Console Management')
2.1.4. Manipulating ini files¶
2.1.4.1. Reading a value in a section of a ini file¶
Command inifile_readstring will read a value from a key and a section of a ini file.
inifile_writestring("file.ini","global","key")
2.1.4.2. Writing a value in a section of a ini file¶
Command inifile_writestring will modify a value from a key and a section of a ini file.
inifile_writestring("file.ini","global","key","value")
2.1.4.3. Deleting a key in a section of a ini file¶
Command inifile_deleteoption will delete a key in a given section of a ini file.
inifile_deleteoption("file.ini","global","key")
2.1.4.4. Deleting an entire section of a ini file¶
Command inifile_deletesection will delete a section of a ini file and all of its content.
inifile_deletesection("file.ini","global")
2.1.5. Windows environment/ Software/ Services¶
2.1.5.1. Retrieving the version of a file¶
Command get_file_properties shows package properties.
get_file_properties(makepath(programfiles32,'InfraRecorder','infrarecorder.exe'))['ProductVersion']
2.1.5.2. Checking the Windows version¶
Command windows_version checks that the Windows version is strictly inferior to 6.2.0.
windows_version()<Version('6.2.0'):
Hint
For more informations you can visit Microsoft Windows version number.
2.1.5.3. Checking for 64bits architecture¶
Command iswin64 checks that the system architecture is 64bits.
if iswin64():
print('Pc x64')
else:
print('Pc not x64')
2.1.5.4. Checking for the Program Files variable¶
programfiles;
print(programfiles())
programfiles32;
print(programfiles32())
programfiles64;
print(programfiles64())
Each command returns a different ProgramFiles location.
For example, command programfiles64 returns native Program Files directory, eg. C:\Program Files (x86)
on either win64 or win32 architecture and programfiles() will return the path of the 32bit Program Files directory, eg. Programs Files (x86)
on win64 architecture, and Programs Files
on win32 architecture.
2.1.5.5. Checking for the AppData variable¶
user_appdata/ user_local_appdata
Hint
These functions are used with session_setup
Command user_appdata returns roaming AppData profile path of logged on user (C:\Users\%username%\AppData\Roaming
).
print(user_appdata())
Command user_local_appdata returns the local AppData profile path of the logged on user (C:\Users\%username%\AppData\Local
).
print(user_local_appdata())
2.1.5.6. Disabling temporarily the wow3264 file redirection¶
Command disable_file_system_redirection disables wow3264 redirection in the current context.
with disable_file_system_redirection():
filecopyto('file.txt',system32())
2.1.5.7. Obtaining the current logged in user¶
Command get_current_user shows the currently logged on username.
print(get_current_user())
2.1.5.8. Obtaining the computer name¶
Command get_computername shows the name of the computer.
print(get_computername())
2.1.5.9. Obtaining the AD domain to which the computer is joined¶
Command get_domain_fromregistry returns the FQDN of the computer.
get_domain_fromregistry()
2.1.6. Actions on installed software¶
2.1.6.1. Checking installed software¶
Command installed_softwares returns the list of installed software on the computer from registry in an array.
installed_softwares('winscp')
[{'install_location': u'C:\\Program Files\\WinSCP\\', 'version': u'5.9.2', 'name': u'WinSCP 5.9.2', 'key': u'winscp3_is1', 'uninstall_string': u'"C:\\Program Files\\WinSCP\\unins000.exe"', 'publisher': u'Martin Prikryl', 'install_date': u'20161102', 'system_component': 0}]
2.1.6.2. Obtaining the uninstall command from registry¶
Command uninstall_cmd returns the silent uninstall command.
uninstall_cmd('winscp3_is1')
"C:\Program Files\WinSCP\unins000.exe" /SILENT
2.1.6.3. Uninstalling software¶
for soft in installed_softwares('winscp'):
if Version(soft['version']) < Version('5.9.2'):
run(uninstall_cmd(soft['key']))
For each item of the list return by installed_softwares containing keyword winscp.
If the version is lower than 5.9.2.
Then uninstall using the uninstall_cmd and specifying the corresponding uninstallkey.
2.1.6.4. Killing tasks¶
Command killalltasks kills all tasks with the specified name.
killalltasks('firefox')
2.1.7. Using control file fields¶
It is possible to use control file informations on setup.py
.
2.1.7.1. Obtaining packages version¶
def setup():
print(control['version'])
Command print(control['version']) shows the version value from the control
file.
def setup():
print(control['version'].split('-',1)[0])
Command print(control['version'].split('-',1)[0]) shows the software version number without the WAPT version number from the control
file.
2.1.7.2. Obtaining software title names¶
Todo
upcoming documentation
2.1.8. Managing a WAPT package with another WAPT package¶
2.1.8.1. Installing a package¶
WAPT.install('tis-scratch')
Command install installs a WAPT package on the selected computer.
2.1.8.2. Removing a package¶
WAPT.remove('tis-scratch')
Command remove uninstalls a WAPT package from the selected computer.
2.1.8.3. Forgetting a package¶
WAPT.forget_packages('tis-scratch')
Command forget_packages informs the WAPT Agent to forget a WAPT package on the selected computer.
Hint
If the desired result is to remove tis-scratch, you should either reinstall the package (wapt-get install "tis-scratch"
) then remove it (wapt-get remove "tis-scratch"), either removing it manually from the Control Panel menu .
2.2. Improving my package¶
2.2.1. Copying a file¶
It is possible to configure Firefox with a policies.json
file.
See https://github.com/mozilla/policy-templates/blob/master/README.md.
This file MUST be placed in the distribution
folder at the root of Firefox.
To help you create this policies.json
file you can use the enterprise policy generator generator for Firefox.
When you have generated your policies.json
file, place it in c:\waptdev\prefix-firefox-esr-wapt\policies.json
.
The distribution
folder at the root of Firefox may not exist, so we will test its existence and create it with the mkdirs command if it does not exist:
if not isdir(r'C:\Program Files\Mozilla Firefox\distribution'):
mkdirs(r'C:\Program Files\Mozilla Firefox\distribution')
Important
If you have backslashes in your path, you should always put an r in front of the string, like in the previous example.
You will also need to use the filecopyto
function to copy the policies.json
file:
filecopyto('policies.json',r'C:\Program Files\Mozilla Firefox\distribution')
Hint
There is no need to put the full path for the source file since the policies.json
file is at the root of the WAPT package, so we use the relative path.
Modify your setup.py
:
# -*- coding: utf-8 -*-
from setuphelpers import *
uninstallkey = []
def install():
install_exe_if_needed("Firefox Setup 45.5.0esr.exe",silentflags="-ms",key='Mozilla Firefox 45.5.0 ESR (x64 fr)',min_version="45.5.0")
remove_desktop_shortcut('Firefox')
if not isdir(r'C:\Program Files\Mozilla Firefox\distribution'):
mkdirs(r'C:\Program Files\Mozilla Firefox\distribution')
filecopyto('policies.json',r'C:\Program Files\Mozilla Firefox\distribution')
Your package is now ready to apply a configuration. You can launch an installation with PyScripter and validate that the package works according to your objective.
Finally, launch your Firefox to verify that it will work for your users.
2.2.2. Uninstalling unwanted versions¶
Hint
At each step of these examples you can run an installation to test the result.
In our case we want to uninstall the non ESR version of Firefox.
We will look for the other software installed on the host to check if a non-esr version of Firefox is installed.
To reproduce our example, download and install the latest consumer version of Firefox:
To search unwanted version of Firefox we will use the
installed_softwares
function. This function returns a dictionary list containing the software properties:print(installed_softwares('Firefox')) [ { 'install_date': '', 'install_location': 'C:\\Program Files\\Mozilla Firefox', 'key': 'Mozilla Firefox 78.7.1 ESR (x64 fr)', 'name': 'Mozilla Firefox 78.7.1 ESR (x64 fr)', 'publisher': 'Mozilla', 'system_component': 0, 'uninstall_string': '"C:\\Program Files\\Mozilla Firefox\\uninstall\\helper.exe"', 'version': '78.7.1', 'win64': True }, { 'install_date': '', 'install_location': 'C:\Program Files (x86)\\Mozilla Firefox', 'key': 'Mozilla Firefox 79.0 (x86 fr)', 'name': 'Mozilla Firefox 79.0 (x86 fr)', 'publisher': 'Mozilla', 'system_component': 0, 'uninstall_string': '"C:\Program Files (x86)\\Mozilla Firefox\\uninstall\\helper.exe"', 'version': '79.0', 'win64': False } ]
Check the name of each software.
for uninstall in installed_softwares('Mozilla Firefox'): print(uninstall['name'])
Show the name of each software found.
for uninstall in installed_softwares('Mozilla Firefox'): if not 'ESR' in uninstall['name']: print(uninstall['name'])
Show the name of each software found which does not include the string ESR in its name and its uninstallkey.
for uninstall in installed_softwares('Mozilla Firefox'): if not 'ESR' in uninstall['name']: print(uninstall['name']) print('Uninstall ' + uninstall['key'])
We will now use a WAPT trick using the uninstall_cmd function:
Install cmd accepts an uninstall key as an argument and will send the command to run to start the silent uninstall.
for uninstall in installed_softwares('Mozilla Firefox'): if not 'ESR' in uninstall['name']: print(uninstall['name']) print('Uninstall ' + uninstall['key']) silent_uninstall = uninstall_cmd(uninstall['key']) print('Run ' + silent_uninstall)
Start the uninstallation.
for uninstall in installed_softwares('Mozilla Firefox'): if not 'ESR' in uninstall['name']: print(uninstall['name']) print('Uninstall ' + uninstall['key']) silent_uninstall = uninstall_cmd(uninstall['key']) print('Run ' + silent_uninstall) run(silent_uninstall)
We can also uninstall the Mozilla maintenance service:
for uninstall in installed_softwares('MozillaMaintenanceService'):
run(uninstall_cmd(uninstall['key']))
Finally, modify your
setup.py
:# -*- coding: utf-8 -*- from setuphelpers import * uninstallkey = [] def install(): #Install firefox if necessary install_exe_if_needed("Firefox Setup 45.5.0esr.exe",silentflags="-ms",key='Mozilla Firefox 45.5.0 ESR (x64 fr)',min_version="45.5.0") #Removal of the firefox shortcut on the all user desktop remove_desktop_shortcut('Firefox') #Creation of the distribution folder if it does not exist if not isdir(r'C:\Program Files\Mozilla Firefox\distribution'): mkdirs(r'C:\Program Files\Mozilla Firefox\distribution') #Copy of the policies.json file found at the root of the package in the destination of the distribution folder filecopyto('policies.json',r'C:\Program Files\Mozilla Firefox\distribution') #For each Mozilla Firefox installed for uninstall in installed_softwares('Mozilla Firefox'): #If the software does not have the word ESR in the name if not 'ESR' in uninstall['name']: print(uninstall['name']) print('Uninstall ' + uninstall['key']) #Looking for how we can uninstall it silently silent_uninstall = uninstall_cmd(uninstall['key']) print('Run ' + silent_uninstall) #We launch the previous command. run(silent_uninstall) #Uninstalling mozilla maintenance service for uninstall in installed_softwares('MozillaMaintenanceService'): run(uninstall_cmd(uninstall['key']))
Your code now handles the uninstallation of unwanted versions of Firefox.
2.2.3. Improving setup.py to use variables¶
Examples of variable usage:
version_firefox = "45.0"
uninstallkey = "Mozilla Firefox " + version_firefox + " ESR (x64 fr)"
print(uninstallkey)
uninstallkey = "Mozilla Firefox %s ESR (x64 fr)" % (version_firefox)
print(uninstallkey)
uninstallkey = "Mozilla Firefox {} ESR (x64 fr)".format(version_firefox)
print(uninstallkey)
uninstallkey = f"Mozilla Firefox {version_firefox} ESR (x64 fr)"
print(uninstallkey)
Important
The last example is the best example but this operation only works with Python3.
We can now use variables in our setup.py
:
# -*- coding: utf-8 -*- from setuphelpers import * uninstallkey = [] def install(): version_firefox = "45.5.0" #Install firefox if necessary install_exe_if_needed("Firefox Setup %sesr.exe" % version_firefox,silentflags="-ms",key='Mozilla Firefox %s ESR (x64 fr)' % version_firefox,min_version=version_firefox) #Removal of the firefox shortcut on the all user desktop remove_desktop_shortcut('Firefox') distribution_folder=r'C:\Program Files\Mozilla Firefox\distribution' #Creation of the distribution folder if it does not exist if not isdir(distribution_folder): mkdirs(distribution_folder) ... The rest of the code does not change ...
Hint
You can retrieve the version number shown in the control
file like this:
version_firefox = control.get_software_version()
2.2.4. Customizing the user environment¶
It is sometimes necessary to customize a software in user context to set specific settings or to comply to the Organization’s rules and preferences:
Creating user desktop shortcut with specific arguments.
Making changes to user Windows registry keys.
Making changes to files, to browser settings of the user.
Configuring shortcuts to the Organization’s set of templates for Documents, Spreadsheets or Presentations in Office Suites to encourage or insure that editorial and graphical guidelines are followed.
Setting up the user’s email or instant messaging from the Organization’s main user data repository (LDAP directory, database, etc).
Customizing an office suite or business software based on the Organization’s main user data repository (LDAP directory, database, etc).
The session_setup function benefits from the power of python to achieve a high level of automation.
2.2.4.1. Principles of session_setup¶
The WAPT session_setup function is executed for each user using:
C:\Program Files (x86)\wapt\wapt-get.exe session-setup ALL
Calling that function executes the session_setup script defined within each WAPT package installed on the computer.
The WAPT Agent stores in its local database (C:\Program Files (x86)\wapt\waptdb.sqlite
) the instruction sets of all WAPT packages.
Attention
The session_setup script is launched only once per WAPT package version and per user.
The WAPT Agent stores in is local %appdata%\wapt\waptsession.sqlite
database the instances of the session_setup scripts that have been already been played.
Output example of wapt-get session-setup ALL
:
Note
The logged in user session_setup has already previously been launched.
wapt-get session-setup ALL
Configuring tis-7zip ... No session-setup. Done
Configuring tis-ccleaner ... Already installed. Done
Configuring tis-vlc ... No session-setup. Done
Configuring tis-tightvnc ... No session-setup. Done
Configuring tis-paint.net ... No session-setup. Done
Configuring wsuser01.mydomain.lan ... No session-setup. Done
2.2.4.2. Using session_setup¶
The session_setup scripts are located in the section def session_setup() of the setup.py
file:
Example:
def session_setup():
registry_setstring(HKEY_CURRENT_USER, "SOFTWARE\\Microsoft\\Windows Live\\Common",'TOUVersion','16.0.0.0', type=REG_SZ)
Attention
With session_setup, there is no possibility to call files contained inside the WAPT package.
To call external files when uninstalling, copy and paste the needed files in an external folder during the package installation process (example: c:\cachefile
).
2.2.4.3. Example: creating a personalized desktop shortcut¶
One of the possibilities offered by Setuphelpers is adding personalized shortcuts on user desktops, instead of a desktop shortcut common to all users.
For that purpose, we will use the create_user_desktop_shortcut()
function to create shortcuts containing the username and passing a website as an argument to Firefox.
# -*- coding: utf-8 -*-
from setuphelpers import *
uninstallkey = []
def install():
install_exe_if_needed("Firefox Setup 45.5.0esr.exe",silentflags="-ms",key='Mozilla Firefox 45.4.0 ESR (x64 fr)',min_version="45.5.0")
def session_setup():
create_user_desktop_shortcut("Mozilla Firefox de %s" % get_current_user(),r'C:\Program Files\Mozilla Firefox\firefox.exe',arguments="-url https://tranquil.it")
Now start the
session-setup
directly from PyScripter.Finally, check that the icon is present on the desktop.
2.2.5. Using the audit functions for compliance¶
Note
This feature is available in the Enterprise version.
The audit function allows to make regular checks to desktop configurations and to centralize the results of these checks in the WAPT Console. This feature allows you to ascertain that your installed base of hosts matches your set of conformity rules over time.
For example you can:
Regularly check the list of local administrators on the desktops.
Ascertain over time the correct configuration of a critical software.
Regularly check the presence of the correct version of a piece of software.
Ascertain the security settings of a workstation.
The audit
function benefits from the depth and the breadth of python libraries for unmatched levels of precision and finesse for your auditing needs.
2.2.5.1. Working principle¶
The audit
tasks are launched once after every wapt-get upgrade, then regularly as defined by the audit_schedule
attribute.
To manually launch an audit check, you may also use the following command:
wapt-get audit
Note
By default, the audit
function will not launch if the audit is not necessary.
To force the execution, you may launch the following command:
wapt-get audit -f
The audit
script is defined in the package’s setup.py
with a function def audit()
:
In this example, we are improving the Firefox package previously studied in this documentation.
Add the
audit
function in thesetup.py
.def audit(): if isfile(r'C:\Program Files\Mozilla Firefox\distribution\policies.json'): print('File policies.json found') return "OK" else: print('File policies.json not found') return "ERROR"
Start the audit from PyScripter.
Test with the file then delete the
C:\Program Files\Mozilla Firefox\distribution\policies.json
file and test again with PyScripter.
You can directly see the status of the audit in the WAPT Console (Click on the package then on the audit column):
The audit function returns one of these 3 values:
OK;
WARNING;
ERROR.
Attention
With the audit function, it is not possible to use files that are contained in the WAPT packages.
To use files embedded in the WAPT package that will be used for an audit, you MUST instruct to copy the file(s) to a temporary folder when the WAPT package installs.
2.2.5.2. Planning an audit¶
The audit tasks are launched once after every upgrade, then regularly as defined with the audit_schedule
value.
The value is contained in the control
file of the WAPT package.
By default, if audit_schedule
is empty, the audit task can be launched manually from the WAPT Console or be launched automatically if you have defined the option waptaudit_task_period
in the wapt-get.ini
of the WAPT Agent.
For more information about the last method, please see this documentation.
Otherwise, the periodicity may be indicated in several ways:
An integer (in minutes).
An integer followed by a letter (m = minutes, h = hours , d = days , w = weeks).
2.2.5.3. Default behavior of the audit function¶
By default, the only audit function checks the presence of UninstallKey for its WAPT package.
This way, WAPT ascertains that the software is still present on the host, according to the host configuration.
2.2.6. Auditing configurations to insure compliance¶
Note
This feature is available in the Enterprise version.
The audit_data
function allows to make regular checks to desktop configurations and to centralize the results of these checks in the WAPT Console.
There is historization and you can encrypt your data and decrypt it with your WAPT certificate.
For example you can:
Change an administrator password, encrypt information and display it on your WAPT Console.
Regularly check the modification your computer needs like CVE or GLPI inventory.
Ascertain the security settings of a workstation and historize issues.
The
audit_data
function is usable in theaudit
function only.
2.2.6.1. Working principle¶
The audit_data
functions are launched if they are defined in the def audit()
section of the setup.py
file.
On the server side, audit data is stored in the HostAuditData table.
The content of the table can be queried using the Reporting tab in the WAPT Console.
The Data is automatically purged according to expiration date.
When WAPT host update_status()
is launched, the newer audit data is sent to the WAPT Server.
On the Client side, the audit data is stored in the host database with an expiration date (date_expiration) and the max count (max_count) of the stored data is defined in the code.
In this example, we are checking public IP on the computer.
Add the
audit_data
function inside theaudit
function in thesetup.py
.def audit(): ip = wgets('https://api.ipify.org',verify_cert=False) print(f'My public IP address is: {ip}') WAPT.write_audit_data_if_changed('Public IP','log for %s' % get_computername(),ip,max_count=5) return 'OK'
Here are the functions related to audit_data
:
def write_audit_data_if_changed(self, section, key, value, ptype=None, value_date=None, expiration_date=None, max_count=2, keep_days=None): """Write data only if different from last one """ def write_audit_data(self, section, key, value, ptype=None, value_date=None, expiration_date=None, max_count=2, keep_days=None): """Stores in database a metrics, removes expired ones Args: section (str) key (str) value (any) value_date expiration_date (str) : expiration date of the new value max_count (int) : keep at most max_count value. remove oldest one. keep_days (int) : set the expiration date to now + keep_days days. override expiration_date arg if not None Returns: None """ def read_audit_data(self, section, key, default=None, ptype=None): """Retrieve the latest value associated with section/key from database""" def read_audit_data_set(self, section, key): """Retrieve all the values associated with section/key from database""" def delete_audit_data(self, section, key): def read_audit_data_since(self, last_query_date=None): """Retrieve all the values since a date from database"""
2.2.7. Updating automatically a software package¶
Note
This part of the documentation is for advanced users of WAPT.
The update_package
functions are very practical, they allow to gain a lot of time when needing to update a WAPT package with the most recent version of a piece of software.
2.2.7.1. Working principle¶
The update_package function will:
Fetch online the latest version of the software.
Download the latest version of the software binaries.
Remove old versions of the software binaries.
Update the version number of the software in the
control
file.
If you base your install function on the version number inside the control
file, then you do not even need to modify your setup.py
.
You just have to do your usual Quality Assurance tests before you build-upload your new package.
2.2.7.2. Example¶
Here is the update_package script for firefox-esr as an example:
def update_package():
import re,requests,glob
#Retrieving the last file name
url = requests.head('https://download.mozilla.org/?product=firefox-esr-latest&os=win64',proxies={}).headers['Location']
filename = url.rsplit('/',1)[1].replace('%20',' ')
#download of it if is not in the package
if not isfile(filename):
print('Downloading %s from %s'%(filename,url))
wget(url,filename)
#removing old exe with wrong name
for fn in glob.glob('*.exe'):
if fn != filename:
remove_file(fn)
# updates control version from filename, increment package version.
control.version = '%s-0'%(re.findall('Firefox Setup (.*)esr\.exe',filename)[0])
control.save_control_to_wapt()
You may launch the update_package in PyScripter:
You will find many inspiring examples of update_package scripts in packages hosted in the Tranquil IT store.
2.2.8. Deploying a portable software with WAPT¶
A good example of a WAPT package is a self-contained/ portable software package:
Create the folder for the software in
C:\Program Files (x86)
.Copy the software in that folder.
Create the shortcut to the application.
Manage the uninstallation process for the application.
Close the application if it is running.
2.2.8.1. Example with ADWCleaner¶
First, download Adwcleaner.
You can then generate your package template, please refer to the documentation for creating packages from the WAPT Console.
The file C:\waptdev\tis-adwcleaner-wapt
is created.
Here you will find an example of a portable package that takes almost all the WAPT functions of a setup.py
:
from setuphelpers import *
uninstallkey = []
exe_name = 'AdwCleaner.exe'
path_adw = makepath(programfiles,'AdwCleaner')
path_exe = makepath(path_adw,exe_name)
nameshortcut = 'AdwCleaner'
def install():
mkdirs(path_adw)
filecopyto(exe_name,path_exe)
create_desktop_shortcut(nameshortcut,path_exe)
def uninstall():
remove_tree(path_adw)
remove_desktop_shortcut(nameshortcut,path_exe)
def audit():
if not isfile(path_exe):
print('File not found')
return "OK"
else:
print('File Found')
return "ERROR"
def update_package():
wget('https://downloads.malwarebytes.com/file/AdwCleaner',exe_name)
control.version = get_file_properties(exe_name)['FileVersion'] + '-0'
control.save_control_to_wapt()
2.2.9. Packaging Windows Update .msu packages¶
Hint
Pre-requisites: to build WAPT packages, the WAPT development environment MUST be installed.
Between Patch Tuesday releases, Microsoft may release additional KBs or critical updates that will need to be pushed to hosts quickly.
For that purpose, WAPT provides a package template for .msu files.
In that example, we use the KB4522355 downloaded from Microsoft Catalog website.
Download KB4522355 MSU package from Microsoft Catalog website.
Create a WAPT package template from the downloaded .msu file. In the WAPT Console, click on
.Select the downloaded .msu package and fill in the required fields.
Click on Make and edit (recommended) to launch package customization.
WAPT package IDE is launched using the source code from the pre-defined .msu template.
As usual with WAPT packages, test, then build, then sign, then upload and finally affect the desired WAPT packages to your selected hosts and it is done!!
If the KB becomes bundled with the following Patch Tuesday, you can select the hosts onto which the package has been applied and forget the KB package on the hosts.
2.2.10. Packaging simple Linux packages¶
Before starting, we assume several conditions:
You have a graphical interface on your Linux system that you use for developing and testing packages.
You have installed the vscode package from the Tranquil IT repository.
Your user is named linuxuser and is a member of the sudoers group.
2.2.10.1. Creating a base template from you linux computer¶
Start up a Command Line utility.
As linuxuser, create a WAPT package template.
wapt-get make-template <template_name>
Warning
Do not launch this command as root or with a sudo.
When you create a template, there will be several files in the .vscode folder inside the WAPT package folder:
settings.json
;launch.json
.
Example with VLC:
wapt-get make-template "tis-vlc" Using config file: /opt/wapt/wapt-get.ini Template created. You can build the WAPT package by launching /opt/wapt//wapt-get.py build-package /home/linuxuser/waptdev/tis-vlc-wapt You can build and upload the WAPT package by launching /opt/wapt//wapt-get.py build-upload /home/linuxuser/waptdev/tis-vlc-wapt
Hint
All WAPT packages are stored in linuxuser’s home (home of the currently logged in user).
VSCode loads up and opens the WAPT package project.
Check the
control
file content.You have to give a
description
to the WAPT package, define theos_target
and theversion
of the WAPT package.Hint
os_target
for unix is linux.Warning
The software
version
number in yourcontrol
file MUST start at 0, and not the version number of the software title, as the version number may not be the same as displayed in the DEB / YUM repository.Original
control
file.package : tis-vlc version : 0-0 architecture : all section : base priority : optional maintainer : user description : automatic package for vlc
Modified
control
file.package : tis-vlc version : 0 architecture : all section : base priority : optional maintainer : Tranquil-IT Systems description : VLC for linux target_os : linux min_wapt_version : 1.8
Note
It is to be noted that a sub-version -1 has been added. It is the packaging version of the WAPT package.
It allows the WAPT package Developer to release several WAPT package versions of the same software, very useful for very rapid and iterative development.
Make changes to the code in the
setup.py
file accordingly.:emphasize-lines: 8 # -*- coding: utf-8 -*- from setuphelpers import * uninstallkey = [] def install(): apt_install('vlc')
Save the package.
2.2.10.2. Managing the uninstallation¶
Make changes to the
setup.py
file with an uninstall.
def uninstall(): apt_remove('vlc')
Launch a remove from VSCode Run Configurations.
Check that the software has been correctly removed.
dpkg -l | grep vlc
Hint
In the uninstall() function, it is not possible to call for files included inside the WAPT package. To call files from the package, it is necessary to copy/ paste the files in a temporary directory during package installation.
2.2.10.3. Managing the session-setup¶
Make changes to the
setup.py
file with asession-setup
;In this example, we will create a file
vlcrc
by default in the user profile.def session_setup(): vlcrc_content="""[qt] # Qt interface qt-notification=0 qt-privacy-ask=0 metadata-network-access=0 """ vlcdir = os.path.join(os.environ['HOME'], '.config', 'vlc') path_vlrc = makepath(vlcdir,'vlcrc') ensure_dir(vlcdir) if not isfile(path_vlrc): with open(makepath(vlcdir,'vlcrc')) as f: f.write(vlcrc_content)
Launch a session-setup from VSCode Run Configurations.
2.2.10.4. Building and uploading the WAPT package¶
You will find the WAPT package in your ~/waptdev
folder.
You need to transfer the WAPT package folder to the Windows host that has the private key that you use to sign your WAPT packages.
Then, please refer to the documentation for building and uploading packages from the WAPT Console.
2.2.11. Encrypting sensitive data contained in a WAPT package¶
Note
This part of the documentation is for advanced users of WAPT.
This feature is available only in the Enterprise version.
2.2.11.1. What is the purpose for doing that?¶
With WAPT, the integrity of the package is ensured. A package whose content has been modified without being re-signed will systematically be refused by the WAPT client.
On the other hand, the content of a WAPT package is not encrypted and will be readable by everyone. This technical model of transparency brings nevertheless many benefits.
This can be annoying in the case of a package that contains a password, a license key, or any sensitive or confidential data.
Fortunately, we have a solution!
2.2.11.2. Working principle¶
When a WAPT Agent registers with the WAPT Server, it generates a private key/ public certificate pair in C:\Program Files (x86)\wapt\private
.
The certificate is sent to the WAPT Server with the inventory when the WAPT client is first registered.
The private key is kept by the Agent and is only readable locally by the Local Administrators.
We will therefore encrypt the sensitive data contained inside the package with the certificate belonging to the host.
During installation, the WAPT Agent will be able to decrypt the sensitive data using its private key.
With this mode of operation, the WAPT Server and secondary repositories have no knowledge of the sensitive data.
2.2.11.3. Practical case¶
You will find here an example of a WAPT package where we encrypt a string of text in an update_package function and then decrypt this text in the install function.
In this example, the update_package function allows us to browse the WAPT Server database to retrieve the certificate from each host and then encrypt the sensitive text with it.
The encrypted text for each host is then stored in a encrypt-txt.json
file at the root of the WAPT package.
When the WAPT package installs, the WAPT Agent will take the encrypted text and decipher it with his own private key.
You can test it by yourself by downloading the example package tis-encrypt-sample.
Attention
The python output (log install of the WAPT package) is readable by the users on the host, so you should not display the deciphered text with a print during installation.
3. Using different IDEs for developing WAPT packages¶
3.1. Configuring WAPT to use supported IDEs¶
If you are used to work with another IDE, you can be relieved now as WAPT supports many popular text editors.
Note
Using a supported IDE will launch the WAPT package project with a valid debug configuration.
3.1.1. On Windows¶
Text editor name |
Text editor logo |
---|---|
PyScripter |
|
Visual Studio Code |
|
Visual Studio Codium |
To configure another editor for WAPT, you MUST modify the editor_for_packages
attribute in the [global]
section of your WAPT Console’s %LOCALAPPDATA%\waptconsole\waptconsole.ini
configuration file.
[global]
...
editor_for_packages = vscode
3.1.2. On Linux / macOS¶
Text editor name |
Text editor logo |
---|---|
Visual Studio Code |
|
Visual Studio Codium |
|
Nano |
|
Vim |
To configure another editor for WAPT, you MUST modify the editor_for_packages
attribute in the [global]
section of your WAPT Agent configuration file: /opt/wapt/wapt-get.ini
.
By default, if the editor_for_packages
attribute is empty, WAPT will try to launch (in that order):
vscodium;
vscode;
nano;
vim;
vi.
[global]
...
editor_for_packages = vim
3.2. Configuring WAPT to use a custom editor¶
[global]
...
editor_for_packages = C:\Program Files\Notepad++\notepad++.exe {setup_filename}
[global]
...
editor_for_packages = /opt/pycharm/bin/pycharm_x64 {wapt_sources_dir}
3.2.1. Custom arguments¶
Argument |
Description |
---|---|
|
Launches custom editor and edit WAPT package |
|
Launches custom editor and edit WAPT package |
|
Launches the custom text editor and opens the WAPT package folder. |
|
Launches the custom text editor and opens the WAPT install folder. |