Skip to content
⌘ NSIS Forum Archive

NSISArray plugin

147 posts

CancerFace#
I can reproduce the crash with this minimal script:
SetCompressor /SOLID lzma
!include "MUI.nsh"
!include "LogicLib.nsh"

OutFile "TEST.exe"
InstallDir "$PROGRAMFILES\Test"

!define EXTENTIONS_ARRAY_LIST_A 'ext1|ext2|ext3|ext4'
!define EXTENTIONS_ARRAY_TYPE_A "TestFile"

Section -Ext
MessageBox MB_OK|MB_ICONEXCLAMATION "Starting Section"
NSISArray::ArrayExists /NOUNLOAD ExtentionsArray
Pop $0
${If} $0 <> 1
NSISArray::New /NOUNLOAD ExtentionsArray 2 2
${EndIf}
MessageBox MB_OK|MB_ICONEXCLAMATION "Starting Process"
NSISArray::WriteListC /NOUNLOAD ExtentionsArray '${EXTENTIONS_ARRAY_LIST_A}' "|"
NSISArray:😁ebug /NOUNLOAD ExtentionsArray
NSISArray::Clear /NOUNLOAD ExtentionsArray
SectionEnd

Section -Uninstaller
SetOutPath "$INSTDIR"
WriteUninstaller "$INSTDIR\uninstall.exe"
SectionEnd

Section -Un.Ext
MessageBox MB_OK|MB_ICONEXCLAMATION "Starting Section"
NSISArray::ArrayExists /NOUNLOAD unExtentionsArray
Pop $0
${If} $0 <> 1
NSISArray::New /NOUNLOAD unExtentionsArray 2 2
${EndIf}
NSISArray:😁ebug /NOUNLOAD unExtentionsArray
NSISArray::WriteListC /NOUNLOAD unExtentionsArray "${EXTENTIONS_ARRAY_LIST_A}" "|"
NSISArray::Clear /NOUNLOAD unExtentionsArray
SectionEnd

Function .onInit
MessageBox MB_OK|MB_ICONEXCLAMATION "Creating array in .onInit"
NSISArray::New /NOUNLOAD ExtentionsArray 2 2
MessageBox MB_OK|MB_ICONEXCLAMATION "Created array on .onInit"
FunctionEnd

Function un.onInit
MessageBox MB_OK|MB_ICONEXCLAMATION "Creating array in un.onInit"
NSISArray::New /NOUNLOAD unExtentionsArray 2 2
MessageBox MB_OK|MB_ICONEXCLAMATION "Created array in un.onInit"
FunctionEnd

Function .onGUIEnd
MessageBox MB_OK|MB_ICONEXCLAMATION "Deleting Array on .onGUIEnd"
NSISArray:😁elete /NOUNLOAD ExtentionsArray
MessageBox MB_OK|MB_ICONEXCLAMATION "Deleted Array on .onGUIEnd"
NSISArray::Unload
FunctionEnd

Function un.onGUIEnd
MessageBox MB_OK|MB_ICONEXCLAMATION "Deleting Array on un.onGUIEnd"
NSISArray:😁elete /NOUNLOAD unExtentionsArray
NSISArray::Unload
MessageBox MB_OK|MB_ICONEXCLAMATION "Deleted Array on un.onGUIEnd"
FunctionEnd
The install part works fine.
The uninstaller crashes when the first Array command is called (NSISArray::ArrayExists) if the array is created in un.onInit.
CF
Brummelchen#
exactly that script dont crash here ... nsis 2.30, array 1.5rc2
winxp sp2 latest updates, vc8sp1

