Setting EnvironmentVariables 
Author Message
 Setting EnvironmentVariables

Hey everyone,

Do you know whether it is possible to SET environmentvariables from within a
C#-program?
Sort of like the opposite of  : Environment.GetEnvironmentVariable("path");

Any suggestions will be greatly appreciated :)

Jesper



Thu, 30 Dec 2004 02:06:42 GMT  
 Setting EnvironmentVariables


Quote:
> Hey everyone,

> Do you know whether it is possible to SET environmentvariables from within
a
> C#-program?
> Sort of like the opposite of  :

Environment.GetEnvironmentVariable("path");

Quote:

> Any suggestions will be greatly appreciated :)

You'd have to use native calls, but it gets real hairy as setting
environment variables is platform dependent (varies between Win9x and
NT). This is probably why they didn't do this to begin with.

However, Why would you modify the current process' environment anyhow?
Just use a global configuration object.

You can create a new set of environment variables if you create a new
process (spawn another process for whatever reason).

I think the logic is that environment vars are used to get things
started, not to serve as a configuration store for your app.

-c



Thu, 30 Dec 2004 04:25:50 GMT  
 Setting EnvironmentVariables
Thank you Chad,

I ougth to have written a few lines about why I need to setEnv :)

Im developing a small app for Java-developers that constantly have to mess
around with path and CLASSPATH which is

either done through cmd or the advanced environment settings which only
offer a small textfield for editing a rather long string. As of right

now I can display the variables in a very nice and overlookable way but
modifying and adding to these variables is the real problem.

Also I dont mind making a rather platformspecific solution!

I tried using the Process.Start() to start a small .bat-script feading it
arguments but the regurlar set path statements

(ie: set path=%path%;%1) etc. dont seem to be persistent (works only for the
current process and not if you start up a new prompt)!

Thanks again - I will look into using a global configuration object!

Regards Jesper Linvald


Quote:



> > Hey everyone,

> > Do you know whether it is possible to SET environmentvariables from
within
> a
> > C#-program?
> > Sort of like the opposite of  :
> Environment.GetEnvironmentVariable("path");

> > Any suggestions will be greatly appreciated :)

> You'd have to use native calls, but it gets real hairy as setting
> environment variables is platform dependent (varies between Win9x and
> NT). This is probably why they didn't do this to begin with.

> However, Why would you modify the current process' environment anyhow?
> Just use a global configuration object.

> You can create a new set of environment variables if you create a new
> process (spawn another process for whatever reason).

> I think the logic is that environment vars are used to get things
> started, not to serve as a configuration store for your app.

> -c



Thu, 30 Dec 2004 04:53:49 GMT  
 Setting EnvironmentVariables

Quote:

> Do you know whether it is possible to SET environmentvariables from within a
> C#-program?

Of course.  It's not directly supported by the .NET Framework though, you'd
have to use P/Invoke to call unmanaged code (and therefore, require security
privileges to call unmanaged code).

The reason it's not supported is you have to think about the .NET Process
model.

You have a Process (the run-time environment) containing one or more
AppDomains (lightweight processes), that each contain one or more
Threads (within which your code is executing).

So, you see, you're not only changing YOUR environment, but you are
changing the environment, potentially, of other AppDomains.

Baaaad.   ;-)

Quote:
> Sort of like the opposite of  : Environment.GetEnvironmentVariable("path");

Sure.  Here you go, if you're intent on busting out ...

- - - SetEnvironment.cs
using System;
using System.Runtime.InteropServices;    // P/Invoke
using System.Security.Permissions;        // Declarative Security (optional)

class EnvironTest
{
    [DllImport( "kernel32.dll", CharSet=CharSet.Auto, SetLastError=true)]
    [EnvironmentPermissionAttribute( SecurityAction.LinkDemand, Write="ABC")]
    public static extern bool SetEnvironmentVariable( string pszName, string pszValue);

    public static string GetEnvironmentVariable( string pszName)
    {
        return Environment.GetEnvironmentVariable( pszName);
    }

