diff --git a/CreamInstaller/CreamInstaller.csproj b/CreamInstaller/CreamInstaller.csproj
index 2659c7b..6a1a5ea 100644
--- a/CreamInstaller/CreamInstaller.csproj
+++ b/CreamInstaller/CreamInstaller.csproj
@@ -24,6 +24,7 @@
pointfeev
pointfeev.creaminstaller
CreamInstaller.Program
+ false
@@ -38,11 +39,11 @@
-
+
-
+
@@ -51,8 +52,8 @@
-
-
+
+
True
True
diff --git a/CreamInstaller/CustomMessageException.cs b/CreamInstaller/CustomMessageException.cs
deleted file mode 100644
index d42b3b4..0000000
--- a/CreamInstaller/CustomMessageException.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using System;
-
-namespace CreamInstaller
-{
- public class CustomMessageException : Exception
- {
- private string message;
- public override string Message => message ?? "CustomMessageException";
-
- public override string ToString() => Message;
-
- public CustomMessageException(string message)
- {
- this.message = message;
- }
- }
-}
\ No newline at end of file
diff --git a/CreamInstaller/ExceptionHandler.cs b/CreamInstaller/ExceptionHandler.cs
new file mode 100644
index 0000000..b3fdfce
--- /dev/null
+++ b/CreamInstaller/ExceptionHandler.cs
@@ -0,0 +1,55 @@
+using System;
+using System.Windows.Forms;
+
+namespace CreamInstaller
+{
+ public static class ExceptionHandler
+ {
+ public static bool OutputException(Exception e)
+ {
+ while (!(e.InnerException is null)) e = e.InnerException;
+ string output = "";
+ string[] stackTrace = e.StackTrace?.Split('\n');
+ if (!(stackTrace is null) && stackTrace.Length > 0)
+ {
+ output += "STACK TRACE\n";
+ for (int i = 0; i < Math.Min(stackTrace.Length, 3); i++)
+ {
+ string line = stackTrace[i];
+ if (!(line is null))
+ {
+ output += "\n " + line.Substring(line.IndexOf("at"));
+ }
+ }
+ }
+ string[] messageLines = e.Message?.Split('\n');
+ if (!(messageLines is null) && messageLines.Length > 0)
+ {
+ if (output.Length > 0) output += "\n\n";
+ output += "MESSAGE\n";
+ for (int i = 0; i < messageLines.Length; i++)
+ {
+ string line = messageLines[i];
+ if (!(line is null))
+ {
+ output += "\n " + messageLines[i];
+ }
+ }
+ }
+ return MessageBox.Show(output, caption: "CreamInstaller encountered an exception", buttons: MessageBoxButtons.RetryCancel, icon: MessageBoxIcon.Error) == DialogResult.Retry;
+ }
+ }
+
+ public class CustomMessageException : Exception
+ {
+ private string message;
+ public override string Message => message ?? "CustomMessageException";
+
+ public override string ToString() => Message;
+
+ public CustomMessageException(string message)
+ {
+ this.message = message;
+ }
+ }
+}
diff --git a/CreamInstaller/DialogForm.Designer.cs b/CreamInstaller/Forms/DialogForm.Designer.cs
similarity index 100%
rename from CreamInstaller/DialogForm.Designer.cs
rename to CreamInstaller/Forms/DialogForm.Designer.cs
diff --git a/CreamInstaller/DialogForm.cs b/CreamInstaller/Forms/DialogForm.cs
similarity index 100%
rename from CreamInstaller/DialogForm.cs
rename to CreamInstaller/Forms/DialogForm.cs
diff --git a/CreamInstaller/DialogForm.resx b/CreamInstaller/Forms/DialogForm.resx
similarity index 100%
rename from CreamInstaller/DialogForm.resx
rename to CreamInstaller/Forms/DialogForm.resx
diff --git a/CreamInstaller/InstallForm.Designer.cs b/CreamInstaller/Forms/InstallForm.Designer.cs
similarity index 100%
rename from CreamInstaller/InstallForm.Designer.cs
rename to CreamInstaller/Forms/InstallForm.Designer.cs
diff --git a/CreamInstaller/InstallForm.cs b/CreamInstaller/Forms/InstallForm.cs
similarity index 100%
rename from CreamInstaller/InstallForm.cs
rename to CreamInstaller/Forms/InstallForm.cs
diff --git a/CreamInstaller/InstallForm.resx b/CreamInstaller/Forms/InstallForm.resx
similarity index 100%
rename from CreamInstaller/InstallForm.resx
rename to CreamInstaller/Forms/InstallForm.resx
diff --git a/CreamInstaller/MainForm.Designer.cs b/CreamInstaller/Forms/MainForm.Designer.cs
similarity index 100%
rename from CreamInstaller/MainForm.Designer.cs
rename to CreamInstaller/Forms/MainForm.Designer.cs
diff --git a/CreamInstaller/MainForm.cs b/CreamInstaller/Forms/MainForm.cs
similarity index 100%
rename from CreamInstaller/MainForm.cs
rename to CreamInstaller/Forms/MainForm.cs
diff --git a/CreamInstaller/MainForm.resx b/CreamInstaller/Forms/MainForm.resx
similarity index 100%
rename from CreamInstaller/MainForm.resx
rename to CreamInstaller/Forms/MainForm.resx
diff --git a/CreamInstaller/SelectForm.Designer.cs b/CreamInstaller/Forms/SelectForm.Designer.cs
similarity index 100%
rename from CreamInstaller/SelectForm.Designer.cs
rename to CreamInstaller/Forms/SelectForm.Designer.cs
diff --git a/CreamInstaller/SelectForm.cs b/CreamInstaller/Forms/SelectForm.cs
similarity index 92%
rename from CreamInstaller/SelectForm.cs
rename to CreamInstaller/Forms/SelectForm.cs
index 76bd106..50875c6 100644
--- a/CreamInstaller/SelectForm.cs
+++ b/CreamInstaller/Forms/SelectForm.cs
@@ -2,6 +2,7 @@
using Gameloop.Vdf.Linq;
using Microsoft.Win32;
using System;
+using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
@@ -75,7 +76,7 @@ namespace CreamInstaller
return true;
}
- private bool GetGamesFromLibraryDirectory(string libraryDirectory, out List> games)
+ private bool GetGamesFromLibraryDirectory(string libraryDirectory, out List> games)
{
games = new();
if (Program.Canceled) return false;
@@ -91,14 +92,16 @@ namespace CreamInstaller
string installdir = property.Value.installdir.ToString();
string name = property.Value.name.ToString();
string _buildid = property.Value.buildid.ToString();
- if (string.IsNullOrWhiteSpace(_appid)
+ if (string.IsNullOrWhiteSpace(_appid)
|| string.IsNullOrWhiteSpace(installdir)
|| string.IsNullOrWhiteSpace(name)
|| string.IsNullOrWhiteSpace(_buildid)) continue;
- string gameDirectory = libraryDirectory + @"\common\" + installdir;
+ string branch = property.Value.UserConfig?.betakey?.ToString();
+ if (string.IsNullOrWhiteSpace(branch)) branch = "public";
+ string gameDirectory = libraryDirectory + @"\common\" + installdir;
if (!int.TryParse(_appid, out int appid)) continue;
if (!int.TryParse(_buildid, out int buildid)) continue;
- games.Add(new(appid, name, buildid, gameDirectory));
+ games.Add(new(appid, name, branch, buildid, gameDirectory));
}
catch {}
}
@@ -109,46 +112,39 @@ namespace CreamInstaller
private readonly List treeNodes = new();
- internal readonly Dictionary> DLC = new();
-
- internal List RunningTasks = null;
+ internal List RunningTasks = new();
private void GetCreamApiApplicablePrograms(IProgress progress)
{
int cur = 0;
if (Program.Canceled) return;
- List> applicablePrograms = new();
+ List> applicablePrograms = new();
string launcherRootDirectory = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\\Programs\\Paradox Interactive";
- if (Directory.Exists(launcherRootDirectory)) applicablePrograms.Add(new(0, "Paradox Launcher", 0, launcherRootDirectory));
+ if (Directory.Exists(launcherRootDirectory)) applicablePrograms.Add(new(0, "Paradox Launcher", "", 0, launcherRootDirectory));
foreach (string libraryDirectory in GameLibraryDirectories)
- if (GetGamesFromLibraryDirectory(libraryDirectory, out List> games))
- foreach (Tuple game in games)
+ if (GetGamesFromLibraryDirectory(libraryDirectory, out List> games))
+ foreach (Tuple game in games)
applicablePrograms.Add(game);
- RunningTasks = new();
- foreach (Tuple program in applicablePrograms)
+ RunningTasks.Clear();
+ foreach (Tuple program in applicablePrograms)
{
int appId = program.Item1;
string name = program.Item2;
- int buildId = program.Item3;
- string directory = program.Item4;
+ string branch = program.Item3;
+ int buildId = program.Item4;
+ string directory = program.Item5;
if (Program.Canceled) return;
// easy anti cheat detects DLL changes, so skip those games
if (Directory.Exists(directory + @"\EasyAntiCheat")) continue;
// battleye in DayZ detects DLL changes, but not in Arma3?
- //if (Directory.Exists(directory + @"\BattlEye")) continue;
- if (name == "DayZ") continue;
+ if (name != "Arma 3" && Directory.Exists(directory + @"\BattlEye")) continue;
Task task = new(() =>
{
if (Program.Canceled || !GetDllDirectoriesFromGameDirectory(directory, out List dllDirectories)) return;
VProperty appInfo = null;
- if (Program.Canceled || (name != "Paradox Launcher" && !SteamCMD.GetAppInfo(appId, buildId, out appInfo))) return;
- Dictionary dlc = null;
- if (!DLC.TryGetValue(appId, out dlc))
- {
- dlc = new();
- DLC.Add(appId, dlc);
- }
+ if (Program.Canceled || (name != "Paradox Launcher" && !SteamCMD.GetAppInfo(appId, out appInfo, branch, buildId))) return;
if (Program.Canceled) return;
+ ConcurrentDictionary dlc = new();
List dlcTasks = new();
List dlcIds = new();
if (!(appInfo is null))
@@ -175,9 +171,9 @@ namespace CreamInstaller
if (Program.Canceled) return;
string dlcName = null;
VProperty dlcAppInfo = null;
- if (SteamCMD.GetAppInfo(id, 0, out dlcAppInfo)) dlcName = dlcAppInfo?.Value?["common"]?["name"]?.ToString();
+ if (SteamCMD.GetAppInfo(id, out dlcAppInfo)) dlcName = dlcAppInfo?.Value?["common"]?["name"]?.ToString();
if (Program.Canceled) return;
- if (string.IsNullOrWhiteSpace(dlcName)) dlcName = $"Unnamed DLC ({id})";
+ if (string.IsNullOrWhiteSpace(dlcName)) dlcName = $"Unknown DLC ({id})";
dlc[id] = dlcName;
});
dlcTasks.Add(task);
diff --git a/CreamInstaller/SelectForm.resx b/CreamInstaller/Forms/SelectForm.resx
similarity index 100%
rename from CreamInstaller/SelectForm.resx
rename to CreamInstaller/Forms/SelectForm.resx
diff --git a/CreamInstaller/Program.cs b/CreamInstaller/Program.cs
index e847bcf..6ce1ad4 100644
--- a/CreamInstaller/Program.cs
+++ b/CreamInstaller/Program.cs
@@ -29,7 +29,15 @@ namespace CreamInstaller
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.ApplicationExit += new EventHandler(OnApplicationExit);
- Application.Run(new MainForm());
+ retry:
+ try
+ {
+ Application.Run(new MainForm());
+ }
+ catch (Exception e)
+ {
+ if (ExceptionHandler.OutputException(e)) goto retry;
+ }
}
mutex.Close();
}
diff --git a/CreamInstaller/Resources.cs b/CreamInstaller/Resources/Resources.cs
similarity index 84%
rename from CreamInstaller/Resources.cs
rename to CreamInstaller/Resources/Resources.cs
index cfaf885..59f7ba3 100644
--- a/CreamInstaller/Resources.cs
+++ b/CreamInstaller/Resources/Resources.cs
@@ -7,7 +7,7 @@ namespace CreamInstaller
{
public static void WriteResourceToFile(string resourceName, string filePath)
{
- using Stream resource = Assembly.GetExecutingAssembly().GetManifestResourceStream("CreamInstaller." + resourceName);
+ using Stream resource = Assembly.GetExecutingAssembly().GetManifestResourceStream(@"CreamInstaller.Resources." + resourceName);
using FileStream file = new(filePath, FileMode.Create, FileAccess.Write);
resource.CopyTo(file);
}
diff --git a/CreamInstaller/steam_api.dll b/CreamInstaller/Resources/steam_api.dll
similarity index 100%
rename from CreamInstaller/steam_api.dll
rename to CreamInstaller/Resources/steam_api.dll
diff --git a/CreamInstaller/steam_api64.dll b/CreamInstaller/Resources/steam_api64.dll
similarity index 100%
rename from CreamInstaller/steam_api64.dll
rename to CreamInstaller/Resources/steam_api64.dll
diff --git a/CreamInstaller/SteamCMD.cs b/CreamInstaller/SteamCMD.cs
index ffd7e2f..969ad02 100644
--- a/CreamInstaller/SteamCMD.cs
+++ b/CreamInstaller/SteamCMD.cs
@@ -1,5 +1,6 @@
using Gameloop.Vdf;
using Gameloop.Vdf.Linq;
+using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
@@ -15,7 +16,9 @@ namespace CreamInstaller
public static string FilePath = DirectoryPath + @"\steamcmd.exe";
public static string ArchivePath = DirectoryPath + @"\steamcmd.zip";
public static string DllPath = DirectoryPath + @"\steamclient.dll";
- public static string AppInfoCachePath = DirectoryPath + @"\appinfocache";
+ public static string AppCachePath = DirectoryPath + @"\appcache";
+ public static string AppCacheAppInfoPath = AppCachePath + @"\appinfo.vdf";
+ public static string AppInfoPath = DirectoryPath + @"\appinfo";
public static bool Run(string command, out string output)
{
@@ -52,16 +55,18 @@ namespace CreamInstaller
ZipFile.ExtractToDirectory(ArchivePath, DirectoryPath);
File.Delete(ArchivePath);
}
+ if (File.Exists(AppCacheAppInfoPath)) File.Delete(AppCacheAppInfoPath);
if (!File.Exists(DllPath)) Run($@"+quit", out _);
}
- public static bool GetAppInfo(int appId, int buildId, out VProperty appInfo)
+ public static bool GetAppInfo(int appId, out VProperty appInfo, string branch = "public", int buildId = 0)
{
appInfo = null;
if (Program.Canceled) return false;
string output;
- string appUpdatePath = $@"{AppInfoCachePath}\{appId}";
+ string appUpdatePath = $@"{AppInfoPath}\{appId}";
string appUpdateFile = $@"{appUpdatePath}\appinfo.txt";
+ restart:
if (Directory.Exists(appUpdatePath) && File.Exists(appUpdateFile)) output = File.ReadAllText(appUpdateFile);
else
{
@@ -76,18 +81,26 @@ namespace CreamInstaller
}
}
if (Program.Canceled || output is null) return false;
- try { appInfo = VdfConvert.Deserialize(output); } catch { }
+ try { appInfo = VdfConvert.Deserialize(output); }
+ catch
+ {
+ if (File.Exists(appUpdateFile))
+ {
+ File.Delete(appUpdateFile);
+ goto restart;
+ }
+ }
+ if (!(appInfo is null) && appInfo.Value is VValue) goto restart;
if (appInfo is null || (!(appInfo.Value is VValue) && appInfo.Value.Children().ToList().Count == 0)) return true;
VToken type = appInfo.Value is VValue ? null : appInfo.Value?["common"]?["type"];
if (type is null || type.ToString() == "Game")
{
- string buildid = appInfo.Value is VValue ? null : appInfo.Value["depots"]?["public"]?["buildid"]?.ToString();
+ string buildid = appInfo.Value is VValue ? null : appInfo.Value["depots"]?["branches"]?[branch]?["buildid"]?.ToString();
if (buildid is null && !(type is null)) return true;
if (type is null || int.Parse(buildid) < buildId)
{
- File.Delete(appUpdateFile);
- bool success = GetAppInfo(appId, buildId, out appInfo);
- return success;
+ if (File.Exists(appUpdateFile)) File.Delete(appUpdateFile);
+ goto restart;
}
}
return true;