Erstellen Sie ein Python-Webanwendungsinstallationsprogramm mit Apache, Django und PostgreSQL für Windows





Dieser Beitrag ist eine Fortsetzung des ersten Teils des Artikels über Habré , in dem ausführlich die Bereitstellung des Django-Stacks unter MS Windows beschrieben wurde. Als Nächstes erhalten Sie schrittweise Anweisungen zum Erstellen eines Installationsprogramms, das den Prozess der Installation des Stacks auf anderen Computern automatisiert, ohne dass Sie in der Befehlszeile arbeiten, virtuelle Maschinen usw. erstellen müssen. Dabei wird die gesamte Abfolge der Aktionen auf die Aktionen Weiter -> Weiter -> Fertig stellen reduziert.



Was sollte der Installer also tun:



  1. Entpacken Sie alle erforderlichen Programme und Komponenten in ein vom Benutzer angegebenes Verzeichnis.
  2. Führen Sie vor der Installation Überprüfungen durch.
  3. Registrieren Sie den Python-Interpreter in der Windows-Registrierung.
  4. Installieren Sie die Software-Abhängigkeitsbibliotheken, falls diese noch nicht installiert sind.
  5. Erstellen Sie Apache- und PostgreSQL-Dienste und starten Sie sie.
  6. Ein zusätzliches Plus ist die automatische Erstellung eines Deinstallationsprogramms, das den installierten Stapel entfernt, wenn der Benutzer dies wünscht.


Unter den möglichen Optionen für Installer werden wir den kostenlosen Installer Inno Setup wählen, weil Damit können Sie alle oben genannten Schritte ausführen und Installationsprogramme erstellen, ohne viele Skripts ausführen zu müssen Im Vergleich zu Wix ist die Setup-Dateisyntax im INI-Format, das einfacher zu lesen und zu ändern ist als XML. Heute konkurriert es mit vielen kommerziellen Installateuren und übertrifft diese sogar in Bezug auf Funktionsumfang und Stabilität.



Das Beste daran ist, dass zum Erstellen eines Basisinstallationsprogramms überhaupt keine Skripte erforderlich sind, da Inno Setup mit einem grafischen Assistenten geliefert wird, der überraschend gute Arbeit mit Basisinstallationsprogrammen leistet.



Die Installationslogik kann in Pascal geschrieben werden, anstatt in Wix verschlungene benutzerdefinierte Aktionen auszuführen. Der einzige Nachteil ist, dass nur exe erstellt wird und das MSI-Dateiformat nicht unterstützt wird.



Schritt 1.Inno Setup Installation



Zusätzliche Kommentare sind hier nicht erforderlich, da Das Herunterladen und Installieren des Installationsprogramms ist trivial.



Schritt 2: Schreiben Sie die Inno Setup-Installation per Skript



Erstellen wir mit dem Installationsskript-Assistenten ein Stub-Inno-Setup-Skript (* .iss-Datei).



















































Als Ergebnis wird eine * .iss-Datei mit folgendem Inhalt erstellt:
; Script generated by the Inno Setup Script Wizard.

; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!



#define MyAppName "Severcart"

#define MyAppVersion "1.21.0"

#define MyAppPublisher "Severcart Inc."

#define MyAppURL "https://www.severcart.ru/"



[Setup]

; NOTE: The value of AppId uniquely identifies this application. Do not use the same AppId value in installers for other applications.

; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)

