mirror of
https://github.com/FroggMaster/CreamInstaller.git
synced 2026-07-28 14:47:04 -07:00
Further Enhancements to Recall Games Installed With DLC Unlockers
- Rename JSON Proxy field to "Proxy DLL Name" and always store the resolved name instead of null for default convention - Add DetectInstalledProxy() to find proxy dlls winmm/winhttp/version.dll - Fixes to ensure all detected unlockers are persisted in installed.json on scan so pre-existing unlockers are tracked even if not installed via CreamInstaller - Restore proxy and extra protection state from saved records for both scanned and previously scanned games on reload - Detect proxy DLLs from disk for previously scanned game reconstruction
This commit is contained in:
@@ -371,7 +371,7 @@ internal sealed partial class InstallForm : CustomForm
|
|||||||
RootDirectory = selection.RootDirectory,
|
RootDirectory = selection.RootDirectory,
|
||||||
Unlocker = unlocker,
|
Unlocker = unlocker,
|
||||||
UseProxy = selection.UseProxy,
|
UseProxy = selection.UseProxy,
|
||||||
Proxy = selection.Proxy,
|
ProxyDllName = selection.UseProxy ? selection.Proxy ?? Selection.DefaultProxy : null,
|
||||||
UseExtraProtection = selection.UseExtraProtection,
|
UseExtraProtection = selection.UseExtraProtection,
|
||||||
Dlc = selection.DLC.Select(dlc => new InstalledDlcRecord
|
Dlc = selection.DLC.Select(dlc => new InstalledDlcRecord
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1111,16 +1111,23 @@ internal sealed partial class SelectForm : CustomForm
|
|||||||
List<InstalledGameRecord> toRemove = [];
|
List<InstalledGameRecord> toRemove = [];
|
||||||
foreach (InstalledGameRecord record in saved)
|
foreach (InstalledGameRecord record in saved)
|
||||||
{
|
{
|
||||||
// Already in the list from this scan — just ensure unlocker is set
|
// Already in the list from this scan; ensure unlocker, proxy, and extra protection are set
|
||||||
Selection existing = Selection.FromId(record.Platform, record.Id);
|
Selection existing = Selection.FromId(record.Platform, record.Id);
|
||||||
if (existing is not null)
|
if (existing is not null)
|
||||||
{
|
{
|
||||||
if (existing.InstalledUnlocker == InstalledUnlocker.None)
|
if (existing.InstalledUnlocker == InstalledUnlocker.None)
|
||||||
existing.InstalledUnlocker = record.Unlocker;
|
existing.InstalledUnlocker = record.Unlocker;
|
||||||
|
if (record.UseProxy)
|
||||||
|
{
|
||||||
|
existing.UseProxy = true;
|
||||||
|
existing.Proxy = record.ProxyDllName;
|
||||||
|
}
|
||||||
|
if (record.UseExtraProtection)
|
||||||
|
existing.UseExtraProtection = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Root directory no longer exists — mark for removal
|
// Root directory no longer exists mark for removal
|
||||||
if (!record.RootDirectory.DirectoryExists())
|
if (!record.RootDirectory.DirectoryExists())
|
||||||
{
|
{
|
||||||
toRemove.Add(record);
|
toRemove.Add(record);
|
||||||
@@ -1144,8 +1151,20 @@ internal sealed partial class SelectForm : CustomForm
|
|||||||
selection.InstalledUnlocker = selection.DetectInstalledUnlocker();
|
selection.InstalledUnlocker = selection.DetectInstalledUnlocker();
|
||||||
if (selection.InstalledUnlocker == InstalledUnlocker.None)
|
if (selection.InstalledUnlocker == InstalledUnlocker.None)
|
||||||
selection.InstalledUnlocker = record.Unlocker;
|
selection.InstalledUnlocker = record.Unlocker;
|
||||||
selection.UseProxy = record.UseProxy;
|
if (selection.InstalledUnlocker != InstalledUnlocker.None)
|
||||||
selection.Proxy = record.Proxy;
|
{
|
||||||
|
string detectedProxy = selection.DetectInstalledProxy();
|
||||||
|
if (detectedProxy is not null)
|
||||||
|
{
|
||||||
|
selection.UseProxy = true;
|
||||||
|
selection.Proxy = detectedProxy;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
selection.UseProxy = record.UseProxy;
|
||||||
|
selection.Proxy = record.ProxyDllName;
|
||||||
|
}
|
||||||
|
}
|
||||||
selection.UseExtraProtection = record.UseExtraProtection;
|
selection.UseExtraProtection = record.UseExtraProtection;
|
||||||
|
|
||||||
Invoke(delegate
|
Invoke(delegate
|
||||||
@@ -1382,9 +1401,20 @@ internal sealed partial class SelectForm : CustomForm
|
|||||||
ProgramData.WriteExtraProtectionChoices(extraProtectionChoices);
|
ProgramData.WriteExtraProtectionChoices(extraProtectionChoices);
|
||||||
loadButton.Enabled = CanLoadSelections();
|
loadButton.Enabled = CanLoadSelections();
|
||||||
|
|
||||||
// Detect installed unlockers from disk for all selections
|
// Detect installed unlockers and proxy DLLs from disk for all selections
|
||||||
foreach (Selection selection in Selection.All.Keys)
|
foreach (Selection selection in Selection.All.Keys)
|
||||||
|
{
|
||||||
selection.InstalledUnlocker = selection.DetectInstalledUnlocker();
|
selection.InstalledUnlocker = selection.DetectInstalledUnlocker();
|
||||||
|
if (selection.InstalledUnlocker != InstalledUnlocker.None)
|
||||||
|
{
|
||||||
|
string detectedProxy = selection.DetectInstalledProxy();
|
||||||
|
if (detectedProxy is not null)
|
||||||
|
{
|
||||||
|
selection.UseProxy = true;
|
||||||
|
selection.Proxy = detectedProxy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Merge with persisted installed game records for any saved games not yet having a detected unlocker
|
// Merge with persisted installed game records for any saved games not yet having a detected unlocker
|
||||||
List<InstalledGameRecord> installedRecords = ProgramData.ReadInstalledGames();
|
List<InstalledGameRecord> installedRecords = ProgramData.ReadInstalledGames();
|
||||||
@@ -1397,11 +1427,14 @@ internal sealed partial class SelectForm : CustomForm
|
|||||||
selection.InstalledUnlocker = record.Unlocker;
|
selection.InstalledUnlocker = record.Unlocker;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Persist all selections with a detected DLC unlocker to installed.json, so they are tracked
|
// Persist any selections with a detected unlocker to installed.json, preserving existing
|
||||||
// even when the unlocker was installed outside of CreamInstaller
|
// proxy/extrapolation data from the saved record so detection does not overwrite prior install state
|
||||||
foreach (Selection selection in Selection.All.Keys)
|
foreach (Selection selection in Selection.All.Keys)
|
||||||
{
|
{
|
||||||
if (selection.InstalledUnlocker != InstalledUnlocker.None)
|
if (selection.InstalledUnlocker != InstalledUnlocker.None)
|
||||||
|
{
|
||||||
|
InstalledGameRecord existing = installedRecords.FirstOrDefault(r =>
|
||||||
|
r.Platform == selection.Platform && r.Id == selection.Id);
|
||||||
ProgramData.UpsertInstalledGame(new InstalledGameRecord
|
ProgramData.UpsertInstalledGame(new InstalledGameRecord
|
||||||
{
|
{
|
||||||
Platform = selection.Platform,
|
Platform = selection.Platform,
|
||||||
@@ -1409,9 +1442,9 @@ internal sealed partial class SelectForm : CustomForm
|
|||||||
Name = selection.Name,
|
Name = selection.Name,
|
||||||
RootDirectory = selection.RootDirectory,
|
RootDirectory = selection.RootDirectory,
|
||||||
Unlocker = selection.InstalledUnlocker,
|
Unlocker = selection.InstalledUnlocker,
|
||||||
UseProxy = selection.UseProxy,
|
UseProxy = existing?.UseProxy ?? false,
|
||||||
Proxy = selection.Proxy,
|
ProxyDllName = existing?.UseProxy == true ? existing.ProxyDllName : null,
|
||||||
UseExtraProtection = selection.UseExtraProtection,
|
UseExtraProtection = existing?.UseExtraProtection ?? false,
|
||||||
Dlc = selection.DLC.Select(dlc => new InstalledDlcRecord
|
Dlc = selection.DLC.Select(dlc => new InstalledDlcRecord
|
||||||
{
|
{
|
||||||
DlcType = dlc.Type.ToString(),
|
DlcType = dlc.Type.ToString(),
|
||||||
@@ -1419,6 +1452,7 @@ internal sealed partial class SelectForm : CustomForm
|
|||||||
Name = dlc.Name
|
Name = dlc.Name
|
||||||
}).ToList()
|
}).ToList()
|
||||||
});
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
OnProxyChanged();
|
OnProxyChanged();
|
||||||
|
|||||||
@@ -163,7 +163,7 @@ internal sealed class Selection : IEquatable<Selection>
|
|||||||
return InstalledUnlocker.CreamAPI;
|
return InstalledUnlocker.CreamAPI;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fallback: config was deleted but _o files remain — identify by replacement DLL content
|
// Fallback: config was deleted but _o files remain identify by replacement DLL content
|
||||||
directory.GetSmokeApiComponents(out string smokeApi32, out string api32_o,
|
directory.GetSmokeApiComponents(out string smokeApi32, out string api32_o,
|
||||||
out string smokeApi64, out string api64_o, out _, out _, out _, out _, out _);
|
out string smokeApi64, out string api64_o, out _, out _, out _, out _, out _);
|
||||||
if (api32_o.FileExists() || api64_o.FileExists())
|
if (api32_o.FileExists() || api64_o.FileExists())
|
||||||
@@ -226,6 +226,19 @@ internal sealed class Selection : IEquatable<Selection>
|
|||||||
return InstalledUnlocker.None;
|
return InstalledUnlocker.None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal string DetectInstalledProxy()
|
||||||
|
{
|
||||||
|
HashSet<string> knownProxies = ["winmm", "winhttp", "version"];
|
||||||
|
foreach (string directory in DllDirectories)
|
||||||
|
foreach (string proxy in knownProxies)
|
||||||
|
{
|
||||||
|
string proxyPath = directory + @"\" + proxy + ".dll";
|
||||||
|
if (proxyPath.FileExists())
|
||||||
|
return proxy;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private void ReadCreamApiConfig(string configPath)
|
private void ReadCreamApiConfig(string configPath)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|||||||
@@ -37,7 +37,10 @@ internal sealed class InstalledGameRecord
|
|||||||
public string RootDirectory { get; set; }
|
public string RootDirectory { get; set; }
|
||||||
public InstalledUnlocker Unlocker { get; set; }
|
public InstalledUnlocker Unlocker { get; set; }
|
||||||
public bool UseProxy { get; set; }
|
public bool UseProxy { get; set; }
|
||||||
public string Proxy { get; set; }
|
|
||||||
|
[JsonProperty("Proxy DLL Name")]
|
||||||
|
public string ProxyDllName { get; set; }
|
||||||
|
|
||||||
public bool UseExtraProtection { get; set; }
|
public bool UseExtraProtection { get; set; }
|
||||||
public List<InstalledDlcRecord> Dlc { get; set; } = [];
|
public List<InstalledDlcRecord> Dlc { get; set; } = [];
|
||||||
}
|
}
|
||||||
@@ -84,7 +87,7 @@ internal static event Action<string> OnLogError;
|
|||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
// ignored — logging must never crash the application
|
// ignored; logging must never crash the application
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,7 +102,7 @@ internal static event Action<string> OnLogError;
|
|||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
// ignored — logging must never crash the application
|
// ignored; logging must never crash the application
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,7 +117,7 @@ internal static event Action<string> OnLogError;
|
|||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
// ignored — logging must never crash the application
|
// ignored; logging must never crash the application
|
||||||
}
|
}
|
||||||
OnLogWarning?.Invoke(message);
|
OnLogWarning?.Invoke(message);
|
||||||
}
|
}
|
||||||
@@ -132,7 +135,7 @@ internal static event Action<string> OnLogError;
|
|||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
// ignored — logging must never crash the application
|
// ignored; logging must never crash the application
|
||||||
}
|
}
|
||||||
OnLogError?.Invoke(message);
|
OnLogError?.Invoke(message);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user