如何以跨平台方式设置环境变量?

时间:2012-02-14 10:13:42

标签: haskell cross-platform environment-variables

我可以使用System.Environment.getEnv轻松读取环境变量。但是,System.Environment没有任何相应的setEnv函数(据我所知)。

如何从Haskell程序设置环境变量?我更喜欢跨平台的解决方案。 (所以只执行export VAR=val或使用System.Posix.Env并不是我想要的。)

3 个答案:

答案 0 :(得分:3)

在POSIX平台上,您可以使用System.Posix.Env,它具有putEnv功能。这比运行export更便携,但遗憾的是不是真正的跨平台。

答案 1 :(得分:3)

请注意,基础4.7.0现在setEnv中有System.Environment。所以对于现在或将来它已经整理出来了。

但是,如果您在版本< 4.7.0(我目前的情况下)中需要此功能,我还从the commit that adds the feature中提取了使用较旧的基本版本进行此操作所需的功能。

然而,我严重失去了对这一点的耐心,并且做得相当难看,但它对我有用......

混乱是在Windows环境中有3个函数要调用:putenvSetEnvironmentVariableA(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仅适用于Windows。正如您所看到的,我有widechar调用的代码,但我目前对其进行了评论。我认为对于我的用例来说,调用putenv可能就足够了,但它确实可以正常工作。那么我的话就是这样:

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

我的问题是我主要是家里的Linux用户而且我不喜欢在家里做太多的工作,我把很多的精力放到了让这个和其他东西在Windows上正常工作,我无法让自己进一步清理它。但是使用这段代码和原始补丁你应该让它在基础&lt; 4.7上工作而没有太多问题。

答案 2 :(得分:2)

提示跨平台不可能是Java API没有putenv。 另请参阅此related post

最常见用例的解决方案是在exec个程序时传递适当构造的环境。