    public static void Main( string[] args)
    {
        string value;

        Console.Out.WriteLine( "Setting ABC environment variable ...");
        if ( !SetEnvironmentVariable( "ABC", "123") )
        {
            Console.Out.WriteLine( "SetEnvironmentVariable() call failed, error code={0:X}",
                Marshal.GetLastWin32Error());
            return;
        }

        Console.Out.WriteLine( "Getting ABC environment variable ...");
        value = GetEnvironmentVariable( "ABC");
        if ( value == null )
        {
            Console.Out.WriteLine( "GetEnvironmentVariable() call failed, ABC not found.");
            return;
        }
        Console.Out.WriteLine( "ABC={0}", value);

        Console.Out.WriteLine( "Deleting ABC environment variable ...");
        if ( !SetEnvironmentVariable( "ABC", null) )
        {
            Console.Out.WriteLine( "SetEnvironmentVariable() call failed, error code={0:X}",
                Marshal.GetLastWin32Error());
            return;
        }

        Console.Out.WriteLine( "Getting ABC environment variable ...");
        value = GetEnvironmentVariable( "ABC");
        if ( value != null )
        {
            Console.Out.WriteLine( "SetEnvironmentVariable() call failed, ABC still exists.");
            return;
        }
        Console.Out.WriteLine( "ABC successfully deleted.");

        return;
    }

Quote:
}

- - -

The line of interest is the 'external' declaration of the SetEnvironment-
Variable function.  You'll notice it's striking similarity to the C proto-
type from the Platform SDK.  First step in calling a native method is
just to use sensibly equivalent data types.  Then you can mark them
up with attributes, if necessary.

Now mark it up with DllImportAttribute ([DllImport] for short).  Most
important is the DLL that exports the function.  SetEnvironment-
Variable is a kernel32 function (if you're ever in doubt, you can
check the Platform SDK documentation, it's faster than dumping
the export tables of every DLL).

The defaults are satisfactory, except I chose:

CharSet.Auto -- you'll observe that the parameters are TSTR,
ie, Unicode on NT/2K and later systems, and ANSI on 9x/ME
systems.  CharSet.Auto tells the runtime to decide how to
marshal managed strings to C strings based on the execution
platform.  By setting this, incidentally, it's not necessary to
use MarshalAs attributes on the string parameters to tell
the marshaler that they should be TSTR.

SetLastError -- if the native function sets the error such that
you'd normally retrieve it using GetLastError( ) in the Win API,
and you might be interested in it, then set this DllImportAttribute
parameter to true.

You see in the test routine that I test for an error code using
the Framework method, Marshal.GetLastWin32Error( ).

At run-time, C# calls to EnvironTest::SetEnvironmentVariable( )
will be marshaled and forwarded to the corresponding Platform
SDK function.  This will change the environment of your host
process.

Quote:
> Any suggestions will be greatly appreciated :)

No problem.  Incidentally, I point out the recommended (although
optional) security attribute.  This checks that the immediate
calling method has permission to write to (in this case, the
specific environment variable the method is interested in) the
environment block.

If you're going to design a C# application around this, and you
grant it security privileges to execute Unmanaged Code, you
can elide some of the risk by carefully applying security
attributes.  Force the code to answer the question:

    "Exactly WHY do you want to execute Unmanaged Code?"

In this instance, if it's to set a specific user environment variable,
then perhaps it's okay.  This differentiates this piece of code,
from all other code that wants to execute Unmanaged Code,
"just because."  If you follow this guideline it's possible to
use P/Invoke methods as a profesional tool, and not as a
barbaric and blunt instrument.

Derek Harmon



Thu, 30 Dec 2004 06:05:26 GMT  
 Setting EnvironmentVariables



Quote:
> > Do you know whether it is possible to SET environmentvariables from
within a
> > C#-program?

> Of course.  It's not directly supported by the .NET Framework though,
you'd
> have to use P/Invoke to call unmanaged code (and therefore, require
security
> privileges to call unmanaged code).

In addition, this only changes the environment for your
process.

