2012-02-14 13 views
9

Puedo leer fácilmente una variable de entorno usando System.Environment.getEnv. Sin embargo, System.Environment no tiene ninguna función setEnv correspondiente (por lo que pude ver).¿Cómo puedo establecer una variable de entorno de forma multiplataforma?

¿Cómo configuro una variable de entorno de un programa Haskell? Yo preferiría una solución multiplataforma. (Por lo que sólo la ejecución de export VAR=val o el uso de System.Posix.Env no es exactamente lo que estoy buscando.)

+1

Tenga en cuenta que la base 4.7.0 ahora tiene un 'setEnv'. –

+0

@EmmanuelTouzery: Impresionante. ¿Podrías poner eso como una respuesta para una mayor visibilidad? Gracias. –

Respuesta

3

Tenga en cuenta que la base 4.7.0 ahora tiene un setEnv en System.Environment. Entonces, para el presente o el futuro cercano está resuelto.

Sin embargo, si necesita esta característica en las versiones < 4.7.0 (que es mi caso actualmente), también he extraído de the commit that adds the feature las funciones necesarias para que esto funcione con una versión base anterior.

Sin embargo seriamente perdido la paciencia en este caso y lo hizo bastante feo, pero funciona para mí ...

El lío es que hay 3 funciones para llamar en un entorno Windows: putenv, SetEnvironmentVariableA (ASCII) y SetEnvironmentVariableW (widechar, utf16). El parche que se comprometió con la base 4.7 lo hace automáticamente, pero hice algo más feo por falta de tiempo (aún puedo limpiarlo).

Esto es lo que tengo:

setEnv_ :: String -> String -> IO() 
setEnv_ key value = withCString key $ \k -> withCString value $ \v -> do 
    success <- c_SetEnvironmentVariable k v 
    unless success (throwGetLastError "setEnv") 

putEnv :: String -> IO() 
putEnv v = void (withCString v $ \vv -> c_putenv vv) 

foreign import stdcall unsafe "windows.h SetEnvironmentVariableA" 
    c_SetEnvironmentVariable :: CString -> CString -> IO Bool 

-- SetEnv_ :: String -> String -> IO() 
-- SetEnv_ key value = withCWString key $ \k -> withCWString value $ \v -> do 
-- success <- c_SetEnvironmentVariable k v 
-- unless success (throwGetLastError "setEnv") 
-- 
-- Foreign import stdcall unsafe "windows.h SetEnvironmentVariableW" 
-- c_SetEnvironmentVariable :: LPTSTR -> LPTSTR -> IO Bool 

foreign import ccall unsafe "putenv" c_putenv :: CString -> IO CInt 

usar Obviamente CPP a poner todo en un solo #ifdef para ventanas. Como pueden ver, tengo el código para la llamada Widechar, pero lo comenté actualmente. Creo que para mi caso de uso probablemente sea suficiente llamar al putenv pero funciona como es. Así que aquí es como yo llamo a continuación:

setEnv_ "LANG" localeStr 
putEnv $ "LANG=" ++ localeStr 

Mi problema es que soy principalmente un usuario de Linux en casa y no me gusta hacer demasiado trabajo en las ventanas en el hogar, y puse mucho de energía para hacer que esto y otras cosas funcionen correctamente en Windows, y no puedo arreglar esto más adelante. Pero con este código y el parche original debe hacer que funcione en la base < 4.7 sin muchos problemas.

3

En las plataformas POSIX que puede utilizar System.Posix.Env, que tiene una función putEnv. Eso es más portátil que ejecutar export, aunque desafortunadamente no es verdaderamente multiplataforma.

+1

Gracias por la respuesta. De hecho, vi ese módulo después de publicar la pregunta, pero realmente me gustaría algo que funcione en Windows. –

3

Una sugerencia de que esto no es posible multiplataforma es que la API de Java no tiene un putenv. Vea también este related post.

La solución para el caso de uso más frecuente es pasar un entorno construido adecuadamente cuando exec -ing programas.

Cuestiones relacionadas