GetEnv Environment Variable question


I received a question:


 


Can you explain me the internal behavior of VFP’s GetEnv() function. It’s seems to me that VFP during startup make a copy of environment block and GetEnv() works with this internal buffer. So using WinAPI’s SetEnvironmentVariable and GetEnvironmentVariable do not change behavior of GetEnv() function. And what about behavior of other VFP functions and other internals of VFP – is it safe to change process’s environment block or …


 


 


The Fox GetEnv function is just a wrapper around the C Runtime library getenv function


When a process starts, a copy of the environment is put in the Program Segment Prefix. This copy is then used for any child processes. This is the way it’s been ever since the DOS days. I remember examining the PSP in the 16 bit command line debugger: type DEBUG in a Windows Command Prompt and it’s still there!


 


From the documentation of _putenv:


 


_putenv and _wputenv affect only the environment that is local to the current process; you cannot use them to modify the command-level environment. That is, these functions operate only on data structures accessible to the run-time library and not on the environment “segment” created for a process by the operating system. When the current process terminates, the environment reverts to the level of the calling process (in most cases, the operating-system level). However, the modified environment can be passed to any new processes created by _spawn, _exec, or system, and these new processes get any new items added by _putenv and _wputenv


 


Thus changing the environment variable only affects the current process and child processes.


The code below creates an environment variable called “test” and sets it to the current time.


Switch to another process and see what happens to the environment variable.


Instantiate an EXE server, have it check the variable


Instantiate a DLL server and have it check the variable


 


 


CLEAR ALL


CLEAR


 


oEnv=CREATEOBJECT(“environ”)


?”ComputerName=”,oEnv.GetVar(“ComputerName”)


?”Test=”,oEnv.GetVar(“test”)


oEnv.SetVar(“test”,TRANSFORM(DATETIME()))


?”Test=”,oEnv.GetVar(“test”)


!set > d:\t.txt


TYPE d:\t.txt


 


DEFINE CLASS Environ as Custom


      PROCEDURE init


            DECLARE integer GetEnvironmentVariable IN WIN32API string, string @, integer dwSize


            DECLARE integer SetEnvironmentVariable IN WIN32API string lpName, string lpValue


      PROCEDURE GetVar(cVar as string)


            LOCAL nLen,cstr


            cstr=SPACE(200)


            nLen=GetEnvironmentVariable(cVar,@cstr, LEN(cstr))


            IF nLen>0


                  cstr=LEFT(cstr,nLen-1)


            ELSE


                  cstr=””


            ENDIF


            RETURN cstr


      PROCEDURE SetVar(cVar as string, cValue as String)


            SetEnvironmentVariable(cVar, cValue)


            return


     


ENDDEFINE


 


 


 


 


 


 

Comments (2)

  1. marco cenzato says:

    I suppose that nowaday this behavior is useless and odd: at the DOS time the enviroment was only one common to all process and the C runtime library added this kind of workaroud (PSP) to avoid global modification.

    In Win32 the Get/SetEnvironmentVariable API protect each process from the others because they work on the process environment.

    I think that would be better if VFP internally use the regular GetEnvironmentVariable API: in my programs for this ‘problem’ I didn’t use GetEnv bat a couple of API wrapper function xGetEnv() and xSetEnv().

    And what about the GetCommandLine() API? Is it the same problem?

  2. wgcs says:

    For anyone who really does need to permanently change the environment variables, this page at MSDN explains it: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/environment_variables.asp

    Basically, just edit the registry at HKEY_LOCAL_MACHINESystemCurrentControlSetControlSession ManagerEnvironment