User Tools

Site Tools


proj:wininstallers

Home

Project

Windows NSIS Installer Notes

Make Package

  • Update sofawin/licence.txt if necessary
  • cd C:\sofa_dev_win\sofastatistics
  • git pull (SSH passphrase “matilda loves linux better”)
  • bring across licence.txt if changed
  • Copy contents of C:\sofa_dev_win\sofastatistics\sofastats over top of C:\sofa_dev_win\packaging\sofastats (leaving behind tests, eclipse project files, pycache folders, and any exes such as convert.exe and wkhtmltopdf.exe)
  • Eliminate debug = True (esp dev_debug = True in home.py)
  • Delete build and dist folders under C:\sofa_dev_win\packaging\sofastats (to ensure clean build)
  • Create executable
cd C:\sofa_dev_win\packaging\sofastats\
pyinstaller sofastats.spec
  • Under C:\sofa_dev_win\packaging\sofastats\ copy everything but pycache, build, and dist into dist\sofastats.
  • Change the version at the top of In C:\sofa_dev_win\1 sofastats.nsi:
!define SOFA_VERSION "1.5.2"
  • In C:\sofa_dev_win\ right click on “1 sofastats.nsi” and “compile NSIS script” then click on “Test Installer” button.
  • Run SOFA from icon on Desktop
  • (Assuming OK) copy sofastats-1.5.2_for_win.exe to the USB for safe-keeping
  • Compress to zip folder so sofastats-x.x.x_for_win.zip

Windows Development and Packaging

In short, how we get from a clean Windows machine to a development (to fix Windows-specific bugs) and packaging environment for SOFA.

Create working folders

Make C:\sofa_dev_win

