Skip to content

Instantly share code, notes, and snippets.

@strager
Last active December 15, 2015 18:49
Show Gist options
  • Save strager/5306598 to your computer and use it in GitHub Desktop.
Save strager/5306598 to your computer and use it in GitHub Desktop.
-- ghc -Wall -Werror -O2 test_java.hs -o test_java.exe && strip test_java.exe
import Control.Applicative
import Control.Monad (guard)
import Data.Bits
import Data.List (nub)
import Data.Maybe (catMaybes)
import System.Exit
import System.FilePath
import System.IO
import System.IO.Error
import System.Process
import qualified Control.Exception as Ex
import qualified GHC.IO.Exception
import qualified System.Win32.Registry as Reg
import qualified System.Win32.Types as Reg (HKEY)
tryThis :: String -> IO () -> IO ()
tryThis message m = do
putStrLn $ "Trying " ++ message ++ "..."
(m >> putStrLn "OK") `Ex.catch` onException
putStrLn ""
where
onException :: Ex.SomeException -> IO ()
onException e = putStrLn $ "Failed: " ++ show e
hPipe :: Handle -> Handle -> IO ()
hPipe inp out = hGetContents inp >>= hPutStr out
checkExitCode :: ExitCode -> IO ()
checkExitCode ExitSuccess = return ()
checkExitCode exitCode@(ExitFailure _) = Ex.throw exitCode
dealWithHandles :: (Handle, Handle, Handle, ProcessHandle) -> IO ()
dealWithHandles (inp, out, err, pid) = do
hClose inp
hPipe out stdout
hPipe err stdout
checkExitCode =<< waitForProcess pid
registryLocations :: [String]
registryLocations =
[ "SOFTWARE\\JavaSoft\\Java Runtime Environment"
, "SOFTWARE\\Wow6432Node\\JavaSoft\\Java Runtime Environment"
]
findJRERootKeysWithRegsam :: Reg.REGSAM -> IO [Reg.HKEY]
findJRERootKeysWithRegsam regsam
= fmap catMaybes . flip mapM registryLocations $ \ loc -> ignoreKeyNotFound
$ Just <$> Reg.regOpenKeyEx Reg.hKEY_LOCAL_MACHINE loc (regsam .|. Reg.kEY_READ)
-- We look in all the registries we can find: current, 32-bit, 64-bit.
findJRERootKeys :: IO [(Reg.HKEY, Reg.REGSAM)]
findJRERootKeys
= concat <$> mapM findWithRegsam regsams
where
regsams = [0, kEY_WOW64_64KEY, kEY_WOW64_32KEY]
kEY_WOW64_64KEY = 0x0100
kEY_WOW64_32KEY = 0x0200
findWithRegsam regsam = do
keys <- findJRERootKeysWithRegsam regsam
return $ map (\ key -> (key, regsam)) keys
findJREInstallation :: Reg.HKEY -> Reg.REGSAM -> IO (Maybe FilePath)
findJREInstallation root regsamAdd = do
currentVersion <- Reg.regQueryValue root (Just "CurrentVersion")
key <- Reg.regOpenKeyEx root currentVersion regsam
fmap Just $ Reg.regQueryValue key (Just "JavaHome")
where regsam = Reg.kEY_READ .|. regsamAdd
ignoreKeyNotFound :: (Alternative f) => IO (f a) -> IO (f a)
ignoreKeyNotFound = Ex.handleJust
(guard . isKeyNotFound)
(const $ return empty)
where
isKeyNotFound err
= ioeGetErrorType err == GHC.IO.Exception.InvalidArgument
findJREInstallations :: IO [FilePath]
findJREInstallations = fmap (nub . catMaybes)
$ mapM (uncurry findJREInstallation) =<< findJRERootKeys
getJVMPath :: IO FilePath
getJVMPath = do
installations <- findJREInstallations
case installations of
-- TODO Find first existing.
(x:_) -> return (x </> "bin" </> "java.exe")
[] -> fail "No JRE installation found"
main :: IO ()
main = do
java <- getJVMPath
tryThis "runInteractiveProcess java -version" $ do
dealWithHandles =<< runInteractiveProcess
"java" ["-version"] Nothing Nothing
tryThis "runInteractiveProcess java.exe -version" $ do
dealWithHandles =<< runInteractiveProcess
"java.exe" ["-version"] Nothing Nothing
tryThis ("runInteractiveProcess " ++ java ++ " -version") $ do
dealWithHandles =<< runInteractiveProcess
java ["-version"] Nothing Nothing
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment