Recognising when environment variables have changed lazarus / 34-Windows ---------------------------------------------------------------------- TS-MPS · 2013-04-26 13:57 Hi I have written a Lazarus program for Windows that generates a string grid of environment variables and their values when you click a 'Show environment variables...' button on the form. However if you change an environment variable value whilst the program is running, or add a new environment variable then the program does not "see" this even though the code that generates the list is re-run by the user: Code: [Select]env_count := GetEnvironmentVariableCount ;   For Ctr := 1 to env_count do   begin     temp_string := sysutils.GetEnvironmentString(Ctr) ;     env_variables [ Ctr ].name := copy( temp_string, 1 , pos ( '=' , temp_string ) -1);     env_variables [ Ctr ].value := sysutils.GetEnvironmentVariable(env_variables [ Ctr ].name);   end; Is this a limitation of the sysutils method of reading the variables ? (i.e. it doesn't support the WM_SETTINGCHANGE message as per http://support.microsoft.com/kb/104011) Is there a better way of reading the environment variables that is more "real-time"? (I'm only concerned with Windows app, so cross platform compatability not an issue) ---------------------------------------------------------------------- Martin_fr · 2013-04-26 14:09 While not the answer to your issue, please also read: http://forum.lazarus.freepascal.org/index.php/topic,20695.0.html ---------------------------------------------------------------------- TS-MPS · 2013-04-26 14:34 Quote from: Martin_fr on April 26, 2013, 04:09:32 pmWhile not the answer to your issue, please also read: http://forum.lazarus.freepascal.org/index.php/topic,20695.0.html Many thanks for the link, although that is talking about changing the variable via the debugger, but I was really refering to changing them via control panel or another utility. So for example, variable 'FOO' is not defined at all and then I do the following sequence: Start my utility Retrieve list of variables using my utility, no mention of 'FOO' in the list of current variables (correct) Using another program than add new variable called 'FOO'. Retrieve list of variables using my utility, no mention of 'FOO' in the list of current variables (technically this is "working as intended" but still not ideal behaviour from the API) Broadcast a WM_SETTINGCHANGE message to all running apps. Retrieve list of variables using my utility, no mention of 'FOO' in the list of current variables (very poor behaviour, the underlying API should "know" the list has changed so when I query it I should expect an up to date list) Close my utility Start my utility Retrieve list of variables using my utility, it now includes the definition of 'FOO' in the list of current variables (correct) Requiring application restarts on environment variable changes might have been acceptable in 1995 or so, but really the functionality is there in the OS now to notify apps of any changes so they should regenerate their internal list of variables on the fly (or even perhaps just query "real-time" rather than maintaining their own copy) ---------------------------------------------------------------------- ludob · 2013-04-27 05:39 The MS support article gives you the solution: read the registry. Environment variables are passed to a process at creation. Only changes in environment variables in the parent process can be seen with the windows GetEnvironmentVariable function. This little snippet reads the registry and dumps the environment variables to a memo: Code: [Select]procedure TForm1.Button1Click(Sender: TObject); var   reg:TRegistry;   envl: TStringList;   i: Integer; begin   reg:=TRegistry.Create();   envl:=TStringList.Create;   try     Reg.RootKey := HKEY_CURRENT_USER;     memo1.lines.Add('USER');     if reg.OpenKeyReadOnly('\Environment') then       begin       reg.GetValueNames(envl);       for i:=0 to envl.count-1 do         begin         memo1.lines.Add(envl[i]+' = '+ reg.ReadString(envl[i]));         end;       end;     Reg.RootKey := HKEY_LOCAL_MACHINE;     memo1.lines.Add('SYSTEM');     if reg.OpenKeyReadOnly('\SYSTEM\CurrentControlSet\Control\Session Manager\Environment') then       begin       reg.GetValueNames(envl);       for i:=0 to envl.count-1 do         begin         memo1.lines.Add(envl[i]+' = '+ reg.ReadString(envl[i]));         end;       end;   finally     reg.free;     envl.free;   end; end; ---------------------------------------------------------------------- marcov · 2013-04-27 10:47 Quote from: TS-MPS on April 26, 2013, 04:34:22 pm Requiring application restarts on environment variable changes might have been acceptable in 1995 or so, but really the functionality is there in the OS now to notify apps of any changes so they should regenerate their internal list of variables on the fly (or even perhaps just query "real-time" rather than maintaining their own copy) Environment variables were already old as concept in 1995. But if the OS allows changing of environment variables, you can simply use winapi functions instead of FPC built in (that cache)