diff --git a/silently.cabal b/silently.cabal
--- a/silently.cabal
+++ b/silently.cabal
@@ -1,6 +1,6 @@
 name: silently
-version: 1.1.5
-cabal-version: >= 1.2
+version: 1.2
+cabal-version: >= 1.8
 build-type: Simple
 license: BSD3
 license-file: LICENSE
@@ -15,22 +15,24 @@
 category:
 author: Trystan Spangler
 tested-with: GHC ==7.0
-extra-source-files:
-  src/windows/System/IO/Silently.hs
-  src/unix/System/IO/Silently.hs
-  src/other/System/IO/Silently.hs
 
+source-repository head
+  type: git
+  location: https://github.com/trystan/silently
+
 Library
-  build-depends: base >=4 && <=5, directory -any
+  build-depends:
+      base >=4 && <=5
+    , directory
+    , deepseq
   exposed-modules: System.IO.Silently
   exposed: True
   buildable: True
 
-  if os(windows)
-    hs-source-dirs: src/windows
-  else
-    if os(linux) || os(osx) || os(freebsd) || os(openbsd) || os(netbsd)
-      hs-source-dirs: src/unix
-    else
-      hs-source-dirs: src/other
+  hs-source-dirs:
+      src
 
+  if os(windows)
+    cpp-options: -DWINDOWS
+  if os(linux) || os(osx) || os(freebsd) || os(openbsd) || os(netbsd)
+    cpp-options: -DUNIX
diff --git a/src/System/IO/Silently.hs b/src/System/IO/Silently.hs
new file mode 100644
--- /dev/null
+++ b/src/System/IO/Silently.hs
@@ -0,0 +1,88 @@
+{-# LANGUAGE CPP #-}
+-- | Need to prevent output to the terminal, a file, or stderr? Need to capture it and use it for
+-- your own means? Now you can, with 'silence' and 'capture'.
+
+module System.IO.Silently (
+  silence, hSilence,
+  capture, hCapture
+) where
+
+import GHC.IO.Handle (hDuplicate, hDuplicateTo)
+import System.IO
+import System.IO.Error
+import Control.Exception (bracket)
+import Control.DeepSeq
+import System.Directory (removeFile,getTemporaryDirectory)
+
+mNullDevice :: Maybe FilePath
+#ifdef WINDOWS
+mNullDevice = Just "NUL"
+#elif UNIX
+mNullDevice = Just "/dev/null"
+#else
+mNullDevice = Nothing
+#endif
+
+-- | Run an IO action while preventing all output to stdout.
+silence :: IO a -> IO a
+silence = hSilence [stdout]
+
+-- | Run an IO action while preventing all output to the given handles.
+hSilence :: [Handle] -> IO a -> IO a
+hSilence handles action = case mNullDevice of
+  Just nullDevice -> bracket (openFile nullDevice AppendMode)
+                             hClose
+                             prepareAndRun
+
+  Nothing -> do
+    tmpDir <- getTempOrCurrentDirectory
+    bracket (openTempFile tmpDir "silence")
+                               cleanup
+                               (prepareAndRun . snd)
+
+ where
+  cleanup (tmpFile,tmpHandle) = do
+    hClose tmpHandle
+    removeFile tmpFile
+  prepareAndRun tmpHandle = go handles
+    where
+      go [] = action
+      go hs = goBracket go tmpHandle hs
+
+
+getTempOrCurrentDirectory :: IO String
+getTempOrCurrentDirectory = getTemporaryDirectory `catchIOError` (\_ -> return ".")
+
+-- | Run an IO action while preventing and capturing all output to stdout.
+-- This will, as a side effect, create and delete a temp file in the temp directory or current directory if there is no temp directory.
+capture :: IO a -> IO (String, a)
+capture = hCapture [stdout]
+
+-- | Run an IO action while preventing and capturing all output to the given handles.
+-- This will, as a side effect, create and delete a temp file in the temp directory or current directory if there is no temp directory.
+hCapture :: [Handle] -> IO a -> IO (String, a)
+hCapture handles action = do
+  tmpDir <- getTempOrCurrentDirectory
+  bracket (openTempFile tmpDir "capture")
+                             cleanup
+                             (prepareAndRun . snd)
+ where
+  cleanup (tmpFile,tmpHandle) = do
+    hClose tmpHandle
+    removeFile tmpFile
+  prepareAndRun tmpHandle = go handles
+    where
+      go [] = do
+              a <- action
+              mapM_ hFlush handles
+              hSeek tmpHandle AbsoluteSeek 0
+              str <- hGetContents tmpHandle
+              str `deepseq` return (str,a)
+      go hs = goBracket go tmpHandle hs
+
+goBracket :: ([Handle] -> IO a) -> Handle -> [Handle] -> IO a
+goBracket go tmpHandle (h:hs) = bracket (do old <- hDuplicate h
+                                            hDuplicateTo tmpHandle h
+                                            return old)
+                                        (\old -> hDuplicateTo old h >> hClose old)
+                                        (\_   -> go hs)
diff --git a/src/other/System/IO/Silently.hs b/src/other/System/IO/Silently.hs
deleted file mode 100644
--- a/src/other/System/IO/Silently.hs
+++ /dev/null
@@ -1,76 +0,0 @@
-
--- | Need to prevent output to the terminal, a file, or stderr? Need to capture it and use it for
--- your own means? Now you can, with 'silence' and 'capture'.
-
-module System.IO.Silently (
-  silence, hSilence,
-  capture, hCapture
-) where
-
-import GHC.IO.Handle (hDuplicate, hDuplicateTo)
-import System.IO (Handle, stdout, hClose, openTempFile)
-import Control.Exception (bracket)
-import System.Directory (removeFile,getTemporaryDirectory)
-
--- | Run an IO action while preventing all output to stdout.
--- This will, as a side effect, create and delete a temp file in the current directory.
-silence :: IO a -> IO a
-silence = hSilence [stdout]
-
--- | Run an IO action while preventing all output to the given handles.
--- This will, as a side effect, create and delete a temp file in the current directory.
-hSilence :: [Handle] -> IO a -> IO a
-hSilence handles action = do
-  tmpDir <- getTempOrCurrentDirectory
-  bracket (openTempFile tmpDir "silence")
-                             cleanup
-                             prepareAndRun
- where
-  cleanup (tmpFile,tmpHandle) = do
-    hClose tmpHandle
-    removeFile tmpFile
-  prepareAndRun (_,tmpHandle) = go handles
-    where
-      go []     = action
-      go hs = goBracket go tmpHandle hs
-
-
-getTempOrCurrentDirectory :: IO String
-getTempOrCurrentDirectory = getTemporaryDirectory `Prelude.catch` (\ex -> return ".")
-
--- | Run an IO action while preventing and capturing all output to stdout.
--- This will, as a side effect, create and delete a temp file in the temp directory or current directory if there is no temp directory.
-capture :: IO a -> IO (String, a)
-capture = hCapture [stdout]
-
--- | Run an IO action while preventing and capturing all output to the given handles.
--- This will, as a side effect, create and delete a temp file in the temp directory or current directory if there is no temp directory.
-hCapture :: [Handle] -> IO a -> IO (String, a)
-hCapture handles action = do
-  tmpDir <- getTempOrCurrentDirectory
-  bracket (openTempFile tmpDir "capture")
-                             cleanup
-                             prepareAndRun
- where
-  cleanup (tmpFile,tmpHandle) = do
-    hClose tmpHandle
-    removeFile tmpFile
-  prepareAndRun (tmpFile,tmpHandle) = go handles
-    where
-      go [] = do
-              a <- action
-              hClose tmpHandle
-              str <- readFile tmpFile
-              forceList str
-              return (str,a)
-      go hs = goBracket go tmpHandle hs
-
-forceList [] = return ()
-forceList (x:xs) = forceList xs
-
-goBracket :: ([Handle] -> IO a) -> Handle -> [Handle] -> IO a
-goBracket go tmpHandle (h:hs) = bracket (do old <- hDuplicate h
-                                            hDuplicateTo tmpHandle h
-                                            return old)
-                                        (\old -> hDuplicateTo old h >> hClose old)
-                                        (\_   -> go hs)
diff --git a/src/unix/System/IO/Silently.hs b/src/unix/System/IO/Silently.hs
deleted file mode 100644
--- a/src/unix/System/IO/Silently.hs
+++ /dev/null
@@ -1,65 +0,0 @@
-
--- | Need to prevent output to the terminal, a file, or stderr? Need to capture it and use it for
--- your own means? Now you can, with 'silence' and 'capture'.
-
-module System.IO.Silently (
-  silence, hSilence,
-  capture, hCapture
-) where
-
-import GHC.IO.Handle (hDuplicate, hDuplicateTo)
-import System.IO (Handle, stdout, hClose, openTempFile, openFile, IOMode(..))
-import Control.Exception (bracket)
-import System.Directory (removeFile,getTemporaryDirectory)
-
--- | Run an IO action while preventing all output to stdout.
-silence :: IO a -> IO a
-silence = hSilence [stdout]
-
--- | Run an IO action while preventing all output to the given handles.
-hSilence :: [Handle] -> IO a -> IO a
-hSilence handles action = bracket (openFile "/dev/null" AppendMode)
-                             hClose
-                             prepareAndRun
- where
-  prepareAndRun tmpHandle = go handles
-    where
-      go [] = action
-      go hs = goBracket go tmpHandle hs
-
-
-getTempOrCurrentDirectory :: IO String
-getTempOrCurrentDirectory = getTemporaryDirectory `Prelude.catch` (\ex -> return ".")
-
--- | Run an IO action while preventing and capturing all output to stdout.
--- This will, as a side effect, create and delete a temp file in the temp directory or current directory if there is no temp directory.
-capture :: IO a -> IO (String, a)
-capture = hCapture [stdout]
-
--- | Run an IO action while preventing and capturing all output to the given handles.
--- This will, as a side effect, create and delete a temp file in the temp directory or current directory if there is no temp directory.
-hCapture :: [Handle] -> IO a -> IO (String, a)
-hCapture handles action = do
-  tmpDir <- getTempOrCurrentDirectory
-  bracket (openTempFile tmpDir "capture")
-                             cleanup
-                             prepareAndRun
- where
-  cleanup (tmpFile,tmpHandle) = do
-    hClose tmpHandle
-    removeFile tmpFile
-  prepareAndRun (tmpFile,tmpHandle) = go handles
-    where
-      go [] = do
-              a <- action
-              hClose tmpHandle
-              str <- readFile tmpFile
-              return (str,a)
-      go hs = goBracket go tmpHandle hs
-
-goBracket :: ([Handle] -> IO a) -> Handle -> [Handle] -> IO a
-goBracket go tmpHandle (h:hs) = bracket (do old <- hDuplicate h
-                                            hDuplicateTo tmpHandle h
-                                            return old)
-                                        (\old -> hDuplicateTo old h >> hClose old)
-                                        (\_   -> go hs)
diff --git a/src/windows/System/IO/Silently.hs b/src/windows/System/IO/Silently.hs
deleted file mode 100644
--- a/src/windows/System/IO/Silently.hs
+++ /dev/null
@@ -1,69 +0,0 @@
-
--- | Need to prevent output to the terminal, a file, or stderr? Need to capture it and use it for
--- your own means? Now you can, with 'silence' and 'capture'.
-
-module System.IO.Silently (
-  silence, hSilence,
-  capture, hCapture
-) where
-
-import GHC.IO.Handle (hDuplicate, hDuplicateTo)
-import System.IO (Handle, stdout, hClose, openTempFile, openFile, IOMode(..))
-import Control.Exception (bracket)
-import System.Directory (removeFile,getTemporaryDirectory)
-
--- | Run an IO action while preventing all output to stdout.
-silence :: IO a -> IO a
-silence = hSilence [stdout]
-
--- | Run an IO action while preventing all output to the given handles.
-hSilence :: [Handle] -> IO a -> IO a
-hSilence handles action = bracket (openFile "NUL" AppendMode)
-                             hClose
-                             prepareAndRun
- where
-  prepareAndRun tmpHandle = go handles
-    where
-      go [] = action
-      go hs = goBracket go tmpHandle hs
-
-
-getTempOrCurrentDirectory :: IO String
-getTempOrCurrentDirectory = getTemporaryDirectory `Prelude.catch` (\ex -> return ".")
-
--- | Run an IO action while preventing and capturing all output to stdout.
--- This will, as a side effect, create and delete a temp file in the temp directory or current directory if there is no temp directory.
-capture :: IO a -> IO (String, a)
-capture = hCapture [stdout]
-
--- | Run an IO action while preventing and capturing all output to the given handles.
--- This will, as a side effect, create and delete a temp file in the temp directory or current directory if there is no temp directory.
-hCapture :: [Handle] -> IO a -> IO (String, a)
-hCapture handles action = do
-  tmpDir <- getTempOrCurrentDirectory
-  bracket (openTempFile tmpDir "capture")
-                             cleanup
-                             prepareAndRun
- where
-  cleanup (tmpFile,tmpHandle) = do
-    hClose tmpHandle
-    removeFile tmpFile
-  prepareAndRun (tmpFile,tmpHandle) = go handles
-    where
-      go [] = do
-              a <- action
-              hClose tmpHandle
-              str <- readFile tmpFile
-              forceList str
-              return (str,a)
-      go hs = goBracket go tmpHandle hs
-
-forceList [] = return ()
-forceList (x:xs) = forceList xs
-
-goBracket :: ([Handle] -> IO a) -> Handle -> [Handle] -> IO a
-goBracket go tmpHandle (h:hs) = bracket (do old <- hDuplicate h
-                                            hDuplicateTo tmpHandle h
-                                            return old)
-                                        (\old -> hDuplicateTo old h >> hClose old)
-                                        (\_   -> go hs)
diff --git a/test/Spec.hs b/test/Spec.hs
new file mode 100644
--- /dev/null
+++ b/test/Spec.hs
@@ -0,0 +1,29 @@
+module Main (main) where
+
+import           Test.Hspec.ShouldBe
+
+import           System.IO
+import           System.IO.Silently
+import           System.Directory
+
+import           Control.Exception
+
+main :: IO ()
+main = hspec spec
+
+spec :: Spec
+spec = do
+
+  describe "hSilence" $ do
+    it "prevents output to a given handle" $ let file = "test/foo.txt" in do
+      h <- openFile file ReadWriteMode
+      hSilence [h] $ do
+        hPutStrLn h "foo bar baz"
+        hFlush h
+      hSeek h AbsoluteSeek 0
+      hGetContents h `shouldReturn` ""
+      `finally` removeFile file
+
+  describe "capture" $ do
+    it "captures stdout" $ do
+      capture (putStr "foo" >> return 23) `shouldReturn` ("foo", 23 :: Int)
