diff --git a/CHANGES.txt b/CHANGES.txt
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,5 +1,9 @@
 Changelog for NSIS
 
+0.3.4, released 2026-01-18
+    #17. add support for Target
+    #16, add support for WriteRegMultiStr
+    #15, add support for ExecShellWait
 0.3.3, released 2019-05-15
     Add Welcome page
 0.3.2, released 2017-11-24
diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright Neil Mitchell 2012-2019.
+Copyright Neil Mitchell 2012-2026.
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# NSIS Manual [![Hackage version](https://img.shields.io/hackage/v/nsis.svg?label=Hackage)](https://hackage.haskell.org/package/nsis) [![Stackage version](https://www.stackage.org/package/nsis/badge/nightly?label=Stackage)](https://www.stackage.org/package/nsis) [![Build status](https://img.shields.io/travis/ndmitchell/nsis/master.svg?label=Build)](https://travis-ci.org/ndmitchell/nsis)
+# NSIS Manual [![Hackage version](https://img.shields.io/hackage/v/nsis.svg?label=Hackage)](https://hackage.haskell.org/package/nsis) [![Stackage version](https://www.stackage.org/package/nsis/badge/nightly?label=Stackage)](https://www.stackage.org/package/nsis) [![Build status](https://img.shields.io/github/actions/workflow/status/ndmitchell/nsis/ci.yml?branch=master)](https://github.com/ndmitchell/nsis/actions)
 
 This library makes it easier to write [NSIS Windows Installers](https://nsis.sourceforge.net/). You should use this library if:
 
diff --git a/nsis.cabal b/nsis.cabal
--- a/nsis.cabal
+++ b/nsis.cabal
@@ -1,15 +1,15 @@
-cabal-version:      >= 1.18
+cabal-version:      1.18
 build-type:         Simple
 name:               nsis
-version:            0.3.3
+version:            0.3.4
 license:            BSD3
 license-file:       LICENSE
 category:           Development
 author:             Neil Mitchell <ndmitchell@gmail.com>
 maintainer:         Neil Mitchell <ndmitchell@gmail.com>
-copyright:          Neil Mitchell 2012-2019
+copyright:          Neil Mitchell 2012-2026
 synopsis:           DSL for producing Windows Installer using NSIS.
-tested-with:        GHC==8.6.5, GHC==8.4.4, GHC==8.2.2, GHC==8.0.2, GHC==7.10.3
+tested-with:        GHC==9.6, GHC==9.4, GHC==9.2, GHC==9.0, GHC==8.10, GHC==8.8
 description:
     NSIS (Nullsoft Scriptable Install System, <http://nsis.sourceforge.net/>) is a tool that allows programmers
     to create installers for Windows.
@@ -32,6 +32,7 @@
     hs-source-dirs: src
     build-depends:
         base == 4.*,
+        extra,
         transformers >= 0.2,
         uniplate >= 1.5
 
diff --git a/src/Development/NSIS.hs b/src/Development/NSIS.hs
--- a/src/Development/NSIS.hs
+++ b/src/Development/NSIS.hs
@@ -54,11 +54,11 @@
     getFileTime, fileExists, findEach,
     createDirectory, createShortcut,
     -- ** Registry manipulation
-    readRegStr, deleteRegKey, deleteRegValue, writeRegStr, writeRegExpandStr, writeRegDWORD,
+    readRegStr, deleteRegKey, deleteRegValue, writeRegStr, writeRegExpandStr, writeRegDWORD, writeRegMultiStr,
     -- ** Environment variables
     envVar,
     -- ** Process execution
-    exec, execWait, execShell, sleep, abort,
+    exec, execWait, execShell, execShellWait, sleep, abort,
     -- ** Windows
     HWND, hwndParent, findWindow, getDlgItem, sendMessage,
     -- ** Plugins
@@ -70,7 +70,7 @@
     installIcon, uninstallIcon, headerImage,
     installDirRegKey, allowRootDirInstall, caption,
     showInstDetails, showUninstDetails, unicode,
-    requestExecutionLevel,
+    requestExecutionLevel, target,
     -- ** Sections
     SectionId, section, sectionGroup, newSectionId,
     sectionSetText, sectionGetText, sectionSet, sectionGet,
@@ -84,7 +84,7 @@
     -- * Escape hatch
     unsafeInject, unsafeInjectGlobal,
     -- * Settings
-    Compressor(..), HKEY(..), MessageBoxType(..), Attrib(..), Page(..), Level(..), Visibility(..),
+    Compressor(..), HKEY(..), MessageBoxType(..), Attrib(..), Page(..), Level(..), Target(..), Visibility(..),
     FileMode(..), SectionFlag(..), ShowWindow(..), FinishOptions(..), DetailsPrint(..)
     ) where
 
diff --git a/src/Development/NSIS/Optimise.hs b/src/Development/NSIS/Optimise.hs
--- a/src/Development/NSIS/Optimise.hs
+++ b/src/Development/NSIS/Optimise.hs
@@ -37,7 +37,7 @@
         f [] = []
 
 
--- Label whose next statement is a good, 
+-- Label whose next statement is a good,
 elimLabeledGoto :: [NSIS] -> [NSIS]
 elimLabeledGoto x = transformBi f x
     where
diff --git a/src/Development/NSIS/Plugins/Sections.hs b/src/Development/NSIS/Plugins/Sections.hs
--- a/src/Development/NSIS/Plugins/Sections.hs
+++ b/src/Development/NSIS/Plugins/Sections.hs
@@ -44,4 +44,3 @@
 
     ensure
     onSelChange ensure
-
diff --git a/src/Development/NSIS/Show.hs b/src/Development/NSIS/Show.hs
--- a/src/Development/NSIS/Show.hs
+++ b/src/Development/NSIS/Show.hs
@@ -7,14 +7,14 @@
 import Data.Generics.Uniplate.Data
 import Data.Char
 import Data.Function
-import Data.List
+import Data.List.Extra
 import Data.Maybe
 
 
 showNSIS :: [NSIS] -> [String]
 showNSIS xs =
     ["!Include MUI2.nsh"] ++
-    ["Var _" ++ show v | v <- sort $ nub [i | Var i <- universeBi xs]] ++
+    ["Var _" ++ show v | v <- nubSort [i | Var i <- universeBi xs]] ++
     outs fs (filter isGlobal xs) ++
     ["!insertmacro MUI_LANGUAGE \"English\""] ++
     (if null plugins then [] else
@@ -28,12 +28,12 @@
         ["!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN"] ++
         [indent $ "!insertmacro MUI_DESCRIPTION_TEXT " ++ show i ++ " " ++ show d | (i,d) <- descs] ++
         ["!insertmacro MUI_FUNCTION_DESCRIPTION_END"])
-    where descs = filter (not . null . snd) $ concatMap secDescs $ universeBi xs
+    where descs = concatMap (filter (not . null . snd) . secDescs) $ universeBi xs
           inits = filter (\x -> not (isSection x) && not (isGlobal x)) xs
           fs = map fst funs
           funs = map (fst . head &&& concatMap snd) $ groupBy ((==) `on` fst) $ sortBy (compare `on` fst) $
                      [(Fun ".onInit",inits) | not $ null inits] ++ [(name,body) | Function name body <- universeBi xs]
-          plugins = sort $ nub [a ++ "::" ++ b | Plugin a b _ <- universeBi xs]
+          plugins = nubSort [a ++ "::" ++ b | Plugin a b _ <- universeBi xs]
 
 
 secDescs :: NSIS -> [(SectionId, Val)]
@@ -54,6 +54,7 @@
     Page{} -> True
     Unpage{} -> True
     RequestExecutionLevel{} -> True
+    Target{} -> True
     AddPluginDir{} -> True
     InstallDirRegKey{} -> True
     AllowRootDirInstall{} -> True
@@ -109,6 +110,7 @@
 out fs (Goto x) = ["Goto " ++ show x | x /= Label 0]
 out fs (IntOp a b "~" _) = [unwords $ "IntOp" : [show a, show b, "~"]] -- the only unary IntOp
 out fs (ExecShell AExecShell{..}) = [unwords ["ExecShell","\"\"",show esCommand,show esShow]]
+out fs (ExecShellWait AExecShell{..}) = [unwords ["ExecShellWait","\"\"",show esCommand,show esShow]]
 out fs (Plugin a b cs) = [unwords $ (a ++ "::" ++ b) : map show cs]
 out fs (AddPluginDir a) = [unwords ["!addplugindir",show a]]
 out fs (FindWindow a b c d e) = [unwords $ "FindWindow" : show a : map show ([b,c] ++ maybeToList d ++ maybeToList e)]
@@ -116,6 +118,7 @@
 out fs (Unicode x) = ["Unicode " ++ if x then "true" else "false"]
 out fs (UnsafeInject x) = [x]
 out fs (UnsafeInjectGlobal x) = [x]
+out fs (WriteRegMultiStr k a b c) = [unwords ["WriteRegMultiStr", "/REGEDIT5", show k, show a, show b, show c]]
 
 out fs x = [show x]
 
diff --git a/src/Development/NSIS/Sugar.hs b/src/Development/NSIS/Sugar.hs
--- a/src/Development/NSIS/Sugar.hs
+++ b/src/Development/NSIS/Sugar.hs
@@ -4,12 +4,13 @@
 {-# OPTIONS_GHC -fno-warn-unused-imports #-} -- Applicative and Monoid required < 7.9
 
 module Development.NSIS.Sugar(
-    Compressor(..), HKEY(..), MessageBoxType(..), Page(..), Level(..), Visibility(..), FileMode(..), SectionFlag(..),
+    Compressor(..), HKEY(..), MessageBoxType(..), Page(..), Level(..), Type.Target(..), Visibility(..), FileMode(..), SectionFlag(..),
     ShowWindow(..), FinishOptions(..), DetailsPrint(..),
     module Development.NSIS.Sugar, Label, SectionId
     ) where
 
-import Development.NSIS.Type
+import Development.NSIS.Type hiding (Target)
+import qualified Development.NSIS.Type as Type
 import Data.Char
 import Data.List
 import Data.Maybe
@@ -822,6 +823,12 @@
     let d = def{esCommand=x}
     emit $ ExecShell $ if null sw then d else d{esShow=last sw}
 
+execShellWait :: [ShowWindow] -> Exp String -> Action ()
+execShellWait sw x = do
+    Value x <- x
+    let d = def{esCommand=x}
+    emit $ ExecShellWait $ if null sw then d else d{esShow=last sw}
+
 sectionSetText :: SectionId -> Exp String -> Action ()
 sectionSetText x = emit1 $ SectionSetText x
 
@@ -890,6 +897,9 @@
 writeRegDWORD :: HKEY -> Exp String -> Exp String -> Exp Int -> Action ()
 writeRegDWORD k = emit3 $ WriteRegDWORD k
 
+writeRegMultiStr :: HKEY -> Exp String -> Exp String -> Exp String -> Action ()
+writeRegMultiStr k = emit3 $ WriteRegMultiStr k
+
 -- | While the action is executing, do not update the progress bar.
 --   Useful for functions which do a large amount of computation, or have loops.
 hideProgress :: Action a -> Action a
@@ -1119,6 +1129,9 @@
 
 requestExecutionLevel :: Level -> Action ()
 requestExecutionLevel = emit . RequestExecutionLevel
+
+target :: Type.Target -> Action ()
+target = emit . Type.Target
 
 type HWND = Exp Int
 
diff --git a/src/Development/NSIS/Type.hs b/src/Development/NSIS/Type.hs
--- a/src/Development/NSIS/Type.hs
+++ b/src/Development/NSIS/Type.hs
@@ -103,6 +103,7 @@
     | WriteRegStr HKEY Val Val Val
     | WriteRegExpandStr HKEY Val Val Val
     | WriteRegDWORD HKEY Val Val Val
+    | WriteRegMultiStr HKEY Val Val Val
     | ReadRegStr Var HKEY Val Val
     | DeleteRegKey HKEY Val
     | DeleteRegValue HKEY Val Val
@@ -110,11 +111,13 @@
     | Exec Val
     | ExecWait Val
     | ExecShell AExecShell
+    | ExecShellWait AExecShell
     | ClearErrors
     | Delete ADelete
     | RMDir ARMDir
     | CopyFiles ACopyFiles
     | RequestExecutionLevel Level
+    | Target Target
     | AddPluginDir Val
     | InstallDirRegKey HKEY Val Val
     | AllowRootDirInstall Bool
@@ -322,6 +325,14 @@
 
 data Level = None | User | Highest | Admin
      deriving (Show,Data,Typeable,Read,Bounded,Enum,Eq,Ord)
+
+data Target = AMD64Unicode | X86ANSI | X86Unicode
+     deriving (Data,Typeable,Read,Bounded,Enum,Eq,Ord)
+
+instance Show Target where
+    show AMD64Unicode = "amd64-unicode"
+    show X86ANSI = "x86-ansi"
+    show X86Unicode = "x86-unicode"
 
 data Visibility = Hide | Show | NeverShow
      deriving (Show,Data,Typeable,Read,Bounded,Enum,Eq,Ord)
diff --git a/test/Examples/Example2.hs b/test/Examples/Example2.hs
--- a/test/Examples/Example2.hs
+++ b/test/Examples/Example2.hs
@@ -6,7 +6,7 @@
 
 -- Based on example2.nsi from NSIS
 --
--- This script is based on example1.nsi, but it remember the directory, 
+-- This script is based on example1.nsi, but it remember the directory,
 -- has uninstall support and (optionally) installs start menu shortcuts.
 --
 -- It will install example2.nsi into a directory that the user selects,
@@ -25,7 +25,7 @@
     -- The default installation directory
     installDir "$PROGRAMFILES64/Example2"
 
-    -- Registry key to check for directory (so if you install again, it will 
+    -- Registry key to check for directory (so if you install again, it will
     -- overwrite the old one automatically)
     installDirRegKey HKLM "Software/NSIS_Example2" "Install_Dir"
 
diff --git a/test/Main.hs b/test/Main.hs
--- a/test/Main.hs
+++ b/test/Main.hs
@@ -5,7 +5,6 @@
 import Data.List
 import Data.Maybe
 import System.Process
-import System.Directory
 import System.Environment
 import System.Exit
 
@@ -49,19 +48,12 @@
         putStrLn "*****************************************************************"
     names <- return $ if null names then map fst examples else names
 
-    b <- findExecutable "makensis"
-    let build | "--build" `elem` flags = True
-              | "--nobuild" `elem` flags = False
-              | otherwise = isJust b
-
     forM_ names $ \name -> do
         let script = fromMaybe (error $ "Unknown example: " ++ name) $ lookup name examples
         unless ("--nowrite" `elem` flags) $ writeFile (name ++ ".nsi") $ nsis script
-        when build $ do
+        when ("--build" `elem` flags) $ do
             r <- system $ "makensis -V3 " ++ name ++ ".nsi"
             when (r /= ExitSuccess) $ error "NSIS FAILED"
         when ("--run" `elem` flags) $ do
             system $ name ++ ".exe"
             return ()
-    when (isNothing b) $
-        putStrLn "Warning: No nsis on the PATH, files were not built"