# ok, vista ultimate on vmware dont crash either
Brummelchen#edited
another problem here... 🙁
!include MUI.nsh
!include NSISArray.nsh
Name 'Subtract'
OutFile 'NSISArrayExample - Subtract.exe'
ShowInstDetails show
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_LANGUAGE English
${Array} "TestArray1" 1 256
${ArrayFunc} WriteList
${ArrayFunc} Subtract
${ArrayFunc} Debug
${Array} "TestArray2" 1 256
${ArrayFunc} WriteList
${ArrayFunc} Debug
Section
  ${TestArray1->Init}
  ${TestArray2->Init}
  ${TestArray1->WriteList} "'we1234.tmp' 'we3456.tmp' 'we5432.tmp'"
  ${TestArray2->WriteList} "'we1234.tmp' 'we3456.tmp'"
  ${TestArray1->Debug}
  DetailPrint 'Subtracting TestArray2 from TestArray1...'
  ${TestArray1->Subtract} TestArray2
  ${TestArray2->Delete}
  ${TestArray1->Debug}
  ${TestArray1->Delete}
SectionEnd 
result is 'we3456.tmp' - can't obviously...

# array 1.5rc2, nsis 2.30

btw docs have typo
1.6.27 ${myArray->Subtract} myArray2

Takes away items in myArray2 that are also in myArray. Items are matched case sensitively.

For a compilable NSIS script example, see Examples\NSISArray\Subtract.nsi.
underlined say wrong direction - it takes content in (2) from (1) away - like example do

Might better: "takes away items in (2) from (1)"

#fix
for my problem i have to add a fake entry (like "---") to both arrays - then it works.
CancerFace#
@Brummelchen
the script works for me as well. The uninstaller that is generated however is the one that crashes. Both on XP/SP2 and 2000/SP4 with nsis 2.31 and array 1.5 RC6. On different PCs as well.
CF
Brummelchen#
>> The uninstaller that is generated however is the one that crashes.

how do i get the uninstaller from that script?
might this line help me to understand

WriteUninstaller "$exedir\uninstall.exe"

>> array 1.5 RC6.

Where to get? 😁

i am currently working on a special supporting program again
which need arrays... ok, there are many other ways but array
will fit them fastest ^^ (snapshot before & after)
Brummelchen#
ok, confirmed with 15rc2 - i now found the uninstaller here.
for my blame i did not investigate more time yesterday about that.
au_.exe crashes
Brummelchen#
oh, i see - thats same i have - but i got it from here

(there is no such info, only mentioned as 1.5 in html doc)
Afrow UK#
There is a deeper problem here - possible bug with WriteList. I don't have a build machine available right now so I'll continue tomorrow.

Stu
Afrow UK#
CancerFace, I found that the crash that you were experiencing was because your array name was too long. The new build has 32 bytes allocated for array names (as opposed to 16).

Brummelchen, fixed Subtract.

I also found a memory leak in the Delete function which is now fixed.



Stu
congtak#
Hi, I think there is a possible bug in the {Array->ReadtoStack} function
when I do ${TestArray->ReadtoStack} 0 -1
and TestArray only has one element in it, nothing gets copied to the stack.

To test this I change the ReadToStack.nsi
${TestArray->WriteList} "'zero'"
${TestArray->ReadtoStack} 0 -1
Pop $R0
$R0 is empty.

Thank you
Brummelchen#
${myArray->Concat} $Var ""

returns empty string - is the connecting character mandatory?
Brummelchen#
i have another problem, pls have a look here - it blows the memory and make it crash
Function anagram_sort
  Pop  $R9 ;source
  Push $R5
  Push $R6
  Push $R7
  Push $R8
  ;insert seperater
  StrCpy $R6 ""
  StrCpy $R7 "0"
  loop1:
  StrCpy $R8 $R9 1 $R7
  StrCmp $R8 "" loop1_done
    StrCpy $R6 "$R6$R8|"
    IntOp $R7 $R7 + 1
    Goto loop1
  loop1_done:
  StrCpy $R9 $R6 -1
  ;messagebox mb_ok "'$R9'"
  ${anagram->Init}
  ${anagram->Clear}
  ;write array
  ${anagram->WriteListC} $R9 "|"
  ;sort array
  ${anagram->Sort} ""
  ;read array
  StrCpy $R9 ""
  ${anagram->ReadtoStack} 0 -1
  Pop $R5
  StrCpy $R9 "$R9$R5"
  Pop $R5
  StrCpy $R9 "$R9$R5"
  Pop $R5
  StrCpy $R9 "$R9$R5"
  Pop $R5
  StrCpy $R9 "$R9$R5"
  Pop $R5
  StrCpy $R9 "$R9$R5"
  Pop $R5
  StrCpy $R9 "$R9$R5"
  Pop $R5
  StrCpy $R9 "$R9$R5"
  Pop $R5
  StrCpy $R9 "$R9$R5"
  Pop $R5
  StrCpy $R9 "$R9$R5"
  ${anagram->Delete}
  Push $R9
  Push "|"
  Push ""
    Call StrRep
  Pop $R9
  ;messagebox mb_ok "'$R9'"
  Pop  $R8
  Pop  $R7
  Pop  $R6
  Pop  $R5
  Push $R9
