Skip to content
⌘ NSIS Forum Archive

EnVar Plugin - Adds and removes environment paths

26 posts

JasonFriday13#

EnVar Plugin - Adds and removes environment paths

This plugin has been in development on and off again for about a year and a half, and it's finally ready for public release.

Basically this plugin allows you to check for environment variables, check for paths in those variables, add and remove paths, and delete environment variables.

Download from here: http://nsis.sourceforge.net/EnVar_plug-in.

If you have any problems, reply to this thread.
JasonFriday13#
I have updated this plugin, as requested by a member of the community I have added updating the installer environment from the registry with a function.

Check it out at the wiki page: https://nsis.sourceforge.io/EnVar_plug-in.
JasonFriday13#
I have updated this plugin, I rewrote most of it to use a double linked list to get around some memory issues, and I have added two more error codes (the error codes have changed order as a result).

Check it out at the wiki page: https://nsis.sourceforge.io/EnVar_plug-in.
JasonFriday13#
I made another small update, now EnVar::update supports passing "null" as a RegRoot, which causes the named variable to be removed from the installer environment.

Check it out at the wiki page: https://nsis.sourceforge.io/EnVar_plug-in.
broleke#
Hi,
I'm wondering if you are not getting a buffer overflow with some unicode locale handling.
When looking at the example from MSDN, we can see that there is a while loop for any allocation:
Retrieves the type and data for the specified value name associated with an open registry key. (ANSI)

In your implementation, you assume that APPEND_SIZE and IS_UNICODE_AND_ODD function would allow to get a correctly sized buffer. I'm not sure about that.
Actually, I could observe some issue with German and Japanese ReadRegVar checks when checking for a given string in PATH.
What do you think?
JasonFriday13#
MSDN also says this:
If lpData is NULL, and lpcbData is non-NULL, the function returns ERROR_SUCCESS and stores the size of the data, in bytes, in the variable pointed to by lpcbData. This enables an application to determine the best way to allocate a buffer for the value's data.
In older versions of the plugin I did use a while loop for allocation, but I have rewritten it to request the amount of space required and added a few more bytes on the end for a NULL terminator and maybe a semicolon if needed. APPEND_SIZE also changed, it was 4 bytes, now it's 4 TCHARs (4 bytes for ansi, 8 bytes for unicode). It's ok if the memory allocated is bigger than the data, it just means the end of the memory is unused.

I haven't tested any other languages than English, sorry. If you can provide a sample script that shows the problem, I can take a look at it.
broleke#
Thanks for your feedback.
I'm checking if a given folder is already present in the PATH, using EnVar::Check

EnVar::Check "PATH" "$INSTDIR\bin"

