Index: AE/installer2/src/net/oni2/aeinstaller/backend/oni/Installer.java
===================================================================
--- AE/installer2/src/net/oni2/aeinstaller/backend/oni/Installer.java	(revision 708)
+++ AE/installer2/src/net/oni2/aeinstaller/backend/oni/Installer.java	(revision 720)
@@ -21,4 +21,5 @@
 import java.util.regex.Pattern;
 
+import net.oni2.SettingsManager;
 import net.oni2.aeinstaller.AEInstaller2;
 import net.oni2.aeinstaller.backend.CaseInsensitiveFile;
@@ -27,7 +28,7 @@
 import net.oni2.aeinstaller.backend.packages.Package;
 import net.oni2.aeinstaller.backend.packages.PackageManager;
-import net.oni2.applicationinvoker.AppExecutionResult;
-import net.oni2.settingsmanager.Settings;
-import net.oni2.settingsmanager.Settings.Platform;
+import net.oni2.platformtools.PlatformInformation;
+import net.oni2.platformtools.PlatformInformation.Platform;
+import net.oni2.platformtools.applicationinvoker.ApplicationInvocationResult;
 
 import org.apache.commons.io.FileUtils;
@@ -134,5 +135,5 @@
 							copyRemoveToolsFiles(plainCommon,
 									Paths.getEditionBasePath(), uninstall);