In Windows NT, all environment variables are actually
registry entries. The system initializes the process environment
block based on the registry, and also the environment block
of the process that creates the process.

Applications can choose to be aware of changes to environment
variables by paying attention to the WM_SETTINGCHANGE
message. When you make a change, your app should broadcast
this message to all top level windows.

Windows does not alter -any- applications environment block
after it starts; the application must check the registry
and alter it's own environment.

"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\
Session Manager\Environment"
"HKEY_CURRENT_USER\Environment"
"HKEY_CURRENT_USER\Volatile Environment"

see Knowledge Base's Q104011:
http://support.microsoft.com/support/kb/articles/q104/0/11.asp

Win 9x is even more fun; it stores the environment block
approximately the same as it did in DOS, with the added
benefit that the master environment block is in system
memory, which can't be changed without a reboot (in any
documented fashion).

Evan Smithgall posted some code to do this in 16-bit
C; I've never used it, so I can't say for sure that it works.
It's on my web site:

--
Ron Ruble

For additional programming info, go to my web site:
http://home.att.net/~raffles1/

Please direct additional questions to the newsgroup,
rather than email, so others may benefit from the
discussion.



Fri, 31 Dec 2004 02:39:05 GMT  
 Setting EnvironmentVariables
Thanks alot - that was very usefull and I can as of now set the variables :)
As usual answers gives rise to new questions:

- Do you know how to convert the WM_SETTINGCHANGE into C# syntax so that I
want have to reboot in order to see the changes in effect ?

I believe it has something to do with :
Message.Create(HWND_BROADCAST, WM_SETTINGCHANGE, 0,(LPARAM) "Environment",
.......[ ] );

...but Im not sure!

Thanks a lot again !

Jesper Linvald


Quote:





> > > Do you know whether it is possible to SET environmentvariables from
> within a
> > > C#-program?

> > Of course.  It's not directly supported by the .NET Framework though,
> you'd
> > have to use P/Invoke to call unmanaged code (and therefore, require
> security
> > privileges to call unmanaged code).

> In addition, this only changes the environment for your
> process.

> In Windows NT, all environment variables are actually
> registry entries. The system initializes the process environment
> block based on the registry, and also the environment block
> of the process that creates the process.

> Applications can choose to be aware of changes to environment
> variables by paying attention to the WM_SETTINGCHANGE
> message. When you make a change, your app should broadcast
> this message to all top level windows.

> Windows does not alter -any- applications environment block
> after it starts; the application must check the registry
> and alter it's own environment.

> "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\
> Session Manager\Environment"
> "HKEY_CURRENT_USER\Environment"
> "HKEY_CURRENT_USER\Volatile Environment"

> see Knowledge Base's Q104011:
> http://support.microsoft.com/support/kb/articles/q104/0/11.asp

> Win 9x is even more fun; it stores the environment block
> approximately the same as it did in DOS, with the added
> benefit that the master environment block is in system
> memory, which can't be changed without a reboot (in any
> documented fashion).

> Evan Smithgall posted some code to do this in 16-bit
> C; I've never used it, so I can't say for sure that it works.
> It's on my web site:

> --
> Ron Ruble

> For additional programming info, go to my web site:
> http://home.att.net/~raffles1/

> Please direct additional questions to the newsgroup,
> rather than email, so others may benefit from the
> discussion.



Fri, 31 Dec 2004 08:17:38 GMT  
 
 [ 6 post ] 

 Relevant Pages 

1. Settings|System (tab)|Regional Settings | Region setting other than English (US) causes problem in VarBstrFromDate

2. Program to set up internet settings

3. VC++ project setting -> settings for

4. color setting and font settings

5. Problem setting Additional Include Directories (in Project Settings)

6. writing project settings and directory settings to file

7. Set proxy settings per IWebBrowser2

8. Set color of pen independant of setting style

9. Project Settings->OLE Types, Setting Project Options problem

10. Setting / getting list separator (Regional Setting Properties)???

11. a new project setting set

12. --How to set a exe file in Debug Tab of Project setting--

 

 
Powered by phpBB® Forum Software