Skip to content
⌘ NSIS Forum Archive

Writing a REG_MULTI_SZ value

14 posts

ROB_the_Robot#

Writing a REG_MULTI_SZ value

Hi everyone. I'm fairly new to NSIS scripting, and I can't seem to figure out how to write a REG_MULTI_SZ value to the registry. I had tried using a converter that converts .reg files to NSIS scripts, but the output ends up being WriteRegBin, which won't do. So how is this done? Any help would be appreciated. Thanks in advance.
ROB_the_Robot#
Originally Posted by JasonFriday13 View Post
Thanks for the helpful reply. How exactly do I implement that? Do I really have to add all that to my script just to add one registry value? Why do thinks like 'HKEY_LOCAL_MACHINE' need to be defined? Where am I supposed to put the registry value in all this? Is this really the simplest way to do this? I'm sorry, but it seems like something as basic as this should be a more native feature.

Originally Posted by Anders View Post
Are your strings known at compile-time?
What do you mean by that?

Like I said, I'm kind of new to all this, so I apologize for all the questions.
Anders#
If you know the strings when compiling then you can hardcode the binary layout:

Function RegWriteRawData ; HKEY, Path, Name, Type, Address, Size
System::Store S
Pop $6 ; Size
Pop $5 ; Address
Pop $4 ; Type
Pop $3 ; Name
Pop $2 ; Path
System::Call 'ADVAPI32::RegCreateKey(is, tr2, *p.r1)i.r0'
IntCmp $0 0 "" fail fail
System::Call 'ADVAPI32::RegSetValueEx(pr1,tr3,i0,ir4,pr5,ir6)i.r0'
System::Call 'ADVAPI32::RegCloseKey(pr1)'
fail:
System::Store L
FunctionEnd
!macro RegWriteRawData HKEY Path Name Type Address Size
Push ${HKEY}
Push "${Path}"
Push "${Name}"
Push "${Type}"
Push "${Address}"
Push "${Size}"
Call RegWriteRawData
!macroend
Section
!define HKEY_CURRENT_USER 0x80000001
!define REG_MULTI_SZ             7
System::Call '*(&t6 "First", &t9 "Whatever", &t8 "Goodbye", &t1"", &l.r1)p.r0' ; NSIS 2.51+ (Each item must specify string length + 1) 
!insertmacro RegWriteRawData ${HKEY_CURRENT_USER} "Software\NSIS\Test" "MultiStrTest" ${REG_MULTI_SZ} $0 $1
System::Free $0
SectionEnd 
ROB_the_Robot#
Alright thanks, that looks a lot simpler/easier to understand. I'm still a bit stumped on a few things though. Where do I add the data in this? I mean I kind of figured where to put the registry path and the value name, but I can't figure out where to add the actual data. Do I replace the "First" "Whatever" and the "Goodbye" with each new line? And if that's the case, do I have to update them with the new lengths?

Edit:
Whenever I try to compile, I get this error:
Plugin Command: Call *(&t6 "First", &t9 "Whatever", &t8 "Goodbye", &t1"", &l.r1)p.r0
!insertmacro: RegWriteRawData
!insertmacro: macro "RegWriteRawData" requires 6 parameter(s), passed 5!
Anders#
Did you use my exact code or did you change it? When posting output you should also include the code it self. Which NSIS version are you using?

And yes, you need to update the length when using other strings...
ROB_the_Robot#edited
Yeah, I used your exact code. The only thing I did was I changed HKEY_CURRENT_USER to HKEY_LOCAL_MACHINE, and I separated the macro/function and implemented everything else into a pre-existing section.
Anders#
Originally Posted by ROB_the_Robot View Post
Yeah, I used your exact code. The only thing I did was I changed ...
You either used my exact code or you didn't.

Because you refuse to show us your code nor tell us which version you are using all I can do is guess. Perhaps you defined HKEY_LOCAL_MACHINE incorrectly?

When the compiler is telling you there is something wrong with the parameters then obviously you should double check them...
ROB_the_Robot#
Yeah, sorry. I'm using NSIS 2.51. I know I didn't define HKEY_LOCAL_MACHINE incorrectly; I even looked at the thread JasonFriday13 posted the link to so I could be sure I got the information correct. Here's what I have:
!define HKEY_LOCAL_MACHINE 0x80000002
I figured out the compile error though. It turns out I had defined HKEY_LOCAL_MACHINE and REG_MULTI_SZ outside of the 64-bit part of the section with the rest of the code inside the 64-bit part, and that was causing problems. So now it compiles with no problems, but I don't see the data in the registry after I run the installer. I'm sure this is not an issue with permissions, as I'm using the Administrator account and I have no problems modifying the registry key myself.

