Grüße an alle, die lesen :) DerZiel-Hub entspricht nicht dem Inhalt des Artikels, aber was zu tun ist ... - Es gibt keine thematischen für diesen Zweck, aber der am besten geeignete ist "C", weil Leser werden am leichtesten erkennen können, was geschrieben steht.Zweck des Artikels
Eine Option zur Lösung des Problems der Steuerung globaler Variablen beim Schreiben des Installations- / Deinstallationsprogramms mit NSIS .Kleine Einführung
Beim Schreiben von nsis-Code hat der Programmierer die Möglichkeit, globale Variablen zu verwenden, deren Umfang das gesamte Projekt umfasst. Es gibt nur 20 davon: $ 0- $ 9 und $ R0- $ R9.Es ist sehr bequem, sie zu verwenden, weil Dadurch entfällt die Notwendigkeit, zusätzliche Variablen einzuführen, die formal zur Lösung von Zielproblemen vorgesehen sind. Ich sage formell, weil Alle nsis-Variablen haben einen globalen Gültigkeitsbereich und wenn sie sich in irgendetwas unterscheiden, nur mit dem Qualifikationsmerkmal const (in C / C ++ - Begriffen):!define variable1 ''value 1''
Eigenschaften:- statische Variable des globalen Bereichs;
- Initialisiert bei Erklärung;
- Kontaktmethode: $ {variable1}
Var variable2
Eigenschaften:- Dynamische Variable mit globalem Geltungsbereich;
- Es wird überall durch Code deklariert, jedoch über dem ersten Aufruf.
- Es wird so oft wie nötig initialisiert, jedoch nur innerhalb von Funktionsblöcken und Makros.
- Zugriffsmethode: $ variable2
Angesichts der obigen Merkmale wird daher klar, dass die gezielte Erstellung anderer als statischer Variablen schwer zu rechtfertigen ist, weil Standardmäßig sind bereits globale Variablen vorhanden. Es gibt genügend Variablen, um alle Anforderungen zu erfüllen (und wenn nicht, müssen Sie dem Programmierer die "entsprechenden" Fragen stellen), und andere verstopfen höchstwahrscheinlich nur den Code.Beschreibung des Problems
Das Problem ist jedoch, dass dieser Code immer Fehler generiert:
Function F1
StrCpy $0 "vladimir"
FunctionEnd
Function F2
StrCpy $0 "alexei"
Call F1
${If} $0 == "alexei" ;
;
${EndIf}
FunctionEnd
Und Sie können sich viele Beispiele dafür einfallen lassen, und die Programmierer von nsis haben dieses Problem so gut wie möglich gelöst:- Jemand hat nur alle Variablen genau beobachtet (solche Leute müssen ein Denkmal errichten);
- Jemand, hauptsächlich die Ersteller verschiedener Plug-Ins, die jedes Mal eine der dargestellten Variablen verwenden wollten, ließen es auf den Stapel schieben, und nach dem Ende der Verwendung gaben sie den primären Wert zurück, indem sie Pop aufriefen.
- Und jemand hat Variablen durch Var erzeugt, wie oben beschrieben.
Auf jeden Fall standen sie alle vor dem Problem, dass es keinen universellen Mechanismus gibt, der das Problem der Überwachung des Zustands globaler Variablen löst.Hier erlaube ich mir, ihr (Probleme) eine universelle Lösung anzubieten.Lösung
Zunächst ist der Link zu NSISList ein Plugin, das die Möglichkeit einführt, eine Datenstruktur vom Listentyp zu verwenden, die ähnlich wie std :: list in C ++ verwendet werden sollte.Der zweite Schritt ist der Quellcode des Problemlösungsmechanismus :
!verbose 3
!include NSISList.nsh ; *
!define InitDump "!insertmacro _InitDump"
!macro _InitDump
!ifdef __UNINSTALL__
Call un.InitDump
!else
Call InitDump
!endif
!macroend
!macro Func_InitDump un
Function ${un}InitDump
# $0-$9
${List.Create} d0
${List.Create} d1
${List.Create} d2
${List.Create} d3
${List.Create} d4
${List.Create} d5
${List.Create} d6
${List.Create} d7
${List.Create} d8
${List.Create} d9
# $R0-$R10
${List.Create} dR0
${List.Create} dR1
${List.Create} dR2
${List.Create} dR3
${List.Create} dR4
${List.Create} dR5
${List.Create} dR6
${List.Create} dR7
${List.Create} dR8
${List.Create} dR9
FunctionEnd
!macroend
!insertmacro Func_InitDump ""
!insertmacro Func_InitDump "un."
!define Dump "!insertmacro _Dump"
!macro _Dump
!ifdef __UNINSTALL__
Call un.Dump
!else
Call Dump
!endif
!macroend
!macro Func_Dump un
Function ${un}Dump
# $0-$9
${List.Add} d0 $0
${List.Add} d1 $1
${List.Add} d2 $2
${List.Add} d3 $3
${List.Add} d4 $4
${List.Add} d5 $5
${List.Add} d6 $6
${List.Add} d7 $7
${List.Add} d8 $8
${List.Add} d9 $9
# R0-R9
${List.Add} dR0 $R0
${List.Add} dR1 $R1
${List.Add} dR2 $R2
${List.Add} dR3 $R3
${List.Add} dR4 $R4
${List.Add} dR5 $R5
${List.Add} dR6 $R6
${List.Add} dR7 $R7
${List.Add} dR8 $R8
${List.Add} dR9 $R9
FunctionEnd
!macroend
!insertmacro Func_Dump ""
!insertmacro Func_Dump "un."
!define Undump "!insertmacro _Undump"
!macro _Undump
!ifdef __UNINSTALL__
Call un.Undump
!else
Call Undump
!endif
!macroend
!macro Func_Undump un
Function ${un}Undump
# $0-$9
${List.Pop} $0 d0
${List.Pop} $1 d1
${List.Pop} $2 d2
${List.Pop} $3 d3
${List.Pop} $4 d4
${List.Pop} $5 d5
${List.Pop} $6 d6
${List.Pop} $7 d7
${List.Pop} $8 d8
${List.Pop} $9 d9
# R0-R9
${List.Pop} $R0 dR0
${List.Pop} $R1 dR1
${List.Pop} $R2 dR2
${List.Pop} $R3 dR3
${List.Pop} $R4 dR4
${List.Pop} $R5 dR5
${List.Pop} $R6 dR6
${List.Pop} $R7 dR7
${List.Pop} $R8 dR8
${List.Pop} $R9 dR9
FunctionEnd
!macroend
!insertmacro Func_Undump ""
!insertmacro Func_Undump "un."
Und der dritte Schritt ist eine kleine Beschreibung der Funktionsweise:Jede Funktion, die gemäß der im vorherigen Hauptcodekommentar beschriebenen Regel erstellt und entworfen wurde, ist unter dem Gesichtspunkt der Gefahr des Überschreibens der globalen Variablen $ 0- $ 9, $ R0- $ R9 in sich selbst absolut geschützt - wegen Verletzung der Logik der aufrufenden Funktion.Es funktioniert so:- Die F1-Funktion selbst wird nicht direkt aufgerufen,
Call F1
und durch den Makro-Wrapper${F1} [paramIn1 [paramIn2]...[paramInN]] [paramOut1 [paramOut2]...[paramOutM]]
- Noch bevor die Funktion direkt aufgerufen wird, wird sie aufgerufen
${Dump}
Infolgedessen werden die aktuellen Werte der Variablen $ 0- $ 9, $ R0- $ R9 in Dump gespeichert. Unter der Haube hat er viele Listen, die jeweils an die Zielvariable gebunden sind. - Laden aller Zielvariablen für die Funktion auf den Stapel
Push ${paramIn1} Push ${paramIn2} ... Push ${paramInN}
(wenn es benötigt wird); - Die Funktion wird aufgerufen;
- Die Funktion führt ihre Logik aus und beendet sie.
- Anruf wird passieren
${Undump}
Infolgedessen werden die Werte der globalen Variablen, die beim letzten Aufruf von $ {Dump} gespeichert wurden, wiederhergestellt. - Das Entladen der Funktion ergibt sich aus dem Stapel
Pop ${paramOut1} Pop ${paramOut2} ... Pop ${paramOutM}
(wenn es benötigt wird); - Der Makro-Wrapper der F1-Funktion beendet seine Arbeit.
Fazit
Als Ergebnis haben wir ein universelles Design für das sichere Schreiben von nsis-Code erhalten.Sie können sogar sagen, dass es keine Minuspunkte bringt, außer dass der kompilierte Code etwa 30 ms lang funktioniert. Langsamer.Hoffe das macht jemandem das Leben leichter :)Danke!