Index: /AE/installer2/doc/AEI1-stuff_onisplit-commands.txt
===================================================================
--- /AE/installer2/doc/AEI1-stuff_onisplit-commands.txt	(revision 593)
+++ /AE/installer2/doc/AEI1-stuff_onisplit-commands.txt	(revision 594)
@@ -1,2 +1,4 @@
+filter mod-types from combobox with no nodes
+
 save current installed config
 
@@ -33,27 +35,9 @@
 
 check .net>2.0:
-bool CheckForRequiredSoftware(void)
-{
-#ifdef WIN32
-	// test for .NET 2.0 or higher
-	HKEY hKey;
-	if (!RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\.NETFramework\\policy\\v2.0", 0L, KEY_READ , &hKey) == ERROR_SUCCESS)
-	{
-		string dotnetMsg = "You don't have .NET 2.0 installed! .NET is a framework required by the Edition.\n";
-		dotnetMsg = dotnetMsg + "You can download it from:\n" +
-								"http://gumby.oni2.net/dotnet\n" +
-								"Please install .NET 2.0, then open this Installer again.\n\n" +
-								"Would you like to open the download webpage?";
-		wxMessageDialog* DotNetDialogOfDeath = new wxMessageDialog(TheWindow, dotnetMsg.c_str(), "AE Installer Alert",
-																 wxYES_NO | wxICON_EXCLAMATION	, wxDefaultPosition);
-		if (DotNetDialogOfDeath->ShowModal() == wxID_YES)
+win: http://msdn.microsoft.com/en-us/kb/kbarticle.aspx?id=318785
+HKEY_LOCAL_MACHINE\Software\Microsoft\NET Framework Setup\NDP\v2.0.50727: dword "Install" = 1
 			system("start http://www.microsoft.com/downloads/details.aspx?familyid=0856eacb-4362-4b0d-8edd-aab15c5e04f5");
-		RegCloseKey(hKey);
-		return false;
-	}
-#else // on Mac...
-	// test for the third-party "mono" framework, because without it, we are up a creek
-	FILE *fWhichMono = NULL;
-	char chrWhichMono[32];
+
+mac:
 	fWhichMono = popen("which mono", "r");
 	fgets(chrWhichMono, sizeof(chrWhichMono), fWhichMono);
@@ -63,16 +47,4 @@
 	
 	if (loc == string::npos) // this means that "which mono" did not return a path leading to the mono binary -- abort! abort! abort!
-	{
-		string monoMsg = "You don't have 'mono' installed! 'mono' is a command-line tool required by the Edition.\n";
-		monoMsg = monoMsg + "You can download it from: http://www.go-mono.com/mono-downloads/download.html (OS X 10.4+)\n" +
-							"or http://edt.oni2.net/AE/MonoFramework10.3.dmg (OS X 10.3)\n\n" +
-							"Please install 'mono', then open this Installer again.";
-		wxMessageDialog* MonoDialogOfDeath = new wxMessageDialog(TheWindow, monoMsg.c_str(), "AE Installer Alert", wxOK | wxICON_EXCLAMATION, wxDefaultPosition);
-		MonoDialogOfDeath->ShowModal();
-		return false; // it's quittin' time, Joe
-	}
-#endif
-	return true;
-}
 
 
Index: /AE/installer2/src/net/oni2/aeinstaller/AEInstaller.properties
===================================================================
--- /AE/installer2/src/net/oni2/aeinstaller/AEInstaller.properties	(revision 593)
+++ /AE/installer2/src/net/oni2/aeinstaller/AEInstaller.properties	(revision 594)
@@ -1,4 +1,4 @@
 appname=AE Installer 2
-appversion=0.32
+appversion=0.33
 
 invalidPath.title=Wrong directory
Index: /AE/installer2/src/net/oni2/aeinstaller/AEInstaller2.java
===================================================================
--- /AE/installer2/src/net/oni2/aeinstaller/AEInstaller2.java	(revision 593)
+++ /AE/installer2/src/net/oni2/aeinstaller/AEInstaller2.java	(revision 594)
@@ -17,4 +17,5 @@
 import javax.swing.UIManager.LookAndFeelInfo;
 
+import net.oni2.aeinstaller.backend.OniSplit;
 import net.oni2.aeinstaller.backend.Settings;
 import net.oni2.aeinstaller.backend.Settings.Platform;
@@ -126,4 +127,7 @@
 		System.out.println("ValidPath: "
 				+ StuffToRefactorLater.verifyRunningDirectory());
+		System.out.println("Platform:  " + Settings.getPlatform());
+		System.out.println("Architect: " + Settings.getArchitecture());
+		System.out.println(".NET:      " + OniSplit.isDotNETInstalled());
 
 		if (!StuffToRefactorLater.verifyRunningDirectory()) {
Index: /AE/installer2/src/net/oni2/aeinstaller/backend/OniSplit.java
===================================================================
--- /AE/installer2/src/net/oni2/aeinstaller/backend/OniSplit.java	(revision 594)
+++ /AE/installer2/src/net/oni2/aeinstaller/backend/OniSplit.java	(revision 594)
@@ -0,0 +1,72 @@
+package net.oni2.aeinstaller.backend;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Map;
+import java.util.Vector;
+
+import net.oni2.aeinstaller.backend.Settings.Architecture;
+import net.oni2.aeinstaller.backend.app_launcher.QuickAppExecution;
+
+/**
+ * @author Christian Illy
+ */
+public class OniSplit {
+
+	/**
+	 * @return is a .NET implementation installed?
+	 */
+	public static boolean isDotNETInstalled() {
+		switch (Settings.getPlatform()) {
+			case WIN:
+				try {
+					int view = WinRegistry.KEY_WOW64_32KEY;
+					if (Settings.getArchitecture() == Architecture.AMD64)
+						view = WinRegistry.KEY_WOW64_64KEY;
+
+					Map<String, String> m = WinRegistry
+							.readStringValues(
+									WinRegistry.HKEY_LOCAL_MACHINE,
+									"Software\\Microsoft\\NET Framework Setup\\NDP\\v2.0.50727",
+									view);
+					return m != null;
+				} catch (IllegalArgumentException e) {
+					// TODO Auto-generated catch block
+					e.printStackTrace();
+				} catch (IllegalAccessException e) {
+					// TODO Auto-generated catch block
+					e.printStackTrace();
+				} catch (InvocationTargetException e) {
+					// TODO Auto-generated catch block
+					e.printStackTrace();
+				} catch (Exception e) {
+					if (!e.getMessage()
+							.equals("Registry access not supported (not a Windows OS?)."))
+						// TODO Auto-generated catch block
+						e.printStackTrace();
+				}
+				return false;
+			case MACOS:
+			case LINUX:
+				Vector<String> cmd = new Vector<String>();
+				cmd.add("which");
+				cmd.add("mono");
+				Vector<String> res = null;
+				try {
+					res = QuickAppExecution.execute(cmd);
+				} catch (IOException e) {
+					// TODO Auto-generated catch block
+					e.printStackTrace();
+				}
+				if (res != null) {
+					if (res.get(0).startsWith("/")
+							&& res.get(0).endsWith("mono")) {
+						return true;
+					}
+				}
+				return false;
+			default:
+				return false;
+		}
+	}
+}
Index: /AE/installer2/src/net/oni2/aeinstaller/backend/Settings.java
===================================================================
--- /AE/installer2/src/net/oni2/aeinstaller/backend/Settings.java	(revision 593)
+++ /AE/installer2/src/net/oni2/aeinstaller/backend/Settings.java	(revision 594)
@@ -10,4 +10,7 @@
 import java.net.URLDecoder;
 import java.util.HashMap;
+import java.util.Vector;
+
+import net.oni2.aeinstaller.backend.app_launcher.QuickAppExecution;
 
 import com.thoughtworks.xstream.XStream;
@@ -26,4 +29,18 @@
 	 * @author Christian Illy
 	 */
+	public enum Architecture {
+		/**
+		 * 32 bit
+		 */
+		X86,
+		/**
+		 * 64 bit
+		 */
+		AMD64
+	};
+
+	/**
+	 * @author Christian Illy
+	 */
 	public enum Platform {
 		/**
@@ -75,4 +92,37 @@
 	public static boolean getDebug() {
 		return debugRun;
+	}
+
+	/**
+	 * @return Processor architecture
+	 */
+	public static Architecture getArchitecture() {
+		switch (getPlatform()) {
+			case WIN:
+				String arch = System.getenv("PROCESSOR_ARCHITECTURE")
+						.toLowerCase();
+				if (arch.startsWith("x86"))
+					return Architecture.X86;
+				return Architecture.AMD64;
+			case MACOS:
+			case LINUX:
+				Vector<String> cmd = new Vector<String>();
+				cmd.add("getconf");
+				cmd.add("LONG_BIT");
+				Vector<String> res = null;
+				try {
+					res = QuickAppExecution.execute(cmd);
+				} catch (IOException e) {
+					// TODO Auto-generated catch block
+					e.printStackTrace();
+				}
+				if (res != null) {
+					if (res.get(0).equals("64"))
+						return Architecture.AMD64;
+				}
+				return Architecture.X86;
+			default:
+				return null;
+		}
 	}
 
Index: /AE/installer2/src/net/oni2/aeinstaller/backend/SizeFormatter.java
===================================================================
--- /AE/installer2/src/net/oni2/aeinstaller/backend/SizeFormatter.java	(revision 594)
+++ /AE/installer2/src/net/oni2/aeinstaller/backend/SizeFormatter.java	(revision 594)
@@ -0,0 +1,35 @@
+package net.oni2.aeinstaller.backend;
+
+/**
+ * @author Christian Illy
+ */
+public class SizeFormatter {
+	/**
+	 * @param sizeVal
+	 *            Size in Byte
+	 * @param digits
+	 *            Number of digits
+	 * @return Formatted value
+	 */
+	public static String format(long sizeVal, int digits) {
+		String names[] = { "B", "KiB", "MiB", "GiB" };
+		int nameInd = 0;
+		float size = sizeVal;
+		while (size > 1024) {
+			nameInd++;
+			size /= 1024;
+		}
+		if (size < 10)
+			return String.format(
+					"%1." + String.valueOf(Math.max(digits - 1, 0)) + "f %s",
+					size, names[nameInd]);
+		else if (size < 100)
+			return String.format(
+					"%1." + String.valueOf(Math.max(digits - 2, 0)) + "f %s",
+					size, names[nameInd]);
+		else
+			return String.format(
+					"%1." + String.valueOf(Math.max(digits - 3, 0)) + "f %s",
+					size, names[nameInd]);
+	}
+}
Index: /AE/installer2/src/net/oni2/aeinstaller/backend/WinRegistry.java
===================================================================
--- /AE/installer2/src/net/oni2/aeinstaller/backend/WinRegistry.java	(revision 594)
+++ /AE/installer2/src/net/oni2/aeinstaller/backend/WinRegistry.java	(revision 594)
@@ -0,0 +1,502 @@
+package net.oni2.aeinstaller.backend;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.prefs.Preferences;
+
+/**
+ * @author Unknown
+ */
+public class WinRegistry {
+	/**
+	 * Constant for accessing HKCU
+	 */
+	public static final int HKEY_CURRENT_USER = 0x80000001;
+	/**
+	 * Constant for accessing HKLM
+	 */
+	public static final int HKEY_LOCAL_MACHINE = 0x80000002;
+	/**
+	 * Constant for successful accesses
+	 */
+	public static final int REG_SUCCESS = 0;
+	/**
+	 * Constant for not found
+	 */
+	public static final int REG_NOTFOUND = 2;
+	/**
+	 * Constant for access denied
+	 */
+	public static final int REG_ACCESSDENIED = 5;
+
+	/**
+	 * Access 32bit registry view when running as 64bit application
+	 */
+	public static final int KEY_WOW64_32KEY = 0x0200;
+	/**
+	 * Access 64bit registry view when running as 32bit application
+	 */
+	public static final int KEY_WOW64_64KEY = 0x0100;
+
+	private static final int KEY_ALL_ACCESS = 0xf003f;
+	private static final int KEY_READ = 0x20019;
+	private static Preferences userRoot = Preferences.userRoot();
+	private static Preferences systemRoot = Preferences.systemRoot();
+	private static Class<? extends Preferences> userClass = userRoot.getClass();
+	private static Method regOpenKey = null;
+	private static Method regCloseKey = null;
+	private static Method regQueryValueEx = null;
+	private static Method regEnumValue = null;
+	private static Method regQueryInfoKey = null;
+	private static Method regEnumKeyEx = null;
+	private static Method regCreateKeyEx = null;
+	private static Method regSetValueEx = null;
+	private static Method regDeleteKey = null;
+	private static Method regDeleteValue = null;
+
+	private static boolean usable = false;
+
+	static {
+		try {
+			regOpenKey = userClass.getDeclaredMethod("WindowsRegOpenKey",
+					new Class[] { int.class, byte[].class, int.class });
+			regOpenKey.setAccessible(true);
+			regCloseKey = userClass.getDeclaredMethod("WindowsRegCloseKey",
+					new Class[] { int.class });
+			regCloseKey.setAccessible(true);
+			regQueryValueEx = userClass.getDeclaredMethod(
+					"WindowsRegQueryValueEx", new Class[] { int.class,
+							byte[].class });
+			regQueryValueEx.setAccessible(true);
+			regEnumValue = userClass.getDeclaredMethod("WindowsRegEnumValue",
+					new Class[] { int.class, int.class, int.class });
+			regEnumValue.setAccessible(true);
+			regQueryInfoKey = userClass.getDeclaredMethod(
+					"WindowsRegQueryInfoKey1", new Class[] { int.class });
+			regQueryInfoKey.setAccessible(true);
+			regEnumKeyEx = userClass.getDeclaredMethod("WindowsRegEnumKeyEx",
+					new Class[] { int.class, int.class, int.class });
+			regEnumKeyEx.setAccessible(true);
+			regCreateKeyEx = userClass.getDeclaredMethod(
+					"WindowsRegCreateKeyEx", new Class[] { int.class,
+							byte[].class });
+			regCreateKeyEx.setAccessible(true);
+			regSetValueEx = userClass.getDeclaredMethod("WindowsRegSetValueEx",
+					new Class[] { int.class, byte[].class, byte[].class });
+			regSetValueEx.setAccessible(true);
+			regDeleteValue = userClass.getDeclaredMethod(
+					"WindowsRegDeleteValue", new Class[] { int.class,
+							byte[].class });
+			regDeleteValue.setAccessible(true);
+			regDeleteKey = userClass.getDeclaredMethod("WindowsRegDeleteKey",
+					new Class[] { int.class, byte[].class });
+			regDeleteKey.setAccessible(true);
+			usable = true;
+		} catch (Exception e) {
+			// e.printStackTrace();
+		}
+	}
+
+	private WinRegistry() {
+	}
+
+	/**
+	 * Read a value from key and value name
+	 * 
+	 * @param hkey
+	 *            HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE
+	 * @param key
+	 *            Key to access
+	 * @param valueName
+	 *            Name of value to read
+	 * @param wow64
+	 *            0 for standard registry access (32-bits for 32-bit app,
+	 *            64-bits for 64-bits app) or KEY_WOW64_32KEY to force access to
+	 *            32-bit registry view, or KEY_WOW64_64KEY to force access to
+	 *            64-bit registry view
+	 * @return the value
+	 * @throws Exception
+	 *             If registry access impossible
+	 * @throws IllegalArgumentException
+	 *             On illegal arguments
+	 * @throws IllegalAccessException
+	 *             On illegal access
+	 * @throws InvocationTargetException
+	 *             On reflection problems
+	 */
+	public static String readString(int hkey, String key, String valueName,
+			int wow64) throws Exception, IllegalArgumentException,
+			IllegalAccessException, InvocationTargetException {
+		if (!usable)
+			throw new Exception(
+					"Registry access not supported (not a Windows OS?).");
+		if (hkey == HKEY_LOCAL_MACHINE) {
+			return readString(systemRoot, hkey, key, valueName, wow64);
+		} else if (hkey == HKEY_CURRENT_USER) {
+			return readString(userRoot, hkey, key, valueName, wow64);
+		} else {
+			throw new IllegalArgumentException("hkey=" + hkey);
+		}
+	}
+
+	/**
+	 * Read value(s) and value name(s) form given key
+	 * 
+	 * @param hkey
+	 *            HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE
+	 * @param key
+	 *            Key to access
+	 * @param wow64
+	 *            0 for standard registry access (32-bits for 32-bit app,
+	 *            64-bits for 64-bits app) or KEY_WOW64_32KEY to force access to
+	 *            32-bit registry view, or KEY_WOW64_64KEY to force access to
+	 *            64-bit registry view
+	 * @return the value name(s) plus the value(s)
+	 * @throws Exception
+	 *             If registry access impossible
+	 * @throws IllegalArgumentException
+	 *             On illegal arguments
+	 * @throws IllegalAccessException
+	 *             On illegal access
+	 * @throws InvocationTargetException
+	 *             On reflection problems
+	 */
+	public static Map<String, String> readStringValues(int hkey, String key,
+			int wow64) throws Exception, IllegalArgumentException,
+			IllegalAccessException, InvocationTargetException {
+		if (!usable)
+			throw new Exception(
+					"Registry access not supported (not a Windows OS?).");
+		if (hkey == HKEY_LOCAL_MACHINE) {
+			return readStringValues(systemRoot, hkey, key, wow64);
+		} else if (hkey == HKEY_CURRENT_USER) {
+			return readStringValues(userRoot, hkey, key, wow64);
+		} else {
+			throw new IllegalArgumentException("hkey=" + hkey);
+		}
+	}
+
+	/**
+	 * Read the value name(s) from a given key
+	 * 
+	 * @param hkey
+	 *            HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE
+	 * @param key
+	 *            Key to access
+	 * @param wow64
+	 *            0 for standard registry access (32-bits for 32-bit app,
+	 *            64-bits for 64-bits app) or KEY_WOW64_32KEY to force access to
+	 *            32-bit registry view, or KEY_WOW64_64KEY to force access to
+	 *            64-bit registry view
+	 * @return the value name(s)
+	 * @throws Exception
+	 *             If registry access impossible
+	 * @throws IllegalArgumentException
+	 *             On illegal arguments
+	 * @throws IllegalAccessException
+	 *             On illegal access
+	 * @throws InvocationTargetException
+	 *             On reflection problems
+	 */
+	public static List<String> readStringSubKeys(int hkey, String key, int wow64)
+			throws Exception, IllegalArgumentException, IllegalAccessException,
+			InvocationTargetException {
+		if (!usable)
+			throw new Exception(
+					"Registry access not supported (not a Windows OS?).");
+		if (hkey == HKEY_LOCAL_MACHINE) {
+			return readStringSubKeys(systemRoot, hkey, key, wow64);
+		} else if (hkey == HKEY_CURRENT_USER) {
+			return readStringSubKeys(userRoot, hkey, key, wow64);
+		} else {
+			throw new IllegalArgumentException("hkey=" + hkey);
+		}
+	}
+
+	/**
+	 * Create a key
+	 * 
+	 * @param hkey
+	 *            HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE
+	 * @param key
+	 *            Key to access
+	 * @throws Exception
+	 *             If registry access impossible
+	 * @throws IllegalArgumentException
+	 *             On illegal arguments
+	 * @throws IllegalAccessException
+	 *             On illegal access
+	 * @throws InvocationTargetException
+	 *             On reflection problems
+	 */
+	public static void createKey(int hkey, String key) throws Exception,
+			IllegalArgumentException, IllegalAccessException,
+			InvocationTargetException {
+		int[] ret;
+		if (!usable)
+			throw new Exception(
+					"Registry access not supported (not a Windows OS?).");
+		if (hkey == HKEY_LOCAL_MACHINE) {
+			ret = createKey(systemRoot, hkey, key);
+			regCloseKey
+					.invoke(systemRoot, new Object[] { new Integer(ret[0]) });
+		} else if (hkey == HKEY_CURRENT_USER) {
+			ret = createKey(userRoot, hkey, key);
+			regCloseKey.invoke(userRoot, new Object[] { new Integer(ret[0]) });
+		} else {
+			throw new IllegalArgumentException("hkey=" + hkey);
+		}
+		if (ret[1] != REG_SUCCESS) {
+			throw new IllegalArgumentException("rc=" + ret[1] + "  key=" + key);
+		}
+	}
+
+	/**
+	 * Write a value in a given key/value name
+	 * 
+	 * @param hkey
+	 *            HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE
+	 * @param key
+	 *            Key to access
+	 * @param valueName
+	 *            Name of value to write to
+	 * @param value
+	 *            String to write
+	 * @param wow64
+	 *            0 for standard registry access (32-bits for 32-bit app,
+	 *            64-bits for 64-bits app) or KEY_WOW64_32KEY to force access to
+	 *            32-bit registry view, or KEY_WOW64_64KEY to force access to
+	 *            64-bit registry view
+	 * @throws Exception
+	 *             If registry access impossible
+	 * @throws IllegalArgumentException
+	 *             On illegal arguments
+	 * @throws IllegalAccessException
+	 *             On illegal access
+	 * @throws InvocationTargetException
+	 *             On reflection problems
+	 */
+	public static void writeStringValue(int hkey, String key, String valueName,
+			String value, int wow64) throws Exception,
+			IllegalArgumentException, IllegalAccessException,
+			InvocationTargetException {
+		if (!usable)
+			throw new Exception(
+					"Registry access not supported (not a Windows OS?).");
+		if (hkey == HKEY_LOCAL_MACHINE) {
+			writeStringValue(systemRoot, hkey, key, valueName, value, wow64);
+		} else if (hkey == HKEY_CURRENT_USER) {
+			writeStringValue(userRoot, hkey, key, valueName, value, wow64);
+		} else {
+			throw new IllegalArgumentException("hkey=" + hkey);
+		}
+	}
+
+	/**
+	 * Delete a given key
+	 * 
+	 * @param hkey
+	 *            HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE
+	 * @param key
+	 *            Key to delete
+	 * @throws Exception
+	 *             If registry access impossible
+	 * @throws IllegalArgumentException
+	 *             On illegal arguments
+	 * @throws IllegalAccessException
+	 *             On illegal access
+	 * @throws InvocationTargetException
+	 *             On reflection problems
+	 */
+	public static void deleteKey(int hkey, String key) throws Exception,
+			IllegalArgumentException, IllegalAccessException,
+			InvocationTargetException {
+		int rc = -1;
+		if (!usable)
+			throw new Exception(
+					"Registry access not supported (not a Windows OS?).");
+		if (hkey == HKEY_LOCAL_MACHINE) {
+			rc = deleteKey(systemRoot, hkey, key);
+		} else if (hkey == HKEY_CURRENT_USER) {
+			rc = deleteKey(userRoot, hkey, key);
+		}
+		if (rc != REG_SUCCESS) {
+			throw new IllegalArgumentException("rc=" + rc + "  key=" + key);
+		}
+	}
+
+	/**
+	 * delete a value from a given key/value name
+	 * 
+	 * @param hkey
+	 *            HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE
+	 * @param key
+	 *            Key to access
+	 * @param value
+	 *            Name of value to delete
+	 * @param wow64
+	 *            0 for standard registry access (32-bits for 32-bit app,
+	 *            64-bits for 64-bits app) or KEY_WOW64_32KEY to force access to
+	 *            32-bit registry view, or KEY_WOW64_64KEY to force access to
+	 *            64-bit registry view
+	 * @throws Exception
+	 *             If registry access impossible
+	 * @throws IllegalArgumentException
+	 *             On illegal arguments
+	 * @throws IllegalAccessException
+	 *             On illegal access
+	 * @throws InvocationTargetException
+	 *             On reflection problems
+	 */
+	public static void deleteValue(int hkey, String key, String value, int wow64)
+			throws Exception, IllegalArgumentException, IllegalAccessException,
+			InvocationTargetException {
+		if (!usable)
+			throw new Exception(
+					"Registry access not supported (not a Windows OS?).");
+		int rc = -1;
+		if (hkey == HKEY_LOCAL_MACHINE) {
+			rc = deleteValue(systemRoot, hkey, key, value, wow64);
+		} else if (hkey == HKEY_CURRENT_USER) {
+			rc = deleteValue(userRoot, hkey, key, value, wow64);
+		}
+		if (rc != REG_SUCCESS) {
+			throw new IllegalArgumentException("rc=" + rc + "  key=" + key
+					+ "  value=" + value);
+		}
+	}
+
+	// ========================================================================
+	private static int deleteValue(Preferences root, int hkey, String key,
+			String value, int wow64) throws IllegalArgumentException,
+			IllegalAccessException, InvocationTargetException {
+		int[] handles = (int[]) regOpenKey.invoke(root, new Object[] {
+				new Integer(hkey), toCstr(key),
+				new Integer(KEY_ALL_ACCESS | wow64) });
+		if (handles[1] != REG_SUCCESS) {
+			return handles[1]; // can be REG_NOTFOUND, REG_ACCESSDENIED
+		}
+		int rc = ((Integer) regDeleteValue.invoke(root, new Object[] {
+				new Integer(handles[0]), toCstr(value) })).intValue();
+		regCloseKey.invoke(root, new Object[] { new Integer(handles[0]) });
+		return rc;
+	}
+
+	// ========================================================================
+	private static int deleteKey(Preferences root, int hkey, String key)
+			throws IllegalArgumentException, IllegalAccessException,
+			InvocationTargetException {
+		int rc = ((Integer) regDeleteKey.invoke(root, new Object[] {
+				new Integer(hkey), toCstr(key) })).intValue();
+		return rc; // can REG_NOTFOUND, REG_ACCESSDENIED, REG_SUCCESS
+	}
+
+	// ========================================================================
+	private static String readString(Preferences root, int hkey, String key,
+			String value, int wow64) throws IllegalArgumentException,
+			IllegalAccessException, InvocationTargetException {
+		int[] handles = (int[]) regOpenKey
+				.invoke(root, new Object[] { new Integer(hkey), toCstr(key),
+						new Integer(KEY_READ | wow64) });
+		if (handles[1] != REG_SUCCESS) {
+			return null;
+		}
+		byte[] valb = (byte[]) regQueryValueEx.invoke(root, new Object[] {
+				new Integer(handles[0]), toCstr(value) });
+		regCloseKey.invoke(root, new Object[] { new Integer(handles[0]) });
+		return (valb != null ? new String(valb).trim() : null);
+	}
+
+	// ========================================================================
+	private static Map<String, String> readStringValues(Preferences root,
+			int hkey, String key, int wow64) throws Exception,
+			IllegalArgumentException, IllegalAccessException,
+			InvocationTargetException {
+		HashMap<String, String> results = new HashMap<String, String>();
+		int[] handles = (int[]) regOpenKey
+				.invoke(root, new Object[] { new Integer(hkey), toCstr(key),
+						new Integer(KEY_READ | wow64) });
+		if (handles[1] != REG_SUCCESS) {
+			return null;
+		}
+		int[] info = (int[]) regQueryInfoKey.invoke(root,
+				new Object[] { new Integer(handles[0]) });
+
+		int count = info[2]; // count
+		int maxlen = info[4]; // value length max
+		for (int index = 0; index < count; index++) {
+			byte[] name = (byte[]) regEnumValue.invoke(root, new Object[] {
+					new Integer(handles[0]), new Integer(index),
+					new Integer(maxlen + 1) });
+			String value = readString(hkey, key, new String(name), wow64);
+			results.put(new String(name).trim(), value);
+		}
+		regCloseKey.invoke(root, new Object[] { new Integer(handles[0]) });
+		return results;
+	}
+
+	// ========================================================================
+	private static List<String> readStringSubKeys(Preferences root, int hkey,
+			String key, int wow64) throws IllegalArgumentException,
+			IllegalAccessException, InvocationTargetException {
+		List<String> results = new ArrayList<String>();
+		int[] handles = (int[]) regOpenKey
+				.invoke(root, new Object[] { new Integer(hkey), toCstr(key),
+						new Integer(KEY_READ | wow64) });
+		if (handles[1] != REG_SUCCESS) {
+			return null;
+		}
+		int[] info = (int[]) regQueryInfoKey.invoke(root,
+				new Object[] { new Integer(handles[0]) });
+
+		int count = info[0]; // Fix: info[2] was being used here with wrong
+								// results. Suggested by davenpcj, confirmed by
+								// Petrucio
+		int maxlen = info[3]; // value length max
+		for (int index = 0; index < count; index++) {
+			byte[] name = (byte[]) regEnumKeyEx.invoke(root, new Object[] {
+					new Integer(handles[0]), new Integer(index),
+					new Integer(maxlen + 1) });
+			results.add(new String(name).trim());
+		}
+		regCloseKey.invoke(root, new Object[] { new Integer(handles[0]) });
+		return results;
+	}
+
+	// ========================================================================
+	private static int[] createKey(Preferences root, int hkey, String key)
+			throws IllegalArgumentException, IllegalAccessException,
+			InvocationTargetException {
+		return (int[]) regCreateKeyEx.invoke(root, new Object[] {
+				new Integer(hkey), toCstr(key) });
+	}
+
+	// ========================================================================
+	private static void writeStringValue(Preferences root, int hkey,
+			String key, String valueName, String value, int wow64)
+			throws IllegalArgumentException, IllegalAccessException,
+			InvocationTargetException {
+		int[] handles = (int[]) regOpenKey.invoke(root, new Object[] {
+				new Integer(hkey), toCstr(key),
+				new Integer(KEY_ALL_ACCESS | wow64) });
+		regSetValueEx.invoke(root, new Object[] { new Integer(handles[0]),
+				toCstr(valueName), toCstr(value) });
+		regCloseKey.invoke(root, new Object[] { new Integer(handles[0]) });
+	}
+
+	// ========================================================================
+	// utility
+	private static byte[] toCstr(String str) {
+		byte[] result = new byte[str.length() + 1];
+
+		for (int i = 0; i < str.length(); i++) {
+			result[i] = (byte) str.charAt(i);
+		}
+		result[str.length()] = 0;
+		return result;
+	}
+}
Index: /AE/installer2/src/net/oni2/aeinstaller/backend/app_launcher/LongRunningExecution.java
===================================================================
--- /AE/installer2/src/net/oni2/aeinstaller/backend/app_launcher/LongRunningExecution.java	(revision 594)
+++ /AE/installer2/src/net/oni2/aeinstaller/backend/app_launcher/LongRunningExecution.java	(revision 594)
@@ -0,0 +1,36 @@
+package net.oni2.aeinstaller.backend.app_launcher;
+
+import java.io.IOException;
+
+//TODO
+
+/**
+ * @author Christian Illy
+ */
+public class LongRunningExecution implements Runnable {
+	private ProcessBuilder pb;
+
+	/**
+	 * @param pb
+	 *            ProcessBuilder to use
+	 */
+	public LongRunningExecution(ProcessBuilder pb) {
+		this.pb = pb;
+	}
+
+	@Override
+	public void run() {
+		try {
+			Process p = pb.start();
+			p.waitFor();
+//			GameManager.getInstance().refreshInstalledInfo();
+		} catch (IOException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		} catch (InterruptedException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+	}
+
+}
Index: /AE/installer2/src/net/oni2/aeinstaller/backend/app_launcher/QuickAppExecution.java
===================================================================
--- /AE/installer2/src/net/oni2/aeinstaller/backend/app_launcher/QuickAppExecution.java	(revision 594)
+++ /AE/installer2/src/net/oni2/aeinstaller/backend/app_launcher/QuickAppExecution.java	(revision 594)
@@ -0,0 +1,43 @@
+package net.oni2.aeinstaller.backend.app_launcher;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.List;
+import java.util.Vector;
+
+/**
+ * @author Christian Illy
+ */
+public class QuickAppExecution {
+
+	/**
+	 * Execute a short running application
+	 * 
+	 * @param cmdLine
+	 *            List of command and arguments
+	 * @return List of output lines
+	 * @throws IOException
+	 *             Exc
+	 */
+	public static Vector<String> execute(List<String> cmdLine)
+			throws IOException {
+		ProcessBuilder pb = new ProcessBuilder(cmdLine);
+		pb.redirectErrorStream(true);
+		Process proc = pb.start();
+
+		InputStream is = proc.getInputStream();
+		InputStreamReader isr = new InputStreamReader(is);
+		BufferedReader br = new BufferedReader(isr);
+
+		String line;
+		Vector<String> lines = new Vector<String>();
+
+		while ((line = br.readLine()) != null) {
+			lines.add(line);
+		}
+		return lines;
+	}
+
+}
Index: /AE/installer2/src/net/oni2/aeinstaller/gui/MainWin.properties
===================================================================
--- /AE/installer2/src/net/oni2/aeinstaller/gui/MainWin.properties	(revision 593)
+++ /AE/installer2/src/net/oni2/aeinstaller/gui/MainWin.properties	(revision 594)
@@ -21,5 +21,5 @@
 btnRevertSelection.text=Revert selection
 btnRevertSelection.tooltip=Select mods which are currently installed
-lblModTypes.text=Mod types: 
+lblModTypes.text=Mod type: 
 
 lblSubmitter.text=Submitter:
Index: /AE/installer2/src/net/oni2/aeinstaller/gui/MainWin.yml
===================================================================
--- /AE/installer2/src/net/oni2/aeinstaller/gui/MainWin.yml	(revision 593)
+++ /AE/installer2/src/net/oni2/aeinstaller/gui/MainWin.yml	(revision 594)
@@ -67,4 +67,5 @@
         rowConstraints: grow
         constraints:
-            - tools: dock north
             - contents: grow
+
+#            - tools: dock north