Edit:
Well actually it writes to keys within WOW6432Node no problem, but it won't write to anything outside of that (64-bit registry keys) for some reason. I can't tell if it's an issue with the RegView settings or not, but I can't seem to get it to work either way. Here's what I have now:

Function RegWriteRawData ; HKEY, Path, Name, Type, Address, Size
${If} ${RunningX64}
SetRegView 64
${Else}
SetRegView 32
${EndIf}
System::Store S
Pop $6 ; Size
Pop $5 ; Address
Pop $4 ; Type
Pop $3 ; Name
Pop $2 ; Path
System::Call 'ADVAPI32::RegCreateKey(is, tr2, *p.r1)i.r0'
IntCmp $0 0 "" fail fail
System::Call 'ADVAPI32::RegSetValueEx(pr1,tr3,i0,ir4,pr5,ir6)i.r0'
System::Call 'ADVAPI32::RegCloseKey(pr1)'
fail:
System::Store L
FunctionEnd

!macro RegWriteRawData HKEY Path Name Type Address Size
${If} ${RunningX64}
SetRegView 64
${Else}
SetRegView 32
${EndIf}
Push ${HKEY}
Push "${Path}"
Push "${Name}"
Push "${Type}"
Push "${Address}"
Push "${Size}"
Call RegWriteRawData
!macroend
Am I missing anything? Would I be able to remove "SetRegView 64" and "SetRegView 32" from "Function RegWriteRawData" and "!macro RegWriteRawData" since I already have those set in ".onInit"? Keep in mind that each of my sections has a 64-bit part (${If} ${RunningX64}) and a 32-bit part (${Else}) so I would like to keep things compatible on both platforms.
Anders#
SetRegView has no effect on System::Call, you need to switch from RegCreateKey to RegCreateKeyEx and add the WOW SAM flag.

http://nsis.sourceforge.net/Registry_plug-in does support SetRegView AFAIK.
ROB_the_Robot#
Umm, I'm not quite sure I understand completely. Do I just replace any instance of RegCreateKey in the code with RegCreateKeyEx? And where can I find more info on the WOW SAM flag? Because I don't know how to implement it. I can't seem to find anything about it on Google either.
Anders#
I realize that it is hard to use the System plug-in but the first google result for "RegCreateKeyEx" should be a good starting point. Translating the parameters is the hard part.

Function Reg64WriteRawData ; HKEY, Path, Name, Type, Address, Size 
System::Store S 
Pop $6 ; Size 
Pop $5 ; Address 
Pop $4 ; Type 
Pop $3 ; Name 
Pop $2 ; Path 
System::Call 'ADVAPI32::RegCreateKeyEx(is, tr2, i0, p0, i0, i 0x20006|0x0100, p0, *p.r1, *i)i.r0' ; KEY_WRITE+KEY_WOW64_64KEY
IntCmp $0 0 "" fail fail 
System::Call 'ADVAPI32::RegSetValueEx(pr1,tr3,i0,ir4,pr5,ir6)i.r0' 
System::Call 'ADVAPI32::RegCloseKey(pr1)' 
fail: 
System::Store L 
FunctionEnd 
!macro Reg64WriteRawData HKEY Path Name Type Address Size 
Push ${HKEY} 
Push "${Path}" 
Push "${Name}" 
Push "${Type}" 
Push "${Address}" 
Push "${Size}" 
Call Reg64WriteRawData 
!macroend 
RequestExecutionLevel admin
Section 
!define HKEY_CURRENT_USER 0x80000001
!define HKEY_LOCAL_MACHINE 0x80000002
!define REG_MULTI_SZ 7
System::Call `*(&t11 "Who's next", &t9 "You Know", &t22 "Can't make up my mind", &t1"", &l.r1)p.r0` ; NSIS 2.51+ (Each item must specify string length + 1)  
!insertmacro Reg64WriteRawData ${HKEY_LOCAL_MACHINE} "Software\NSIS\Test" "MultiStrTest" ${REG_MULTI_SZ} $0 $1 
System::Free $0 
SectionEnd 
(Note: v3.02 now supports this natively)