要以有用的格式从注册表中读取值,需要在haskell和c类型之间转换相当多的代码。所讨论的值通常是
REG_EXPAND_SZ
也没用。所以不漂亮,但这对我很有用:
{-# LANGUAGE ForeignFunctionInterface #-}
import System.Win32.Types
import System.Win32.Registry
import Foreign.Ptr (castPtr)
import Foreign.Marshal.Alloc (allocaBytes)
import Foreign.C.String (peekCWString, withCWString)
import Control.Exception (bracket, throwIO)
-- // parse a string from a registry value of certain type
parseRegString :: RegValueType -> LPBYTE -> IO String
parseRegString ty mem
| ty == rEG_SZ = peekCWString (castPtr mem)
| ty == rEG_EXPAND_SZ = peekCWString (castPtr mem) >>=
expandEnvironmentStrings
| otherwise = ioError (userError "Invalid registry value type")
-- // FFI import of the ExpandEnvironmentStrings function needed
-- // to make use of the registry values
expandEnvironmentStrings :: String -> IO String
expandEnvironmentStrings toexpand =
withCWString toexpand $ \input ->
allocaBytes 512 $ \output ->
do c_ExpandEnvironmentStrings input output 256
peekCWString output
foreign import stdcall unsafe "windows.h ExpandEnvironmentStringsW"
c_ExpandEnvironmentStrings :: LPCTSTR -> LPTSTR -> DWORD -> IO DWORD
-- // open the registry key
userShellFolders :: IO HKEY
userShellFolders = regOpenKeyEx hKEY_CURRENT_USER
"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders"
kEY_QUERY_VALUE
-- // read the actual value
localAppData :: IO String
localAppData =
bracket userShellFolders regCloseKey $ \usfkey ->
allocaBytes 512 $ \mem ->
do ty <- regQueryValueEx usfkey "Local AppData" mem 512
parseRegString ty mem
main = localAppData >>= print
我不确定是否正确地处理了所有的错误情况(例如,如果传递的缓冲区太小),因此您可能需要检查Windows文档,以了解在这些情况下会发生什么。