Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Does anyone know how I can retrieve Environment Variables via Perl? I've looked at the Win32::API module but didn't see anything listed.

Thanks

Replies are listed 'Best First'.
Re: Win32 GetEnvironmentVariables?
by Fletch (Bishop) on Nov 10, 2006 at 21:36 UTC
      Sorry I should have been more specific. I actually need to access a dll on windows and retrieve specific environment variables it sets.

        Unless the dll was bound to perl, the changes won't be made until you load the dll. It then depends when the dll sets/changes the environment variables.

        If they are set/changed by the dlls initialisation, then you can

        use Win32; my $hModule = Win32::Loadibrary( 'thedll' );

        to load the library and then use GetEnvironmentStrings or GetEnvironmentVariable (via Win32::API) to get the modified environment for the perl process.

        If they don't get set until a particular api within the dll is called, then use Win32::API to load the dll and call the api before retrieving the new/modified values.


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
        There's no way of knowing which env vars a DLL sets unless you are the child process for which it has set them. That child process can access them via %ENV.
        If they are environment variables, why can't you access them through %ENV?
Re: Win32 GetEnvironmentVariables?
by swampyankee (Parson) on Nov 10, 2006 at 22:22 UTC

    Presuming you're using ActiveState's port, Look in the Win32 (not Win32::API) module for Win32::ExpandEnvironmentStrings(STRING) To quote the documentation:

    [EXT] Takes STRING and replaces all referenced environment variable names with their defined values. References to environment variables take the form %VariableName%. Case is ignored when looking up the VariableName in the environment. If the variable is not found then the original %VariableName% text is retained. Has the same effect as the following:

    $string =~ s/%([^%]*)%/$ENV{$1} || "%$1%"/eg

    back to swampyankee... Incidentally, the built-in %ENV hash should work, except that hashes are case sensitive, but Windows' environment variables are not: $ENV{fred} and $ENV{FRED} are not the same hash elements, but Win32::ExpandEnvironmentStrings('fred') will refer to the same variable as Win32::ExpandEnvironmentStrings('FRED').

    Update:  Thanks to ikegami for pointing out that %ENV is magical, at least on Windows

    emc

    At that time [1909] the chief engineer was almost always the chief test pilot as well. That had the fortunate result of eliminating poor engineering early in aviation.

    —Igor Sikorsky, reported in AOPA Pilot magazine February 2003.

      It's true that hash keys are case-sensitive for normal hashes, but %ENV is magical.

      >perl -e "print $ENV{OS} Windows_NT >perl -e "print $ENV{os} Windows_NT

      Furthermore, the correct usage of Win32::ExpandEnvironmentStrings is Win32::ExpandEnvironmentStrings('%VAR%').

      >perl -e "use Win32; print Win32::ExpandEnvironmentStrings('OS') OS >perl -e "use Win32; print Win32::ExpandEnvironmentStrings('%OS%') Windows_NT >perl -e "use Win32; print Win32::ExpandEnvironmentStrings('OS=%OS%') OS=Windows_NT

      There is a difference between %ENV and Win32::ExpandEnvironmentStrings.

      >echo %VAR% %OS% >perl -e "print $ENV{var} %OS% >perl -e "use Win32; print Win32::ExpandEnvironmentStrings('%VAR%') Windows_NT

      Update: Added 2nd and 3rd para.

        Thanks...I never knew that.

        emc

        At that time [1909] the chief engineer was almost always the chief test pilot as well. That had the fortunate result of eliminating poor engineering early in aviation.

        —Igor Sikorsky, reported in AOPA Pilot magazine February 2003.
        but %ENV is magical
        %ENV appears to be magical only under shells where the lookup and expansion of environmental variables is a case-insensitve operation.

        $ set comspec ComSpec=C:\WINDOWS\system32\cmd.exe $ echo %comspec% C:\WINDOWS\system32\cmd.exe $ echo %COMSPEC% C:\WINDOWS\system32\cmd.exe $ perl -le "print 'comspec : ', $ENV{comspec}" comspec : C:\WINDOWS\system32\cmd.exe $ perl -le "print 'COMSPEC : ', $ENV{COMSPEC}" COMSPEC : C:\WINDOWS\system32\cmd.exe
        On systems (shells rather) where there is a distinction between the case-sensitivity of Env. Vars, %ENV behaves rather normally like a hash should.
        $ set | grep -i ^shell shell /bin/tcsh $ echo $shell /bin/tcsh $ echo $SHELL $ perl -le 'print "shell : ", $ENV{shell}' shell : $ perl -le 'print "SHELL : ", $ENV{SHELL}' SHELL : /bin/bash
        It's likely %ENV is tied (I am guessing) or has mechanism similar to tie associated with it to pass lookups to an underlying system call. It should be noted that not all environmental varaibles are populated into %ENV and in other cases, the values of %ENV contradict those of the shell (as shown above). Don't rely too heavily on information or its validity presented to you in %ENV;

        There is a difference between %ENV and Win32::ExpandEnvironmentStrings.

        %ENV holds literals (just like the shell, in most cases atleast), Win32::ExpandEnvironmentStrings() tests the expansion of a literal in the win32 environment and returns it after substituting values defined for the current user.
        $ set var var=%OS% $ perl -MWin32 -e "print $ENV{var} .= ' evaled' , ' => ', Win32::Expa +ndEnvironmentStrings($ENV{var})" %OS% evaled => Windows_NT evaled
        For the purposes of delayed expansion in the environment, Win32::ExpandEnvironmentStrings() then takes a literal string of the form !Foo! rather than %Foo%.
        $ set var=Foo $ set var var=Foo $ set var=Bar & perl -MWin32 -e "print Win32::ExpandEnvironmentStrings +('%var%')" Foo $ set var var=Bar $ set var=Baz & perl -MWin32 -e "print Win32::ExpandEnvironmentStrings +('!var!')" Baz $ set var var=Baz