-						if (Settings.getPlatform() == Platform.MACOS
+						if (PlatformInformation.getPlatform() == Platform.MACOS
 								&& plainMac.exists())
 							copyRemoveToolsFiles(plainMac,
@@ -225,7 +226,7 @@
 						|| s.endsWith(".raw")
 						|| s.endsWith(".sep")
-						|| (s.equals("intro.bik") && !Settings.getInstance()
+						|| (s.equals("intro.bik") && !SettingsManager.getInstance()
 								.get("copyintro", false))
-						|| (s.equals("outro.bik") && !Settings.getInstance()
+						|| (s.equals("outro.bik") && !SettingsManager.getInstance()
 								.get("copyoutro", false));
 			}
@@ -279,5 +280,5 @@
 					if (oniCommon.exists())
 						foldersOni.add(oniCommon);
-					if (Settings.getPlatform() == Platform.MACOS
+					if (PlatformInformation.getPlatform() == Platform.MACOS
 							&& oniMac.exists())
 						foldersOni.add(oniMac);
@@ -301,5 +302,5 @@
 					if (patchesCommon.exists())
 						foldersPatches.add(patchesCommon);
-					if (Settings.getPlatform() == Platform.MACOS
+					if (PlatformInformation.getPlatform() == Platform.MACOS
 							&& patchesMac.exists())
 						foldersPatches.add(patchesMac);
@@ -369,7 +370,7 @@
 					File bslWin = CaseInsensitiveFile.getCaseInsensitiveFile(
 							bsl, "win_only");
-					if ((Settings.getPlatform() == Platform.MACOS && bslMac
+					if ((PlatformInformation.getPlatform() == Platform.MACOS && bslMac
 							.exists())
-							|| ((Settings.getPlatform() == Platform.WIN || Settings
+							|| ((PlatformInformation.getPlatform() == Platform.WIN || PlatformInformation
 									.getPlatform() == Platform.LINUX) && bslWin
 									.exists()) || bslCommon.exists()) {
@@ -406,5 +407,5 @@
 			File bslWin = CaseInsensitiveFile.getCaseInsensitiveFile(bsl,
 					"win_only");
-			if (Settings.getPlatform() == Platform.MACOS && bslMac.exists()) {
+			if (PlatformInformation.getPlatform() == Platform.MACOS && bslMac.exists()) {
 				for (File f : bslMac.listFiles(dirFileFilter)) {
 					File targetBSL = new File(targetBaseFolder, f.getName());
@@ -413,5 +414,5 @@
 				}
 			}
-			if ((Settings.getPlatform() == Platform.WIN || Settings
+			if ((PlatformInformation.getPlatform() == Platform.WIN || PlatformInformation
 					.getPlatform() == Platform.LINUX) && bslWin.exists()) {
 				for (File f : bslWin.listFiles(dirFileFilter)) {
@@ -508,5 +509,5 @@
 					if (srcFolder.getPath().toLowerCase().contains("vanilla")) {
 						// Extract from .dat
-						AppExecutionResult res = OniSplit.export(levelFolder,
+						ApplicationInvocationResult res = OniSplit.export(levelFolder,
 								srcFolder, exportPatterns);
 						logAppOutput(res, log);
@@ -533,5 +534,5 @@
 								.contains("vanilla")) {
 							// Extract from .dat
-							AppExecutionResult res = OniSplit.export(
+							ApplicationInvocationResult res = OniSplit.export(
 									levelFolder, srcFolder, patterns);
 							logAppOutput(res, log);
@@ -556,5 +557,5 @@
 			Vector<File> files = new Vector<File>();
 			files.add(new File(levelFolder, "*.oni"));
-			AppExecutionResult res = OniSplit.convertOniToXML(levelFolderXML,
+			ApplicationInvocationResult res = OniSplit.convertOniToXML(levelFolderXML,
 					files);
 			logAppOutput(res, log);
@@ -613,5 +614,5 @@
 					"Installing level " + l);
 
-			AppExecutionResult res = OniSplit.packLevel(oniLevelFolders.get(l),
+			ApplicationInvocationResult res = OniSplit.packLevel(oniLevelFolders.get(l),
 					new File(Paths.getEditionGDF(), sanitizeLevelName(l)
 							+ ".dat"));
@@ -627,5 +628,5 @@
 
 	private static void copyVideos(PrintWriter log) {
-		if (Settings.getInstance().get("copyintro", false)) {
+		if (SettingsManager.getInstance().get("copyintro", false)) {
 			File src = new File(Paths.getVanillaGDF(), "intro.bik");
 			log.println("Copying intro");
@@ -640,5 +641,5 @@
 			log.println("NOT copying intro");
 		}
-		if (Settings.getInstance().get("copyoutro", true)) {
+		if (SettingsManager.getInstance().get("copyoutro", true)) {
 			File src = new File(Paths.getVanillaGDF(), "outro.bik");
 			log.println("Copying outro");
@@ -741,5 +742,5 @@
 
 				// Export Vanilla-Level-Dat -> Temp/Level
-				AppExecutionResult res = OniSplit.export(tempLevelFolder, f);
+				ApplicationInvocationResult res = OniSplit.export(tempLevelFolder, f);
 				logAppOutput(res, log);
 
@@ -763,5 +764,5 @@
 				folders.add(f);
 
-				AppExecutionResult res = OniSplit
+				ApplicationInvocationResult res = OniSplit
 						.importLevel(folders,
 								new File(Paths.getVanillaOnisPath(), levelName
@@ -922,5 +923,5 @@
 	}
 
-	private static void logAppOutput(AppExecutionResult result, PrintWriter log) {
+	private static void logAppOutput(ApplicationInvocationResult result, PrintWriter log) {
 		if (result != null) {
 			log.println("\t\t\tCalled:");
Index: AE/installer2/src/net/oni2/aeinstaller/backend/oni/OniLauncher.java
===================================================================
--- AE/installer2/src/net/oni2/aeinstaller/backend/oni/OniLauncher.java	(revision 720)
+++ AE/installer2/src/net/oni2/aeinstaller/backend/oni/OniLauncher.java	(revision 720)
@@ -0,0 +1,68 @@
+package net.oni2.aeinstaller.backend.oni;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.Vector;
+
+import net.oni2.aeinstaller.backend.Paths;
+import net.oni2.platformtools.PlatformInformation;
+import net.oni2.platformtools.applicationinvoker.ApplicationInvoker;
+import net.oni2.platformtools.applicationinvoker.EExeType;
+import net.oni2.platformtools.applicationinvoker.ERuntimeNotInstalledException;
+
+/**
+ * @author Christian Illy
+ */
+public class OniLauncher {
+
+	private static File getOniExe() {
+		File exe = null;
+		switch (PlatformInformation.getPlatform()) {
+			case WIN:
+				exe = new File(Paths.getEditionBasePath(), "Oni.exe");
+				break;
+			case MACOS:
+				exe = new File(Paths.getEditionBasePath(),
+						"Oni.app/Contents/MacOS/Oni");
+				break;
+			case LINUX:
+				exe = new File(Paths.getEditionBasePath(), "Oni.exe");
+				break;
+			default:
+		}
+		if ((exe != null) && !exe.exists())
+			exe = null;
+		return exe;
+	}
+
+	private static EExeType getOniExeType() {
+		switch (PlatformInformation.getPlatform()) {
+			case MACOS:
+				return EExeType.OSBINARY;
+			default:
+				return EExeType.WINEXE;
+		}
+	}
+
+	/**
+	 * @param windowed
+	 *            Run in windowed mode
+	 * @throws FileNotFoundException
+	 *             If Oni's executable was not found
+	 * @throws ERuntimeNotInstalledException
+	 *             If Linux and Wine not found
+	 */
+	public static void launch(boolean windowed) throws FileNotFoundException,
+			ERuntimeNotInstalledException {
+		File exe = getOniExe();
+		if (exe == null)
+			throw new FileNotFoundException("Oni's executable was not found");
+		Vector<String> params = new Vector<String>();
+		params.add("-debugfiles");
+		if (windowed)
+			params.add("-noswitch");
+		ApplicationInvoker.execute(getOniExeType(), exe.getParentFile(), exe,
+				params);
+	}
+
+}
Index: AE/installer2/src/net/oni2/aeinstaller/backend/oni/OniSplit.java
===================================================================
--- AE/installer2/src/net/oni2/aeinstaller/backend/oni/OniSplit.java	(revision 708)
+++ AE/installer2/src/net/oni2/aeinstaller/backend/oni/OniSplit.java	(revision 720)
@@ -6,10 +6,11 @@
 
 import net.oni2.aeinstaller.backend.CaseInsensitiveFile;
-import net.oni2.aeinstaller.backend.DotNet;
 import net.oni2.aeinstaller.backend.Paths;
-import net.oni2.applicationinvoker.AppExecution;
-import net.oni2.applicationinvoker.AppExecutionResult;
-import net.oni2.settingsmanager.Settings;
-import net.oni2.settingsmanager.Settings.Platform;
+import net.oni2.platformtools.PlatformInformation;
+import net.oni2.platformtools.PlatformInformation.Platform;
+import net.oni2.platformtools.applicationinvoker.ApplicationInvoker;
+import net.oni2.platformtools.applicationinvoker.ApplicationInvocationResult;
+import net.oni2.platformtools.applicationinvoker.EExeType;
+import net.oni2.platformtools.applicationinvoker.ERuntimeNotInstalledException;
 
 /**
@@ -34,5 +35,5 @@
 	 * @return OniSplit output
 	 */
-	public static AppExecutionResult export(File targetFolder, File input) {
+	public static ApplicationInvocationResult export(File targetFolder, File input) {
 		return export(targetFolder, input, null);
 	}
@@ -49,22 +50,24 @@
 	 * @return OniSplit output
 	 */
-	public static AppExecutionResult export(File targetFolder, File input,
+	public static ApplicationInvocationResult export(File targetFolder, File input,
 			Vector<String> patterns) {
 		if (!targetFolder.exists())
 			targetFolder.mkdir();
 
-		Vector<String> cmdLine = getProgramInvocation();
+		Vector<String> params = new Vector<String>();
 		if (patterns == null)
-			cmdLine.add("-export");
+			params.add("-export");
 		else {
 			for (String p : patterns)
-				cmdLine.add("-export:" + p);
-		}
-		cmdLine.add(targetFolder.getPath());
-		cmdLine.add(input.getPath());
-		AppExecutionResult res = null;
-		try {
-			res = AppExecution.executeAndWait(cmdLine);
-		} catch (IOException e) {
+				params.add("-export:" + p);
+		}
+		params.add(targetFolder.getPath());
+		params.add(input.getPath());
+		ApplicationInvocationResult res = null;
+		try {
+			res = ApplicationInvoker.executeAndWait(EExeType.DOTNET, null, getProgramFile(), params);
+		} catch (IOException e) {
+			e.printStackTrace();
+		} catch (ERuntimeNotInstalledException e) {
 			e.printStackTrace();
 		}
@@ -81,15 +84,17 @@
 	 * @return OniSplit output
 	 */
-	public static AppExecutionResult importLevel(Vector<File> sourceFolders,
+	public static ApplicationInvocationResult importLevel(Vector<File> sourceFolders,
 			File targetFile) {
-		Vector<String> cmdLine = getProgramInvocation();
-		cmdLine.add(getImportParam());
+		Vector<String> params = new Vector<String>();
+		params.add(getImportParam());
 		for (File f : sourceFolders)
-			cmdLine.add(f.getPath());
-		cmdLine.add(targetFile.getPath());
-		AppExecutionResult res = null;
-		try {
-			res = AppExecution.executeAndWait(cmdLine);
-		} catch (IOException e) {
+			params.add(f.getPath());
+		params.add(targetFile.getPath());
+		ApplicationInvocationResult res = null;
+		try {
+			res = ApplicationInvoker.executeAndWait(EExeType.DOTNET, null, getProgramFile(), params);
+		} catch (IOException e) {
+			e.printStackTrace();
+		} catch (ERuntimeNotInstalledException e) {
 			e.printStackTrace();
 		}
@@ -108,17 +113,19 @@
 	 * @return OniSplit output
 	 */
-	public static AppExecutionResult packLevel(Vector<File> sourceFoldersFiles,
+	public static ApplicationInvocationResult packLevel(Vector<File> sourceFoldersFiles,
 			File targetFile) {
-		Vector<String> cmdLine = getProgramInvocation();
-		cmdLine.add(getPackParam());
-		cmdLine.add(getPackTypeParam());
-		cmdLine.add("-out");
-		cmdLine.add(targetFile.getPath());
+		Vector<String> params = new Vector<String>();
+		params.add(getPackParam());
+		params.add(getPackTypeParam());
+		params.add("-out");
+		params.add(targetFile.getPath());
 		for (File f : sourceFoldersFiles)
-			cmdLine.add(f.getPath());
-		AppExecutionResult res = null;
-		try {
-			res = AppExecution.executeAndWait(cmdLine);
-		} catch (IOException e) {
+			params.add(f.getPath());
+		ApplicationInvocationResult res = null;
+		try {
+			res = ApplicationInvoker.executeAndWait(EExeType.DOTNET, null, getProgramFile(), params);
+		} catch (IOException e) {
+			e.printStackTrace();
+		} catch (ERuntimeNotInstalledException e) {
 			e.printStackTrace();
 		}
@@ -138,18 +145,20 @@
 	 * @return OniSplit output
 	 */
-	public static AppExecutionResult move(File targetFolder, String input,
+	public static ApplicationInvocationResult move(File targetFolder, String input,
 			String moveParameter) {
 		if (!targetFolder.exists())
 			targetFolder.mkdir();
 
-		Vector<String> cmdLine = getProgramInvocation();
-		cmdLine.add("-move"
+		Vector<String> params = new Vector<String>();
+		params.add("-move"
 				+ (moveParameter != null ? ":" + moveParameter : ""));
-		cmdLine.add(targetFolder.getPath());
-		cmdLine.add(input);
-		AppExecutionResult res = null;
-		try {
-			res = AppExecution.executeAndWait(cmdLine);
-		} catch (IOException e) {
+		params.add(targetFolder.getPath());
+		params.add(input);
+		ApplicationInvocationResult res = null;
+		try {
+			res = ApplicationInvoker.executeAndWait(EExeType.DOTNET, null, getProgramFile(), params);
+		} catch (IOException e) {
+			e.printStackTrace();
+		} catch (ERuntimeNotInstalledException e) {
 			e.printStackTrace();
 		}
@@ -166,19 +175,21 @@
 	 * @return OniSplit output
 	 */
-	public static AppExecutionResult convertOniToXML(File targetFolder,
+	public static ApplicationInvocationResult convertOniToXML(File targetFolder,
 			Vector<File> inputFiles) {
 		if (!targetFolder.exists())
 			targetFolder.mkdirs();
 
-		Vector<String> cmdLine = getProgramInvocation();
-		cmdLine.add("-extract:xml");
-		cmdLine.add(targetFolder.getPath());
+		Vector<String> params = new Vector<String>();
+		params.add("-extract:xml");
+		params.add(targetFolder.getPath());
 		for (File f : inputFiles) {
-			cmdLine.add(f.getPath());
-		}
-		AppExecutionResult res = null;
-		try {
-			res = AppExecution.executeAndWait(cmdLine);
-		} catch (IOException e) {
+			params.add(f.getPath());
+		}
+		ApplicationInvocationResult res = null;
+		try {
+			res = ApplicationInvoker.executeAndWait(EExeType.DOTNET, null, getProgramFile(), params);
+		} catch (IOException e) {
+			e.printStackTrace();
+		} catch (ERuntimeNotInstalledException e) {
 			e.printStackTrace();
 		}
@@ -195,19 +206,21 @@
 	 * @return OniSplit output
 	 */
-	public static AppExecutionResult convertXMLtoOni(File targetFolder,
+	public static ApplicationInvocationResult convertXMLtoOni(File targetFolder,
 			Vector<File> inputFiles) {
 		if (!targetFolder.exists())
 			targetFolder.mkdirs();
 
-		Vector<String> cmdLine = getProgramInvocation();
-		cmdLine.add("-create");
-		cmdLine.add(targetFolder.getPath());
+		Vector<String> params = new Vector<String>();
+		params.add("-create");
+		params.add(targetFolder.getPath());
 		for (File f : inputFiles) {
-			cmdLine.add(f.getPath());
-		}
-		AppExecutionResult res = null;
-		try {
-			res = AppExecution.executeAndWait(cmdLine);
-		} catch (IOException e) {
+			params.add(f.getPath());
+		}
+		ApplicationInvocationResult res = null;
+		try {
+			res = ApplicationInvoker.executeAndWait(EExeType.DOTNET, null, getProgramFile(), params);
+		} catch (IOException e) {
+			e.printStackTrace();
+		} catch (ERuntimeNotInstalledException e) {
 			e.printStackTrace();
 		}
@@ -216,5 +229,5 @@
 
 	private static String getImportParam() {
-		if (Settings.getPlatform() == Platform.MACOS)
+		if (PlatformInformation.getPlatform() == Platform.MACOS)
 			return "-import:sep";
 		else
@@ -227,16 +240,8 @@
 
 	private static String getPackTypeParam() {
-		if (Settings.getPlatform() == Platform.MACOS)
+		if (PlatformInformation.getPlatform() == Platform.MACOS)
 			return "-type:macintel";
 		else
 			return "-type:pc";
-	}
-
-	private static Vector<String> getProgramInvocation() {
-		Vector<String> res = new Vector<String>();
-		if (DotNet.getRuntimeExe().length() > 0)
-			res.add(DotNet.getRuntimeExe());
-		res.add(getProgramFile().getPath());
-		return res;
 	}
 
Index: AE/installer2/src/net/oni2/aeinstaller/backend/oni/XMLTools.java
===================================================================
--- AE/installer2/src/net/oni2/aeinstaller/backend/oni/XMLTools.java	(revision 708)
+++ AE/installer2/src/net/oni2/aeinstaller/backend/oni/XMLTools.java	(revision 720)
@@ -6,8 +6,9 @@
 
 import net.oni2.aeinstaller.backend.CaseInsensitiveFile;
-import net.oni2.aeinstaller.backend.DotNet;
 import net.oni2.aeinstaller.backend.Paths;
-import net.oni2.applicationinvoker.AppExecution;
-import net.oni2.applicationinvoker.AppExecutionResult;
+import net.oni2.platformtools.applicationinvoker.ApplicationInvoker;
+import net.oni2.platformtools.applicationinvoker.ApplicationInvocationResult;
+import net.oni2.platformtools.applicationinvoker.EExeType;
+import net.oni2.platformtools.applicationinvoker.ERuntimeNotInstalledException;
 
 /**
@@ -26,14 +27,17 @@
 	 * @return XMLTools output
 	 */
-	public static AppExecutionResult patch(File patch, File source) {
-		Vector<String> cmdLine = getProgramInvocation();
+	public static ApplicationInvocationResult patch(File patch, File source) {
+		Vector<String> params = new Vector<String>();
 		// xmlTools.exe patchfile -filename:PATCH -forceinfiles:TOPATCH
-		cmdLine.add("patchfile");
-		cmdLine.add("-filename:" + patch.getPath());
-		cmdLine.add("-forceinfiles:" + source.getPath());
-		AppExecutionResult res = null;
+		params.add("patchfile");
+		params.add("-filename:" + patch.getPath());
+		params.add("-forceinfiles:" + source.getPath());
+		ApplicationInvocationResult res = null;
 		try {
-			res = AppExecution.executeAndWait(cmdLine);
+			res = ApplicationInvoker.executeAndWait(EExeType.DOTNET, null,
+					getProgramFile(), params);
 		} catch (IOException e) {
+			e.printStackTrace();
+		} catch (ERuntimeNotInstalledException e) {
 			e.printStackTrace();
 		}
@@ -41,15 +45,9 @@
 	}
 
-	private static Vector<String> getProgramInvocation() {
-		Vector<String> res = new Vector<String>();
-		if (DotNet.getRuntimeExe().length() > 0)
-			res.add(DotNet.getRuntimeExe());
-		res.add(getProgramFile().getPath());
-		return res;
-	}
-
 	private static File getProgramFile() {
-		File toolsPath = CaseInsensitiveFile.getCaseInsensitiveFile(Paths.getEditionBasePath(), "Tools");
-		return CaseInsensitiveFile.getCaseInsensitiveFile(toolsPath, "xmlTools.exe");
+		File toolsPath = CaseInsensitiveFile.getCaseInsensitiveFile(
+				Paths.getEditionBasePath(), "Tools");
+		return CaseInsensitiveFile.getCaseInsensitiveFile(toolsPath,
+				"xmlTools.exe");
 	}
 }
