[Last Call] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 238
  • Last Modified:

adding a directory to the system wide $PATH env variable on windows

setting and reading env variables is easy, the probkem i have is that windows has the local user PATH and the system wide PATH variables.

is there any way add a directory (for example c:\myapp) to the current system wide $PATH? further more, any way to make it stay there?

code will be appreciated, thanks!
0
urif
Asked:
urif
  • 5
  • 3
  • 2
2 Solutions
 
Jaime OlivaresCommented:
You can do it directly into Windows Registry.

So, I think you will need something like:
HKEY hk;
DWORD returnval;
if (!RegOpenKey(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment", &hk)) {
 
    RegSetValueEx(hk, "Path", 0, REG_EXPAND_SZ, (LPBYTE)youBufferHere, strlen(youBufferHere) + 1);

 
    SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0,(LPARAM) "Environment", SMTO_ABORTIFHUNG,5000, &returnval);
}
0
 
Jaime OlivaresCommented:
Just have found a ready-made solution:
http://www.experts-exchange.com/Programming/Programming_Platforms/Win_Prog/Q_20618848.html

But don't forget to broadcast a WM_SETTINGCHANGE message to change take effect.
0
 
urifAuthor Commented:
ok, the 1st code will likely overwrite the existing path right?
if so, when i tried to read from the registry to 1st save the existing path the registry froze and then the system. how do you do that then? sorry, i am a linux programmer trying to code under windows.

the second message you gave me, well, that looks more like microsoft's own version of C, i just need a simple C code example. that's all

thanks
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
Jaime OlivaresCommented:
>the second message you gave me, well, that looks more like microsoft's own version of C, i just need a simple C code example.
It is not microsoft own version of C, it is Windows API version, so it will compile with any C compiler for Windows.

But if you prefer, replace 'LPCTSTR' with 'const char *', and 'TCHAR' with 'char'

0
 
urifAuthor Commented:
still it won't compile, let's forget about that version. why do you think the registry might freeze when i tried to reas from it?

do you know a good way to read the value for a key in the registry?

thanks
0
 
urifAuthor Commented:
ok, take a look at this, is the same function but with tiny changes:

int AddToPath (const char * pszPath, int bSystem)
{

    int bRC = 1;

    const char * pszSubKey = bSystem ? "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment" : "Environment";
    HKEY hBase = bSystem ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;

    HKEY hKey = NULL;
    REGSAM sam = KEY_SET_VALUE | KEY_READ;

    if ( ERROR_SUCCESS != RegOpenKeyEx ( hBase, pszSubKey, 0, sam, &hKey)) {

        return FALSE;
    }

   try {

    char acPath [ 2048];
    DWORD dwType = REG_SZ;
    DWORD dwSize = sizeof ( acPath);

    // get old "PATH"

    if ( ERROR_SUCCESS != RegQueryValueEx ( hKey, _T ( "PATH"), 0, &dwType, ( LPVOID) acPath, &dwSize)) {

       exit 1;
    }

    // append new entry

    _tcscat ( acPath, pszPath);

    dwSize = _tcslen ( acPath);

    // set new "PATH"

    if ( ERROR_SUCCESS == RegSetValueEx ( hKey, _T ( "PATH"), 0, dwType, ( LPVOID) acPath, dwSize))
   {

        bRC = TRUE;
    }


    }
   finally
   {

        RegCloseKey ( hKey);
    }

    return bRC;
}

now, i can't find the declaration of HKEY (that i asume is a type that involves registry keys) and i definatelly can't find all those casts to _T (tries with char and char *, but nop)

0
 
urifAuthor Commented:
ok, i got it, but still it won't update the path until i close the command line (cmd) or restart windows. even with the sendmessage...

0
 
Julian HansenCommented:
Have you included the following?

#include "windows.h"
#include "string.h"

0
 
urifAuthor Commented:
yes, i included both, it also works now, but i still i can make it update the command line shell or other application, i need to close them all and re open them in order to make them reas the new path.

i used:

SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0,(LPARAM) "Environment", SMTO_ABORTIFHUNG,5000, &returnval);

on jaime_olivares suggestion and it returns ok, a non zero value, meaning that the function completed succesfully (according to msdn)
any ideas?

thanks so much
0
 
Julian HansenCommented:
There is a problem with the shell. It is passed the environment variables as a memory structure when it is created and does not check for changes.

You can test this by opening two shells and changing the path setting in 1 using the set path= command and you will notice that it does not replicate the change to the other shells.

With respect to other applications not picking it up - this is an application dependent operation. By sending the WM_SETTINGCHANGE message you are merely providing a notification to all windows that a setting has changed. The onus is then on each application to respond to that message and reload settings. If the application has not been coded to do this then you are pretty much stuck.

0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 5
  • 3
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now