AppId={{4FAF87DC-4DBD-42CE-A2A2-B6D559E76BDC}

AppName={#MyAppName}

AppVersion={#MyAppVersion}

;AppVerName={#MyAppName} {#MyAppVersion}

AppPublisher={#MyAppPublisher}

AppPublisherURL={#MyAppURL}

AppSupportURL={#MyAppURL}

AppUpdatesURL={#MyAppURL}

DefaultDirName=c:\severcart

DefaultGroupName={#MyAppName}

; Uncomment the following line to run in non administrative install mode (install for current user only.)

;PrivilegesRequired=lowest

OutputDir=C:\Users\Developer\Desktop\Output

OutputBaseFilename=mysetup

Compression=lzma

SolidCompression=yes

WizardStyle=modern



[Languages]

Name: "russian"; MessagesFile: "compiler:Languages\Russian.isl"



[Files]

Source: "C:\severcart\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs

; NOTE: Don't use "Flags: ignoreversion" on any shared system files







Schritt 3. Überprüft vor der Installation



Bevor Sie Programme in das Verzeichnis entpacken und die Registrierung ändern, müssen Sie überprüfen, ob die TCP-Ports für Apache und PostgreSQL frei sind. Außerdem müssen Sie die Mindestsystemanforderungen von Windows überprüfen, da Wie bereits im ersten Teil dieses Artikels erwähnt, funktioniert die installierte Version von Python nur ab der Version von MS Windows 8 (Kernel-Version 6.2) .



Verwenden Sie den Abschnitt [Code] der Installationsdatei, um die erforderlichen Überprüfungen durchzuführen . Abschnitt [Code]Ist ein optionaler Abschnitt, der ein Pascal-Skript definiert. Pascal-Skript kann verwendet werden, um die Installation oder Deinstallation auf verschiedene Arten anzupassen. Beachten Sie, dass das Erstellen eines Pascal-Skripts nicht einfach ist und Erfahrung mit Inno-Setup und Programmierkenntnissen in Pascal oder zumindest einer ähnlichen Programmiersprache erfordert. Um die Verfügbarkeit von TCP-Ports zu überprüfen, erstellen wir die folgende Funktion: Wir rufen die Testfunktionen in der InitializeSetup- Funktion auf , die während der Installationsinitialisierung aufgerufen wird. Gibt False zurück , um die Installation abzubrechen, andernfalls True .



function IsWindowsVersionOrNewer(Major, Minor: Integer): Boolean;

var

Version: TWindowsVersion;

begin

GetWindowsVersionEx(Version);

Result := (Version.Major > Major) or ((Version.Major = Major) and (Version.Minor >= Minor));

end;



function IsWindows8OrNewer: Boolean;

begin

Result := IsWindowsVersionOrNewer(6, 2);

end;







function CheckPortOccupied(Port:String):Boolean;

var

ResultCode: Integer;

begin

Exec(ExpandConstant('{cmd}'), '/C netstat -na | findstr'+' /C:":'+Port+' "', '',0,ewWaitUntilTerminated, ResultCode);

if ResultCode <> 1 then

begin

Log('this port('+Port+') is occupied');

Result := True;

end else

begin

Result := False;

end;

end;







function InitializeSetup(): Boolean;

var

port_80_check, port_5432_check: boolean;

begin

if not IsWindows8OrNewer() then begin

MsgBox(' . Windows 2012 Windows 8.0.',mbError,MB_OK);

Abort();

Result := False;

end;



port_80_check := CheckPortOccupied('8080');

if port_80_check then begin

MsgBox(' . TCP 8080 .',mbError,MB_OK);

Abort();

Result := False;

end;



port_5432_check := CheckPortOccupied('5432');

if port_5432_check then begin

MsgBox(' . TCP 5432 .',mbError,MB_OK);

Result := False;

Abort();

end;

Result := True;



Schritt 4. Registrieren Sie Python in der Windows-Registrierung



In diesem optionalen Abschnitt werden alle Registrierungsschlüssel / -werte definiert, die das Installationsprogramm auf dem System des Benutzers erstellen oder ändern muss.



Um dies zu tun, fügen Sie die PYTHONPATH und PYTHON Tasten und aktualisieren Sie die Pfad - Variable .



sys.path enthält eine Liste von Zeichenfolgen, die Suchpositionen für Module und Pakete für ein zukünftiges Python-Projekt bereitstellen. Es wird über die Umgebungsvariable PYTHONPATH und andere Einstellungen initialisiert .



PYTHONHOME ist das Python- Ausgangsverzeichnis .



PATH ist eine Umgebungsvariable, mit der das Betriebssystem ausführbare Dateien in der Befehlszeile oder im Terminalfenster findet.



[Registry]



Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; \

ValueType: expandsz; ValueName: "Path"; ValueData: "{olddata};{app}\python;{app}\python\Scripts"



Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; \

ValueType: expandsz; ValueName: "PYTHONPATH"; ValueData: "{app}\python"



Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; \

ValueType: expandsz; ValueName: "PYTHONHOME"; ValueData: "{app}\python"



Schritt 5. Erstellen Sie Konfigurationsdateien für Apache- und PostgreSQL-Dienste



Zum Erstellen von Konfigurationsdateien verwenden wir 2 Python-Skripte, die eine Konfiguration basierend auf dem benutzerdefinierten Installationspfad generieren.



Die Skripte werden im Abschnitt [Ausführen] des Installationsprogramms aufgerufen.



Der Abschnitt [Ausführen] ist optional und gibt eine beliebige Anzahl von Programmen an, die ausgeführt werden sollen, nachdem das Programm erfolgreich installiert wurde, bevor das Installationsprogramm das endgültige Dialogfeld anzeigt.



Als Nächstes fügen wir im selben Abschnitt die versteckte Installation der verteilbaren Visual Studio-Pakete hinzu, ohne die Apache- und PostgreSQL-Dienste nicht funktionieren. Inhalt der Datei create_http_conf.py



[Run]



Filename: "{app}\common\VC_redist.x86apache.exe"; Parameters: "/install /passive"; Flags: waituntilterminated

Filename: "{app}\common\vcredist_x86pg.exe"; Parameters: "/install /passive"; Flags: runhidden;

Filename: "{app}\python\python.exe" ;Parameters: "{app}\common\create_http_conf.py"; Flags: runhidden

Filename: "{app}\python\python.exe" ;Parameters: "{app}\common\edit_pg_conf.py"; Flags: runhidden

Filename: "{app}\common\install.bat";Flags: runhidden

Filename: "{app}\common\services_start.bat"; Flags: runhidden







#!/usr/bin/env python3
# -*- coding:utf-8 -*-

import sys, os


base_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
base_path_un = base_path.replace('\\', '/')
apache_conf_path = os.path.join(base_path, 'Apache24', 'conf', 'extra', 'httpd-wsgi.conf')

print('base_path=',base_path)

CONF = """

LoadFile "%(base)s/python/python39.dll"
LoadModule wsgi_module "%(base)s/python/lib/site-packages/mod_wsgi/server/mod_wsgi.cp39-win32.pyd"
WSGIPythonHome "%(base)s/python"


Alias /static "%(base)s/app/static"

Alias /media "%(base)s/app/media"

<Directory "%(base)s/app/static">
    # for Apache 2.4
    Options Indexes FollowSymLinks
    AllowOverride None
    Require all granted
</Directory>

<Directory "%(base)s/app/media">
    # for Apache 2.4
    Options Indexes FollowSymLinks
    AllowOverride None
    Require all granted
</Directory>


WSGIScriptAlias / "%(base)s/app/conf/wsgi_prod.py"
WSGIPythonPath "%(base)s/python/"

<Directory "%(base)s/app/conf/">
<Files wsgi_prod.py>
    Require all granted
</Files>   
</Directory>

"""
conf_content = CONF % {'base': base_path_un}

with open(apache_conf_path, 'w') as fp:
    fp.write(conf_content)


# Read in the file
apache_main = os.path.join(base_path, 'Apache24', 'conf', 'httpd.conf')
with open(apache_main, 'r') as file :
	filedata = file.read()

# Replace the target string
replace_pattern = 'Define SRVROOT "%(base)s/Apache24"' % {'base' : base_path_un}
find_pattern = 'Define SRVROOT "C:/severcart/Apache24"'

filedata = filedata.replace(find_pattern, replace_pattern)

# Write the file out again
with open(apache_main, 'w') as file:
	file.write(filedata)



Inhalt edit_pg_conf.py



#!/usr/bin/env python3
# -*- coding:utf-8 -*-

import sys, os

"""
c:/djangostack/postgresql/bin/postgres.exe "-D" "c:\djangostack\postgresql\data"
"""


base_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
base_path_un = base_path.replace('\\', '/')
pg_conf_path = os.path.join(base_path, 'postgresql', 'data', 'postmaster.opts')


# Read in the file
pg_conf_path = os.path.join(base_path, 'postgresql', 'data', 'postmaster.opts')
with open(pg_conf_path, 'r') as file :
	filedata = file.read()


# Replace the target string
replace_pattern = base_path_un + '/'
find_pattern = "C:/severcart/"


filedata = filedata.replace(find_pattern, replace_pattern)

# Write the file out again
with open(pg_conf_path, 'w') as file:
	file.write(filedata)


Install.bat-Datei Inhalt services_start.bat-Datei



@echo off



..\Apache24\bin\httpd.exe -k install -n "Apache" > install.log 2>&1



..\postgresql\bin\pg_ctl.exe register -N "PostgreSQL" -D ..\postgresql\data > install.log 2>&1







@echo off



net start "Apache"



net start "PostgreSQL"



Schritt 6: Erstellen Sie das Deinstallationsprogramm



Für jedes Installationsprogramm muss auch die Möglichkeit vorgesehen werden, ein Deinstallationsprogramm zu erstellen. Glücklicherweise erledigt Inno Setup die Aufgabe für uns, mit Ausnahme einiger Schritte, die unternommen werden müssen, um Spuren der Programmpräsenz im Betriebssystem zu bereinigen.



Zu diesem Zweck registrieren wir im Abschnitt [UninstallRun] die Ausführung des Windows-Bat-Skripts, um die installierten Dienste zu stoppen und zu entfernen. Der Inhalt des bat-Skripts: Das Skript stoppt die Dienste und entfernt dann die Apache- und PostgreSQL-Dienste aus der Liste der Windows-Systemdienste.



[UninstallRun]

Filename: "{app}\common\remove.bat"; Flags: runhidden







@echo off



SC STOP Apache

SC STOP PostgreSQL



SC DELETE Apache

SC DELETE PostgreSQL







Schritt 7. Signieren der ausführbaren Datei des ES-Installationsprogramms des Entwicklers



Codesignaturzertifikate werden von Softwareentwicklern verwendet, um Anwendungen und Programme digital zu signieren, um zu beweisen, dass eine von einem Benutzer hochgeladene Datei echt ist und nicht manipuliert wurde. Dies ist besonders wichtig für Publisher, die ihre Software über Download-Sites von Drittanbietern vertreiben, auf die sie keinen Einfluss haben. Bei den wichtigsten Betriebssystemen wird den Endbenutzern eine Fehlermeldung angezeigt, wenn die Software, die sie installieren möchten, nicht von einer vertrauenswürdigen Zertifizierungsstelle signiert ist.



Sie können ein PFX - Entwicklerzertifikat, zum Beispiel, kaufen hier . Das Zertifikat wird für ein Jahr gekauft.



Der vorletzte Schritt zur Arbeit mit dem Installationsprogramm besteht darin, das Programm signtool.exe automatisch zu starten, um das fertige Installationsprogramm im exe-Format zu signieren, nachdem das Inno Setup-Programm seine Arbeit abgeschlossen hat. SignTool ist ein Befehlszeilenprogramm, das Dateien digital signiert, Dateisignaturen und Dateizeitstempel überprüft. Standardmäßig ist das Programm signtool.exe nicht in der Windows-Distribution enthalten. Laden Sie daher das Windows 10 SDK herunter und installieren Sie es .



Nach Abschluss der Installation finden Sie signtool.exe in den Verzeichnissen:



  • x86 -> c: \ Programme (x86) \ Windows Kits \ 10 \ bin \ x86 \
  • x64 -> c: \ Programme (x86) \ Windows Kits \ 10 \ bin \ x64 \


Wenn Sie sich mit dem Signierprogramm vertraut machen möchten, besuchen Sie die offizielle Website des Entwicklers . Es werden alle Befehlszeilenoptionen und Verwendungsbeispiele aufgelistet. Lass uns weitermachen.



Als nächstes richten wir die automatische Signatur der Datei ein. Wählen Sie "Configure Sign Tools ..." aus dem Menü "Tools" .







Klicken Sie anschließend auf die Schaltfläche "Hinzufügen".







Geben Sie dem Werkzeug einen Namen. Dies ist der Name, den Sie verwenden, wenn Sie in den Installationsskripten auf das Tool verweisen. Ich habe mein signtool benannt, weil ich signtool.exe verwende.







Fügen Sie den Text ein, mit dem Sie ausführbare Dateien über die Befehlszeile signieren. Ersetzen Sie den Namen der zu signierenden Datei durch $ f. Inno Setup ersetzt die Variable $ f durch die signierte Datei.



"C: \ Programme (x86) \ Windows Kits \ 10 \ bin \ x86 \ signtool.exe" sign / f "C: \ MY_CODE_SIGNING.PFX" / t timestamp.comodoca.com/authenticode / p MY_PASSWORD $ f







Nach dem Drücken OK, Sie sind mit der Konfiguration des Signatur-Tools fertig.







Fügen wir dem Abschnitt [Setup] das folgende Skript hinzu, um das soeben konfigurierte Signatur-Tool zu verwenden. Dies setzt voraus, dass Sie Ihr Tool signtool benannt haben.



SignTool=signtool



Schritt 8. Montage des Installationsprogramms



Endgültige InnoSetup-Installationsdatei
#define MyAppName «Severcart»

#define MyAppVersion «1.21.0»

#define MyAppPublisher «Severcart Inc.»

#define MyAppURL «www.severcart.ru»



[Setup]

; NOTE: The value of AppId uniquely identifies this application.

; Do not use the same AppId value in installers for other applications.

; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)

SignTool=signtool

AppId={{2CF113D5-B49D-47EF-B85F-AE06EB0E78EB}}

AppName={#MyAppName}

AppVersion={#MyAppVersion}

;AppVerName={#MyAppName} {#MyAppVersion}

AppPublisher={#MyAppPublisher}

AppPublisherURL={#MyAppURL}

AppSupportURL={#MyAppURL}

AppUpdatesURL={#MyAppURL}

DefaultDirName=c:\severcart

DefaultGroupName={#MyAppName}

OutputBaseFilename=setup

Compression=lzma

SolidCompression=yes

ChangesEnvironment=yes



; Uninstall options

Uninstallable=yes

CreateUninstallRegKey=yes

;WizardSmallImageFile=logo3.bmp



[Icons]

Name: "{userdesktop}\severcart"; Filename: «127.0.0.1:8080/»



[Languages]

Name: «russian»; MessagesFile: «compiler:Languages\Russian.isl»



[Files]

Source: «C:\severcart\*»; Excludes: "*.pyc"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs



[Registry]

Root: HKLM; Subkey: «SYSTEM\CurrentControlSet\Control\Session Manager\Environment»; \

ValueType: expandsz; ValueName: «Path»; ValueData: "{olddata};{app}\python;{app}\python\Scripts"



Root: HKLM; Subkey: «SYSTEM\CurrentControlSet\Control\Session Manager\Environment»; \

ValueType: expandsz; ValueName: «PYTHONPATH»; ValueData: "{app}\python"



Root: HKLM; Subkey: «SYSTEM\CurrentControlSet\Control\Session Manager\Environment»; \

ValueType: expandsz; ValueName: «PYTHONHOME»; ValueData: "{app}\python"



[Run]

Filename: "{app}\common\VC_redist.x86apache"; Parameters: "/install /passive"; Flags: waituntilterminated

Filename: "{app}\common\vcredist_x86pg"; Parameters: "/install /passive"; Flags: runhidden;

Filename: "{app}\python\python.exe" ;Parameters: "{app}\common\create_http_conf.py"; Flags: runhidden

Filename: "{app}\python\python.exe" ;Parameters: "{app}\common\edit_pg_conf.py"; Flags: runhidden

Filename: "{app}\common\install.bat";Flags: runhidden

Filename: "{app}\common\services_start.bat"; Flags: runhidden





[UninstallRun]

Filename: "{app}\common\remove.bat"; Flags: runhidden



[Code]

function IsWindowsVersionOrNewer(Major, Minor: Integer): Boolean;

var

Version: TWindowsVersion;

begin

GetWindowsVersionEx(Version);

Result :=

(Version.Major > Major) or

((Version.Major = Major) and (Version.Minor >= Minor));

end;



function IsWindows8OrNewer: Boolean;

begin

Result := IsWindowsVersionOrNewer(6, 2);

end;



function CheckPortOccupied(Port:String):Boolean;

var

ResultCode: Integer;

begin

Exec(ExpandConstant('{cmd}'), '/C netstat -na | findstr'+' /C:":'+Port+' "', '',0,ewWaitUntilTerminated, ResultCode);

if ResultCode <> 1 then

begin

Log('this port('+Port+') is occupied');

Result := True;

end else

begin

Result := False;

end;

end;



function InitializeSetup(): Boolean;

var

port_80_check, port_5432_check: boolean;

begin

if not IsWindows8OrNewer() then begin

MsgBox(' . Windows 2012 Windows 8.0.',mbError,MB_OK);

Abort();

Result := False;

end;



port_80_check := CheckPortOccupied('8080');

if port_80_check then begin

MsgBox(' . TCP 8080 .',mbError,MB_OK);

Abort();

Result := False;

end;



port_5432_check := CheckPortOccupied('5432');

if port_5432_check then begin

MsgBox(' . TCP 5432 .',mbError,MB_OK);

Result := False;

Abort();

end;

Result := True;



end;











Schritt 9. Überprüfen Sie die Arbeit des Installationsprogramms







































Das ist alles, danke für Ihre Aufmerksamkeit.



All Articles