Under that put:

  • sofastatistics (actually, don't make it directly - instead, add it when cloning the git repo). This is the code. Make changes here to get SOFA working on Windows and push the changes up into origin.
  • packaging folder - everything used for packaging goes in here. Put contents of sofastatistics under the packaging/sofastats folder and add launch.py, import2run.py, and sofastats.spec as well from sofa_dev_win.
  • store - put junk here to avoid polluting / overcomplicating other folders

Python and dependencies installed

Set up prerequisites for running SOFA working on Windows at all - install Python 3.7 and all required pip and system dependencies (perhaps PostgreSQL)

Must pip install as admin and install into “C:\Program Files (x86)\Python37-32\” e.g. ..\lib\site-packages

Run

cmd

ctrl-shift Enter to run terminal as admin

"C:\Program Files (x86)\Python37-32\python.exe" -m pip install requests

Re: PostgreSQL: use weak password for throw-away PG 11 installation on Win 10.

Get dev toolchain working e.g. eclipse, git

Install git and git bash etc

Change remote as required so has ssh in it.

Use OpenSSH-generated key made for Windows machine. Don't try to reuse Linux one - bad practice.

Extras if paint self in corner with SSH key:

https://stackoverflow.com/questions/50918607/remove-cached-password-for-git-on-windows

Reinstalling won't solve it. You will have to update it in your Credential Manager.

Go to Control Panel > User Accounts > Credential Manager > Windows Credentials.

You will see Git credentials in the list (e.g. git:https://...).

Click on it, update the password, and execute git pull/push command from your Git bash and it it won't throw any error message.

cd C:\sofa_dev_win
git clone https://git.launchpad.net/sofastatistics

Get SOFA working on Windows

cd "C:\sofa_dev_win\sofastatistics\sofastats\"
"C:\Program Files (x86)\Python37-32\python.exe" -m sofastats.start

Iron out inevitable bugs.

The pathlib library is a good start when working with Windows path names (a common source of problems).

Need to Reload() wx.html2 widget after SetPage when on Windows.

Install pyinstaller

Run

cmd

ctrl-shift Enter to run terminal as admin

"C:\Program Files (x86)\Python37-32\python.exe" -m pip install pyinstaller

Set launch.py dependency imports

Run special script <specify properly here> to identify actual dependencies so they can be called by launch.py

#import CUBRID-Python ## 2014 Python 2 only
import PIL
import PyPDF2
import adodbapi
import agw
import numpy
import openpyxl
#import pgdb  ## part of psycopg2 installation
import psycopg2
import pylab
import pymysql
import requests
import sqlite3
import win32api
import win32com
import win32con
import wx
import wx.dataview
import wx.grid
import wx.html2
import wx.lib
import wx.lib.agw
import wx.lib.agw.hyperlink
import wx.lib.agw.hypertreelist

import import2run

Note - must specify standard library modules called upon and also explicitly call submodules as required e.g.

import sqlite3
import wx.dataview
import wx.grid
import wx.html2
import wx.lib
import wx.lib.agw
import wx.lib.agw.hyperlink
import wx.lib.agw.hypertreelist

Otherwise errors like: ModuleNotFoundError: No module named 'wx.lib.agw.hypertreelist'

Identify Windows C Runtime (CRT) dependency path

This dependency is required if using Python >= 3.5 and Windows systems < Windows 10. I.e. it is required.

E.g. C:\Windows\WinSxS\x86_microsoft-windows-m..namespace-downlevel_31bf3856ad364e35_10.0.17134.1_none_50c6cb8431e7428f

See https://github.com/pyinstaller/pyinstaller/issues/1566#issuecomment-342916812. Note - the end part of the full path

(e.g. …_31bf3856ad364e35_10.0.17134.1_none_50c6cb8431e7428f) will vary but there will only be one on your system

Context at: https://pyinstaller.readthedocs.io/en/v3.3.1/usage.html#windows

This dependency will be used as an argument in the pyinstaller command run later e.g.

--path C:\Windows\WinSxS\x86_microsoft-windows-m..namespace-downlevel_31bf3856ad364e35_10.0.17134.1_none_50c6cb8431e7428f

Run pyinstaller for full run (making spec and using)

Note - usually people only use the –onedir option to start with for debugging reasons and the –onefile option later.

We want the –onedir option during development because it allows us to inject in the py modules we want into the folder so the exe will use them instead of what was originally baked in. In short, we can override individual modules while testing until we are happy. We could use the –onefile option to create a self-contained binary at that point but I like exposing the code - certainly makes it much, much easier to fix problems.

Edit import2run.py if required to ensure it is actually importing SOFA and not just printing output as a test

The actual command:

cd C:\sofa_dev_win\packaging\sofastats\
pyinstaller --clean --exclude start --path C:\Windows\WinSxS\x86_microsoft-windows-m..namespace-downlevel_31bf3856ad364e35_10.0.17134.1_none_50c6cb8431e7428f launch.py

The binary executable is C:\sofa_dev_win\packaging\sofastats\dist\launch\launch.exe

Shift all C:\sofa_dev_win\packaging\sofastats\ in (except for pycache, build, or dist) and rename launch folder to sofastats so calls to sofastats package work.

Rename, relocate, and edit spec file

Warning - must wipe build folder first for a clean exe build

ghostscript - use the commandline version of ghostscript. http://stackoverflow.com/questions/2598669/ghostscript-whats-are-the-differences-between-linux-and-windows-variants. On Windows you have two executables, gswin32c.exe and gswin32.exe instead of gs only. The first one is to run Ghostscript on the commandline (“DOS box”), the second one will open two GUI windows: one to render the output, another one which is console-like and shows GS stdout/stderr or takes your command input if you run GS in interactive mode.

ImageMagick - use the portable version (big fat convert.exe with everything bakes in vs scrawny non-portable version which relies the dependencies)

binaries=[
    ('C:/Program Files/wkhtmltopdf/bin/wkhtmltopdf.exe', '.'),  ## the docs for 3.4 show the structure as (binary, subfolder) where '.' means the main folder
    ('C:/sofa_dev_win/ImageMagick-7.0.8-44-portable-Q16-x64/convert.exe', '.'),  ## need portable version
    ('C:/Program Files (x86)/gs/gs9.27/bin/gswin32c.exe', '.'),
    ('C:/Program Files (x86)/gs/gs9.27/bin/gsdll32.dll', '.'),
],
datas=[
    ('C:/sofa_dev_win/ImageMagick-7.0.8-44-portable-Q16-x64/delegates.xml', '.'), 
],

exe - icon='C:\sofa_dev_win\sofa_32x32.ico'

exe - upx=False

exe - name='sofastats'

exe - exclude_binaries=True ## we want the binaries to go into the sofastats folder (we're one-dir remember) alongside the sofastats.exe binary so they'll be grabbed by col instead. If this is set to False and we're in one-dir then expect failure ;-)

pyz - level=9 ## heavily compressed?

col - upx=False

col - name='sofastats' ## so folder is called sofastats (which it needs to be because that is the expected package name in internal calls e.g. from sofastats import …)

Initially (so debugging is trivial - go on - don't be a martyr!):

exe - console=True exe - debug=True

Then for prod:

exe - console=False exe - debug=False

Put in C:\sofa_dev_win\packaging\sofastats\ as sofastats.spec. Needs to be in same folder as scripts being packaged i.e. launch.py etc

Run pyinstaller off spec file

cd C:\sofa_dev_win\packaging\sofastats\
pyinstaller sofastats.spec

Shift all C:\sofa_dev_win\packaging\sofastats\ in (except for pycache, build, or dist). Folder already named sofastats because of spec edits.

Test binary and SOFA code folders on clean machine

Find a clean Windows 10 machine and test on it using the installer.

Make NSIS installer

Use UltraModernUI

Get latest version from https://sourceforge.net/projects/ultramodernui/files/UltraModernUI/

Note - don't need to specify every file - can just use the recursive syntax

Section ""
  RMDir /r $INSTDIR
  ; Set output path to the installation directory.
  SetOutPath $INSTDIR
  File /r "${DEV_PATH}\*.*"

Note on DAO

For MS Access

Re: dao file, it is because we can't dynamically get it from the frozen (or some similar issue) but it works if we generate it, grab it as a module, and import it. Start with installing pywin. Then go to site-packages\win32com\Pythonwin.exe and run COM Makepy Utility for DAO 3.6. Then go to win32com\gen_py folder and copy content of one of the py files and save as the module to import e.g. dao36_from_gen_py_after_makepy.py.

proj/wininstallers.txt · Last modified: 2019/07/07 03:02 by admin