FunctionEnd 
The code works on 429mbyte with 4meg lines each 9 byte (11 with LF).
The crash is around 2.7mbyte above line 256.400.
(simple character sort)

The Math script instead with bubble sort is working here now for hours.
Ilitirit#
How do I add an empty string to an array?

I tried
${Array->Write} $0 ""

but it doesn't add the element.
TobbeSweden#edited
NSISArray::SearchI seems to modify the array elements. Would it be possible to just temporarily convert them to lower case when comparing?

Edit: Something like this might possibly work. I haven't tried it, or even compiled it...
// Function: Search for string inside string
BOOL my_strstr(TCHAR *s1, int len_s1, TCHAR *s2, int len_s2, BOOL bCaseSensitive)
{
int i = 0, j = 0;

for (;😉
{
if (s2[j] == '\0')
return TRUE;
if (s1[i] == '\0')
return FALSE;
if (s1[i] == s2[j] ||
(!bCaseSensitive && LOWORD(CharLower(s1[i])) == LOWORD(CharLower(s2[j]))))
{
i++;
j++;
}
else
{
i = i - j + 1;
j = 0;
}
}
return FALSE;
}
TobbeSweden#
I've got an array declared in the global scope with ${Array}. I call init on it in .onInit. After that I can use it in the installer.

Trying to use it in the uninstaller I get an error about the array not existing. Trying to init it in un.onInit I get an error about calling init on the array twice :S

What should I do? Do I really have to make two arrays, one for install and one for uninstall?
Animaether#
Originally posted by TobbeSweden
Do I really have to make two arrays, one for install and one for uninstall?
In short: yes.
TobbeSweden#
Here's another problem I'm having. SizeOf doesn't work...

This code:

${whereprofilesarray->SizeOf} $3 $4 $5
MessageBox MB_OK "EnumerateUsers.nsh(${__LINE__}): $3 = $4 = $5 Will show debug next"
${whereprofilesarray->Debug}

NSISArray::ErrorStyle /NOUNLOAD 2

${whereprofilesarray->SizeOf} $3 $4 $5
MessageBox MB_OK "EnumerateUsers.nsh(${__LINE__}): $3 = $4 = $5 Will show debug next"
${whereprofilesarray->Debug}
Gives me these message boxes:

---------------------------
Program Installation
---------------------------
EnumerateUsers.nsh(34.32): 1024 = 5 = 1 Will show debug next
---------------------------
OK
---------------------------


---------------------------
Program Installation
---------------------------
EnumerateUsers.nsh(34.38): 5 = 1 = Will show debug next
---------------------------
OK
---------------------------
As you can see in the second message box the SizeOf return values are wrong. The last return value (blank in this case) seems to vary depending on what's on the stack...

The Debug output looks correct.
TobbeSweden#
This particular problem goes away if I remove 'NSISArray::ErrorStyle /NOUNLOAD 2' and use '${ArrayErrorStyle} MsgBox' instead.

I'm using scripts from the wiki that uses the direct plugin calls (NSISArray::*) for portability and in my own code I use the header wrappers because I find them easier to work with.

Is this the real source of my problems? Is it a known fact that you can't mix the header file macros with direct NSISArray:: calls?
TobbeSweden#
I've "solved" it by replacing all NSISArray:: calls with their header macro alternatives. Everything seems to work as it should now 🙂