Как я могу установить переменную среды кросс-платформенным способом? - PullRequest
9 голосов
/ 14 февраля 2012

Я легко могу прочитать переменную окружения, используя System.Environment.getEnv.Однако System.Environment не имеет соответствующей функции setEnv (насколько я могу судить).

Как установить переменную окружения из программы на Haskell?Я бы предпочел кроссплатформенное решение.(То есть просто выполнение export VAR=val или использование System.Posix.Env не совсем то, что я ищу.)

Ответы [ 3 ]

3 голосов
/ 29 июня 2014

Обратите внимание, что база 4.7.0 теперь имеет setEnv в System.Environment.Таким образом, в настоящее время или в ближайшем будущем он будет рассортирован.

Однако, если вам нужна эта функция в версиях <4.7.0 (что в моем случае в настоящее время), я также извлек из <a href="https://ghc.haskell.org/trac/ghc/attachment/ticket/7427/0001-Add-setEnv-unsetEnv-to-System.Environment.patch" rel="nofollow"> коммит, который добавляет функции, необходимые для работы с более старой базовой версией.

Однако я серьезно потерял терпение и сделал это довольно уродливо, но у меня это работает ...

Беспорядок в том, что в среде Windows есть 3 функции для вызова: putenv, SetEnvironmentVariableA (ASCII) и SetEnvironmentVariableW (widechar, utf16).Патч, который был добавлен в базу 4.7, делает это автоматически, но я сделал что-то более уродливое из-за нехватки времени (возможно, я все еще его очищаю).

Вот что у меня есть:

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 

Очевидно, используйте CPP, чтобы поместить все это в #ifdef только для окон.Как вы видите, у меня есть код для звонка на широкую чарта, но я прокомментировал его в настоящее время.Я думаю, что для моего варианта использования было бы достаточно просто позвонить putenv, но все работает как есть.Тогда вот как я это называю:

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

Моя проблема в том, что я в основном пользователь linux дома, и мне не нравится делать слишком много работы с Windows дома, и я ставлю много энергии, чтобы заставить это и другие вещи работать должным образом на окнах, и я не могу заставить себя убрать это дальше.Но с этим кодом и оригинальным патчем вы должны заставить его работать на базе <4.7 без особых проблем. </p>

3 голосов
/ 14 февраля 2012

На платформах POSIX вы можете использовать System.Posix.Env, который имеет функцию putEnv. Это более переносимо, чем запуск export, хотя, к сожалению, не является кроссплатформенным.

2 голосов
/ 15 февраля 2012

Намек на то, что это не возможно для кроссплатформенности, заключается в том, что Java API не имеет putenv. Смотрите также этот связанный пост .

Решением для наиболее частого варианта использования является прохождение надлежащим образом сконструированной среды при exec -ing программах.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...