تحية لكل من يقرأ :)المحور المستهدف لا يتوافق مع محتوى المقالة ، ولكن ماذا تفعل ... - لا توجد مواضيع موضوعية لهذا الغرض ، ولكن الأنسب هو "C" ، لأن سيكون قراءه قادرين بسهولة على إدراك ما هو مكتوب.الغرض من المقال
خيار لحل مشكلة التحكم في المتغيرات العامة عند كتابة المثبت / إلغاء التثبيت باستخدام NSIS .مقدمة صغيرة
عند كتابة كود nsis ، فإن المبرمج لديه الفرصة لاستخدام المتغيرات العالمية التي يكون نطاقها هو المشروع بأكمله. هناك 20 منهم فقط: $ 0- $ 9 و $ R0- $ R9.من السهل جدا استخدامها ، لأن هذا يلغي الحاجة إلى إدخال متغيرات إضافية مخصصة رسميًا لحل المشكلات المستهدفة. أقول ، رسميا ، لأنه أي متغيرات nsis لها نطاق عالمي وإذا اختلفت في أي شيء ، فعندئذ فقط مع شرط المؤهل (يتحدث بشروط C / C ++):!define variable1 ''value 1''
الميزات:- المتغير الثابت للنطاق العالمي ؛
- تم التهيئة عند الإعلان ؛
- طريقة الاتصال: $ {variable1}
Var variable2
الميزات:- المتغير الديناميكي للنطاق العالمي ؛
- يتم الإعلان عنها في أي مكان بواسطة رمز ، ولكن فوق المكالمة الأولى ؛
- تتم تهيئته عدة مرات حسب الضرورة ، ولكن فقط داخل كتل الوظائف ووحدات الماكرو ؛
- طريقة الوصول: $ متغير 2
وبالتالي ، بالنظر إلى الميزات المذكورة أعلاه ، يصبح من الواضح أنه من الصعب تبرير الإنشاء المستهدف لأي متغيرات أخرى غير ثابتة ، لأنه المتغيرات العالمية موجودة بالفعل بشكل افتراضي ، وهناك ما يكفي منها لتلبية أي احتياجات (وإذا لم يكن الأمر كذلك ، فأنت بحاجة إلى طرح الأسئلة "المناسبة" للمبرمج) وأي متغيرات أخرى على الأرجح تسد الشفرة فقط.وصف المشكلة
لكن المشكلة هي أن هذا الرمز يولد دائمًا أخطاء:
Function F1
StrCpy $0 "vladimir"
FunctionEnd
Function F2
StrCpy $0 "alexei"
Call F1
${If} $0 == "alexei" ;
;
${EndIf}
FunctionEnd
ويمكنك الخروج بالعديد من الأمثلة على ذلك ، وقد قام حرفيو برمجة nsis بحل هذه المشكلة بأفضل طريقة ممكنة:- شاهد شخص ما بعناية جميع المتغيرات (مثل هؤلاء الناس بحاجة إلى إقامة نصب تذكاري)) ؛
- شخص ما ، بشكل رئيسي منشئو المكونات الإضافية المختلفة ، في كل مرة يريد استخدام أي من المتغيرات المقدمة ، جعله يدفع إلى المكدس ، وبعد نهاية الاستخدام ، أعادوا القيمة الأساسية عن طريق استدعاء Pop ؛
- وقام شخص ما بإنتاج متغيرات من خلال Var ، كما هو موضح أعلاه.
على أي حال ، واجهوا جميعًا مشكلة عدم وجود آلية عالمية تحل مشكلة مراقبة حالة المتغيرات العالمية.هنا أسمح لنفسي أن أقدم لها (المشاكل) حلاً شاملاً.حل للمشكلة
بادئ ذي بدء ، فإن الرابط إلى NSISList هو مكون إضافي يقدم القدرة على استخدام بنية بيانات من نوع القائمة ، والتي يجب أن تؤخذ بطريقة مماثلة لـ std :: list في C ++.الخطوة الثانية هي شفرة المصدر لآلية حل المشكلات :
!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."
والخطوة الثالثة هي وصف صغير لكيفية عملها:كل وظيفة تم إنشاؤها وتصميمها وفقًا للقاعدة الموضحة في تعليق الكود الرئيسي السابق ستكون محمية تمامًا من وجهة نظر خطر إعادة كتابة المتغيرات العالمية $ 0- $ 9 ، $ R0- $ R9 بداخلها ، وبالتالي - من انتهاك منطق وظيفة الاستدعاء.يعمل مثل هذا:- لا يتم استدعاء وظيفة F1 نفسها مباشرة ،
Call F1
ومن خلال غلاف الماكرو${F1} [paramIn1 [paramIn2]...[paramInN]] [paramOut1 [paramOut2]...[paramOutM]]
- حتى قبل استدعاء الوظيفة مباشرة ، سيتم استدعاؤها
${Dump}
ونتيجة لذلك ، يتم حفظ القيم الحالية للمتغيرات $ 0- $ 9 ، $ R0- $ R9 في تفريغ. تحت غطاء المحرك لديه الكثير من القوائم ، كل منها مرتبط بمتغيره المستهدف ؛ - تحميل على المكدس جميع المتغيرات المستهدفة للوظيفة
Push ${paramIn1} Push ${paramIn2} ... Push ${paramInN}
(إذا لزم الأمر)؛ - سيتم استدعاء الوظيفة ؛
- ستقوم الوظيفة بتنفيذ منطقها وخروجها ؛
- ستحدث المكالمة
${Undump}
ونتيجة لذلك ، سيتم استعادة قيم المتغيرات العالمية المخزنة في المكالمة الأخيرة من $ {Dump} ؛ - نتائج تفريغ الوظيفة من المكدس
Pop ${paramOut1} Pop ${paramOut2} ... Pop ${paramOutM}
(إذا لزم الأمر)؛ - ستكمل أداة تغليف الماكرو في الدالة F1 عملها.
استنتاج
ونتيجة لذلك ، حصلنا على تصميم عالمي للكتابة الآمنة لرمز nsis.يمكنك حتى القول أنه لا يجلب أي سلبيات ، باستثناء أن التعليمات البرمجية المترجمة ستعمل لمدة 30 مللي ثانية تقريبًا. أبطأ.أتمنى أن يجعل هذا الحياة أسهل بالنسبة لشخص ما :)شكرا لك!