In this case, PATH is populated with folders using Japanese characters (for instance the \ separator is written differently).
broleke#
Another question (sorry for that 🙂: where should we get the release, from https://github.com/GsNSIS/EnVar/releases or https://nsis.sourceforge.io/EnVar_plug-in ?
JasonFriday13#
The only place I release code is either on the nsis wiki or on sourceforge.

[edit] Version history is here: https://nsis.sourceforge.io/File:EnVar_plugin.zip.
JasonFriday13#
This simple script works for me, I wonder what else is happening?

Name "test1"
RequestExecutionLevel user
Unicode true
ShowInstDetails show
!addplugindir "."
Section
  ; using hkcu
  EnVar::AddValue "test1" "こんにちは、元気ですか"
  Pop $0
  DetailPrint "EnVar returned=|$0|"  
  EnVar::Check "test1" "こんにちは、元気ですか"
  Pop $0
  DetailPrint "EnVar returned=|$0|"
  SetAutoClose False
SectionEnd 
Anders#
Chopping a string at arbitrary positions is what kills non-English Unicode support but as long as you only chop at basic non-alphabet ASCII characters like ; and | you should be alright.

The Japanese Yen is seen as the path separator in non-Unicode programs because the Japanese codepage has the Yen where \ should be. MSDN says WideCharToMultiByte converts both \ and the Yen to the same character on Japanese systems.
broleke#
Thanks you both for your answer.
Jason, on the example, do you get the same behavior when checking at an existing PATH (HKLM) already populated with lots of stuff ?
JasonFriday13#
At the moment I'm only checking for white space and semicolons at the start of the values, and only the semicolon to separate the values.

I attached a picture of a test with two different Japanese strings. I had to save the .nsi as a proper unicode file to get this result.
broleke#
Jason, can you use your nsi file and update the call to EnVar::check to check for the PATH (HKLM), that would need to be fully populated first ?
drustsmith#
Hey JasonFriday13, I know this is a super old thread, but hoping to get some insight in to a head banging bug I'm hitting with the EnvVar Plugin.

When it installs the exe it is meant to update the PATH variable with my application's path, but occasionally, about 1/4 time, it appends random junk characters to the end of the PATH variable. It smells a lot like a string termination / overflow error.


When I install my application half the time it gets random funky characters appended to it.

Versions I use:
https://nsis.sourceforge.io/mediawik...Var_plugin.zip
- nsis - nsis v3.9.0
- vcredist140 - vcredist140 v14.38.33135 ​


# Installer
Section
SetOutPath $INSTDIR
File /r ..\dist\test-cli
EnVar::AddValueEx "PATH" "$INSTDIR\test-cli"
WriteUninstaller $INSTDIR\test-cli\uninstall.exe
SectionEnd

drustsmith#
I managed to get it working consistently, with the strangest of hacks:
```
; Set to HKCU
EnVar::SetHKCU
DetailPrint "EnVar::SetHKCU"

EnVar::AddValueEx "PATH" "$INSTDIR\test-cli"
EnVar::AddValueEx "PATH" "$INSTDIR\test-cli"
```

If I just put in the duplicate `AddValueEx` that was not enough to fix it. My poorly informed guess is the DetailPrint is helping to clear some string buffer before the AddValue call.
JasonFriday13#
HKCU is the default when the plugin is loaded, you shouldn't have to manually call it unless you have to switch back from writing to HKLM. Try using the regular 'EnVar::AddValue' instead, the plugin can handle the difference between regular strings and expanded strings. I only included ::AddValueEx in there for brand new variables, and it also serves to upgrade regular variables to their expanded versions. So, if you are not writing an expanded value in the script, use the regular ::AddValue call. Oh, and pop the return value off the stack too.
cwpdeveloper#
I've just had the exact same experience as drustsmith and landed here after trying to google a solution. As suggested, I changed to use 'EnVar::AddValue' instead of ::AddValueEx, and made sure to pop the return value. No change - still got corrupted characters added to my path about half the time. As drustsmith said, adding this:

EnVar::SetHKCU
DetailPrint "EnVar::SetHKCU"

and doubling up the ::AddValue calls makes it work consistently (no corruption at all since that change after running it many, many times, whereas before that change, I never had to run it more than three times to see the problem occur).

I can live with this (weird) workaround, but a fix would be even better! 🙂
JasonFriday13#
Cool. If you can provide an example script that does this, and a screenshot of the corrupted characters, I can have a look at debugging this. It's alot harder to find a problem if it works on my machine. It could be just a malformed value in the users environment that is tripping up my plugin, this would be good to know. But, I can always convert this to a .exe and add a bunch of logging to it to see if anything is out of the ordinary.
Iaacov#
Hi Jason,
Would be nice to have SetValue and SetValueEx functions to entirely set or replace a variable.
Some variables, e.g. TEMP, hold just one value. Setting them to a new value currently requires 2 calls; Delete followed by AddValue.

Great work!
JasonFriday13#
If you are only writing one value, you can use a regular WriteRegStr with the appropriate path and name. MSDN has info on where the environment variables live in the registry.
dstarke#
Thank you for this plugin!

I have just started using it and I found a bug in the code. I hope this is the right place to report it.
In Check, AddValue, AddValueEx, DeleteValue, Delete and Update g_stringsize is being used before being initialized via EXDLL_INIT().
This results in a very small string buffer of APPEND_SIZE (= 4) characters. This causes buffer overruns.
I recommend replacing every use of g_stringsize with string_size in envar.c.

P.S.: The issue may not occur if SetHKCU or SetHKLM is being called first.
JasonFriday13#
Hey thanks. I must have missed that when I was simplifying the code. Also I'll add a SetValue / SetValueEx function as well at some point, but I'm quite busy right now.
JasonFriday13#
Been a long time coming, I have updated the EnVar plugin. Fixed a memory issue (thanks dstarke), and added SetValue and SetValueEx to set a value and overwrite any existing paths.

Check it out at the wiki page: https://nsis.sourceforge.io/EnVar_plug-in.