.. Reminder for header structure:
Level 1: ====================
Level 2: --------------------
Level 3: ++++++++++++++++++++
Level 4: """"""""""""""""""""
Level 5: ^^^^^^^^^^^^^^^^^^^^
.. meta::
:description: (For software editors) Applying best practices to packaging software
:keywords: WAPT, packaging, best practice, documentation
.. _software_packaging_best_practices:
####################################################################
(For software editors) Applying best practices to packaging software
####################################################################
.. note::
`_benwa `_ is a system administrator and he has authorized Tranquil IT to republish his excellent rant on reddit `Developers, you can make sysadmins happier `_.
*********************
Environment variables
*********************
* Environmental variables `have been around since DOS `_.
They can make your (and my) life easier.
*******************
Program directories
*******************
* Not every system uses :file:`C:\\` as the main drive. Some enterprises use folder redirection, and relocate the Documents folder.
Some places in the world do not speak English and their directories reflect that. **Use those environmental variables to make your programs just work**:
* :file:`%SystemDrive%` is the drive where :file:`%SystemRoot%` is located.
You most likely do not need to actually know this;
* :file:`%SystemRoot%` is where the Windows directory is located.
You hopefully do not care about this. Leave the Windows directory alone;
* :file:`%ProgramFiles%` is where you should place your program files, preferable in a :file:`Company\Program` structure;
* :file:`%ProgramFiles(x86)%` is where you should place your 32-bit program files.
Please update them for 64-bit. 32-bit will eventually be unsupported, and business will be waiting for you to get your shit together for far longer than necessary;
* :file:`%ProgramData%` is where you should store data that is not user specific, but still needs to be written to by users (Users do not have write access to this folder either).
Your program should not require administrator rights to run as you should not have us writing to the :file:`%ProgramFiles%` directory.
Also, do not throw executables in here.
* ``%Temp%`` is where you can process temporary data.
Place that data within a unique folder name (maybe a generated GUID perhaps) so you do not cause an incompatibility with another program.
Windows will even do the cleanup for you. Don't put temporary data in in :file:`%ProgramData%` or :file:`%ProgramFiles%`;
* :file:`%AppData%` is where you can save the user running your program settings.
This is a fantastic location that can by synced with a server and used to quickly and easily migrate a user to a new host and keep all of their program settings. Don't put giant or ephemeral files here.
You could be the cause of a very slow login if you put the wrong stuff here and a host needs to sync it up. **DON'T PUT YOUR PROGRAM FILES HERE**.
The business decides what software is allowed to run, not you and a bunch of users who may not know how their company's environment is set up;
* :file:`%LocalAppData%` is where you can put bigger files that are specific to a user and computer. You do not need to sync up a thumbnail cache.
They will not be transferred when a user migrates to a new host, or logs into a new VDI station, or terminal server.
**DON'T PUT YOUR PROGRAM FILES HERE EITHER**;
.. note::
More and more of you software editors offer *portable* versions of your software that will install in and run from :file:`%AppData%` or :file:`%LocalAppData%`. Your aim is to let users install software even though they are not Local Administrators and you market that as a feature, although it is more of a security NOGO.
Even worse, you tend to make it difficult to find the proper :mimetype:`.msi` that would allow your customers to correctly install your software in :file:`%ProgramFiles%`.
Please, make it easy to find your :mimetype:`.msi` that will install in :file:`%ProgramFiles%`, this way you will make your customer AppLock and Software Restriction Policies work well and their sysadmins happy.
You can get these directory paths through `API calls `_ as well if you do not / can not use environmental variables.
****
Logs
****
* Use the `Windows Event Log `_ for logging.
It will handle the rotation for you and a sysadmin can forward those logs or do whatever they need to. You can even make your own little area just for your program.
***********
Error codes
***********
* Use `documented Error Codes `_ when exiting your program.
********
Printing
********
* Use the `Windows printing API `_ and do not use direct printing in your program.
************
Distribution
************
* Distribute your program in `MSI `_.
It is the standard for Windows installation files (even though Microsoft sometimes doesn't use it themselves).
* `Sign your installation file and executables `_.
It is how we know it is valid and can whitelist in `AppLocker `_ or other policies.
.. note::
Applocker and `Software Restriction Policies `_
can be very effective and the **management of these policies can be made simpler with WAPT**.
******
Update
******
* Want to have your application update for you? That can be fine if the business is okay with it.
You can create a scheduled task or service that runs elevated to allow for this without granting the user administration rights.
I like the way Chrome Enterprise does it: gives a GPO to set update settings, the max version it will update to (say 81.* to allow all minor updates automatically and major versions are manual), and a service.
They also have a GPO to prevent user-based installs;
.. note::
WAPT is designed for businesses that do not allow users to run software updates, which is the policy often chosen in large security conscious enterprises.
***************
Version numbers
***************
* Use `semantic versioning `_ (should go in the version property in the installer file and in the Add/Remove Programs list, not in the application title) and have a `changelog `_.
You can also have your installer download at a predictable location to allow for automation.
A published update path is nice too;
.. note::
If you apply this practice, then you will make system administrators who deploy your software updates using the
:ref:`WAPT function def_update() ` **very happy**!!
***
GPO
***
* ADMX templates are dope;
.. note::
We completely agree with you _benwa on this at Tranquil IT.
If developers advise their customers to use GPOs to deploy their software or system or users settings, then, **they **MUST** know that GPOs are not fully reliable**.
Instead, package your software, your system and user configurations using WAPT.
A :file:`setup.py` is so much easier than an :mimetype:`.xml` file for system admins to audit before deploying.
WAPT packages can be applied recursively to trees of Organizational Units, so your WAPT package will behave in production exactly as a GPO would, **just much easier**.
***************
License dongles
***************
* USB license dongles are a sin. Use a regular software or network license.
I am sure there are off the shelf ones so you don ot have to reinvent the wheel;
.. note::
You can make your software accept a license key as a parameter in your :mimetype:`.msi` executable.
WAPT can be used to assign license keys to individual workstations at install using a :ref:`method that ensures that the license key can not be read during transport `.
Then, if you want your software to call home to check on the validity of the license, make the routine work with
:ref:`proxies `.
**********
Networking
**********
* Don't use that damn custom IPv4 input field. Use FDQNs. IPv6 had been around since 1998 and will work with your software if you just give it a chance;
* The Windows Firewall (I can not really say much about third party ones) is going to stay on.
Know the difference between an incoming and outgoing rule.
Most likely, your server will need incoming.
Most likely, you clients will not even need an outgoing.
Set those up at install time, not launch time.
Use Firewall Groups so it is easy to filter.
Do not use Any rules if you can help it.
The goal isnot to make it work, it is to make it work securely.
If you do not use version numbers in your install path, you might not even have to remake those rules after every upgrade;
.. _proper_use_of_proxy_in_software:
* Proxies are good for hygiene and proxies are now a default security feature not just in corporate IT environments, but even on small networks.
Making your software not compatible with proxies will require the network administrators of your customer to make and maintain special rules in their firewall, just for you.
It is easy to code your software to work with proxies, so please do!
****
PDFs
****
* Do not ship a software that requires allowing JavaScript to run in PDF readers.
Business logic should be run before outputting to a PDF, not after.
.. note::
:mimetype:`.pdf` is the file format people use by default to exchange documents.
PDF readers are meant to display documents, not execute unsigned programs.