// return value // -1 = not implemented // 0 = failure // 1 = success public static int InstallGame(CGame game) { //CDock.DeleteCustomImage(game.Title); //bool useEGL = (bool)CConfig.GetConfigBool(CConfig.CFG_USEEGL); bool useLeg = (bool)CConfig.GetConfigBool(CConfig.CFG_USELEG); string pathLeg = CConfig.GetConfigString(CConfig.CFG_PATHLEG); if (string.IsNullOrEmpty(pathLeg)) { useLeg = false; } if (!pathLeg.Contains(@"\") && !pathLeg.Contains("/")) // legendary.exe in current directory { pathLeg = Path.Combine(Directory.GetCurrentDirectory(), pathLeg); } if (useLeg && File.Exists(pathLeg)) { if (OperatingSystem.IsWindows()) { CLogger.LogInfo($"Launch: cmd.exe /c \"" + pathLeg + "\" -y install " + game.ID); CDock.StartAndRedirect("cmd.exe", "/c '\"" + pathLeg + "\" -y install " + game.ID); } else { CLogger.LogInfo($"Launch: " + pathLeg + " -y install " + game.ID); Process.Start(pathLeg, "-y install " + game.ID); } return(1); } else //if (useEGL) { if (OperatingSystem.IsWindows()) { CDock.StartShellExecute(START_GAME + game.ID + INSTALL_GAME_ARGS); } else { Process.Start(START_GAME + game.ID + INSTALL_GAME_ARGS); } return(1); } //return 0; }
public static void StartGame(CGame game) { bool useEGL = (bool)CConfig.GetConfigBool(CConfig.CFG_USEEGL); bool useLeg = (bool)CConfig.GetConfigBool(CConfig.CFG_USELEG); bool syncLeg = (bool)CConfig.GetConfigBool(CConfig.CFG_SYNCLEG); string pathLeg = CConfig.GetConfigString(CConfig.CFG_PATHLEG); if (string.IsNullOrEmpty(pathLeg)) { useLeg = false; } if (!pathLeg.Contains(@"\") && !pathLeg.Contains("/")) // legendary.exe in current directory { pathLeg = Path.Combine(Directory.GetCurrentDirectory(), pathLeg); } if (useLeg && File.Exists(pathLeg)) { if (OperatingSystem.IsWindows()) { string cmdLine = "\"" + pathLeg + "\" -y launch " + game.ID; CLogger.LogInfo($"Launch: cmd.exe /c " + cmdLine); if (syncLeg) { cmdLine = "\"" + pathLeg + "\" -y sync-saves " + game.ID + " & " + cmdLine + " & \"" + pathLeg + "\" -y sync-saves " + game.ID; } CDock.StartAndRedirect("cmd.exe", "/c '" + cmdLine + " '"); } else { CLogger.LogInfo($"Launch: " + pathLeg + " -y launch " + game.ID); if (syncLeg) { Process.Start(pathLeg, "-y sync-saves " + game.ID); } Process.Start(pathLeg, "-y launch " + game.ID); if (syncLeg) { Process.Start(pathLeg, "-y sync-saves " + game.ID); } } } else if (useEGL) { if (OperatingSystem.IsWindows()) { CDock.StartShellExecute(START_GAME + game.ID + START_GAME_ARGS); } else { Process.Start(PROTOCOL + START_GAME + game.ID + START_GAME_ARGS); } } else { if (OperatingSystem.IsWindows()) { CDock.StartShellExecute(game.Launch); } else { Process.Start(game.Launch); } } }
// return value // -1 = not implemented // 0 = failure // 1 = success public static int UninstallGame(CGame game) { //bool useEGL = (bool)CConfig.GetConfigBool(CConfig.CFG_USEEGL); bool useLeg = (bool)CConfig.GetConfigBool(CConfig.CFG_USELEG); string pathLeg = CConfig.GetConfigString(CConfig.CFG_PATHLEG); if (string.IsNullOrEmpty(pathLeg)) { useLeg = false; } if (!pathLeg.Contains(@"\") && !pathLeg.Contains("/")) // legendary.exe in current directory { pathLeg = Path.Combine(Directory.GetCurrentDirectory(), pathLeg); } if (useLeg && File.Exists(pathLeg)) { //Process ps; if (OperatingSystem.IsWindows()) { CLogger.LogInfo("Launch: cmd.exe /c \"" + pathLeg + "\" -y uninstall " + game.ID); CDock.StartAndRedirect("cmd.exe", "/c \"" + pathLeg + "\" -y uninstall " + game.ID); } else { CLogger.LogInfo("Launch: " + pathLeg + " -y uninstall " + game.ID); Process.Start(pathLeg, "-y uninstall " + game.ID); } /* * ps.WaitForExit(30000); * if (ps.ExitCode == 0) */ return(1); } /* * else if (useEGL) * { * Launch(); * return -1; * } */ else if (!string.IsNullOrEmpty(game.Uninstaller)) { // delete Desktop icon File.Delete(Path.Combine(GetFolderPath(SpecialFolder.Desktop), game.Title + ".lnk")); string[] un = game.Uninstaller.Split(';'); // delete manifest file if (un.Length > 1 && !string.IsNullOrEmpty(un[1]) && un[1].EndsWith(".item")) { File.Delete(Path.Combine(GetFolderPath(SpecialFolder.CommonApplicationData), EPIC_ITEMS, un[1])); } if (un.Length > 0 && !string.IsNullOrEmpty(un[0]) && !un[0].EndsWith(".item")) { DirectoryInfo rootDir = new(un[0]); if (rootDir.Exists) { /* * foreach (DirectoryInfo dir in rootDir.EnumerateDirectories()) * dir.Delete(true); * foreach (FileInfo file in rootDir.EnumerateFiles()) * file.Delete(); */ rootDir.Delete(true); return(1); } } } return(0); }
public void GetGames(List <ImportGameData> gameDataList, bool expensiveIcons = false) { List <string> epicIds = new(); string strPlatform = GetPlatformString(ENUM); string dir = Path.Combine(GetFolderPath(SpecialFolder.CommonApplicationData), EPIC_ITEMS); if (!Directory.Exists(dir)) { CLogger.LogInfo("{0} games not found in ProgramData.", _name.ToUpper()); return; } string[] files = Directory.GetFiles(dir, "*.item", SearchOption.TopDirectoryOnly); CLogger.LogInfo("{0} {1} games found", files.Length, _name.ToUpper()); foreach (string file in files) { string strDocumentData = File.ReadAllText(file); if (string.IsNullOrEmpty(strDocumentData)) { continue; } try { using JsonDocument document = JsonDocument.Parse(@strDocumentData, jsonTrailingCommas); string strID = GetStringProperty(document.RootElement, "AppName"); if (string.IsNullOrEmpty(strID)) { strID = Path.GetFileName(file); } string strTitle = GetStringProperty(document.RootElement, "DisplayName"); CLogger.LogDebug($"- {strTitle}"); string strLaunch = GetStringProperty(document.RootElement, "LaunchExecutable"); // DLCs won't have this set string strUninstall = ""; string strAlias = ""; if (!string.IsNullOrEmpty(strLaunch)) { epicIds.Add(strID); strUninstall = GetStringProperty(document.RootElement, "InstallLocation"); strLaunch = Path.Combine(strUninstall, strLaunch); strUninstall += ";" + Path.GetFileName(file); // rather than an uninstaller like most platforms, for Epic, strUninstall holds two fields: the install location and the manifest file strAlias = GetAlias(GetStringProperty(document.RootElement, "MandatoryAppFolderName")); if (strAlias.Length > strTitle.Length) { strAlias = GetAlias(strTitle); } if (strAlias.Equals(strTitle, CDock.IGNORE_CASE)) { strAlias = ""; } gameDataList.Add(new ImportGameData(strID, strTitle, strLaunch, strLaunch, strUninstall, strAlias, true, strPlatform)); } } catch (Exception e) { CLogger.LogError(e, string.Format("Malformed {0} file: {1}", _name.ToUpper(), file)); } } // Get not-installed games (requires Legendary) if (!(bool)CConfig.GetConfigBool(CConfig.CFG_INSTONLY)) { bool useLeg = (bool)CConfig.GetConfigBool(CConfig.CFG_USELEG); string pathLeg = CConfig.GetConfigString(CConfig.CFG_PATHLEG); if (string.IsNullOrEmpty(pathLeg)) { useLeg = false; } if (!pathLeg.Contains(@"\") && !pathLeg.Contains("/")) // legendary.exe in current directory { pathLeg = Path.Combine(Directory.GetCurrentDirectory(), pathLeg); } if (useLeg && File.Exists(pathLeg)) { try { Process ps; string tmpfile = $"tmp_{_name}.json"; string errfile = $"tmp_{_name}.err"; if (OperatingSystem.IsWindows()) { CLogger.LogInfo("Launch: cmd.exe /c \"" + pathLeg + "\" list --json 1> " + tmpfile + " 2> " + errfile); ps = CDock.StartAndRedirect("cmd.exe", "/c \"" + pathLeg + "\" list --json 1> " + tmpfile + " 2> " + errfile); } else { CLogger.LogInfo("Launch: " + pathLeg + " list 1> " + tmpfile + " 2> " + errfile); ps = Process.Start(pathLeg, "list 1> " + tmpfile + " 2> " + errfile); } ps.WaitForExit(30000); if (File.Exists(tmpfile)) { if (ps.ExitCode != 0) { if (File.Exists(errfile)) { string strErrorData = File.ReadAllText(errfile); if (!string.IsNullOrEmpty(strErrorData)) { using StreamReader reader = new(errfile); string line; while ((line = reader.ReadLine()) != null) { if (line.Trim().EndsWith("No saved credentials")) { CLogger.LogInfo("Error getting not-installed {0} games. Is Legendary authenticated?\n" + $"To login, enter: \"{pathLeg}\" auth", _name.ToUpper()); } } } } } string strDocumentData = File.ReadAllText(tmpfile); if (!string.IsNullOrEmpty(strDocumentData)) { CLogger.LogDebug("{0} not-installed games:", _name.ToUpper()); using JsonDocument document = JsonDocument.Parse(@strDocumentData, jsonTrailingCommas); foreach (JsonElement element in document.RootElement.EnumerateArray()) { string strID = GetStringProperty(element, "app_name"); if (epicIds.Contains(strID)) // Check if game is already installed { continue; } string strTitle = GetStringProperty(element, "app_title"); CLogger.LogDebug($"- *{strTitle}"); string strAlias = GetAlias(strTitle); if (strAlias.Equals(strTitle, CDock.IGNORE_CASE)) { strAlias = ""; } gameDataList.Add(new ImportGameData(strID, strTitle, "", "", "", strAlias, false, strPlatform)); } } #if !DEBUG File.Delete(tmpfile); File.Delete(errfile); #endif } else { CLogger.LogInfo("Can't get not-installed {0} games. Error running Legendary.", _name.ToUpper()); } } catch (Exception e) { CLogger.LogError(e, string.Format("Malformed {0} output.", _name.ToUpper())); } } else { CLogger.LogInfo("Can't get not-installed {0} games. Legendary must be installed.\n" + "Go to <https://legendary.gl/release/latest>.", _name.ToUpper()); } } CLogger.LogDebug("--------------------"); }
public void GetGames(List <ImportGameData> gameDataList, bool expensiveIcons = false) { string strPlatform = GetPlatformString(ENUM); // Stop service (otherwise database is locked) ServiceController sc = new("OVRService"); //bool restartSvc = false; try { if (sc.Status.Equals(ServiceControllerStatus.Running) || sc.Status.Equals(ServiceControllerStatus.StartPending)) { //restartSvc = true; sc.Stop(); sc.WaitForStatus(ServiceControllerStatus.Stopped); } } catch (Exception e) { CLogger.LogError(e); } List <string> libPaths = new(); Dictionary <ulong, string> exePaths = new(); string db = Path.Combine(GetFolderPath(SpecialFolder.ApplicationData), OCULUS_DB); using (RegistryKey key = Registry.CurrentUser.OpenSubKey(OCULUS_LIBS, RegistryKeyPermissionCheck.ReadSubTree)) { if (key != null) { foreach (string lib in key.GetSubKeyNames()) { using RegistryKey key2 = Registry.CurrentUser.OpenSubKey(Path.Combine(OCULUS_LIBS, lib), RegistryKeyPermissionCheck.ReadSubTree); libPaths.Add(GetRegStrVal(key2, OCULUS_LIBPATH)); } } } foreach (string lib in libPaths) { List <string> libFiles = new(); try { string manifestPath = Path.Combine(lib, "Manifests"); libFiles = Directory.GetFiles(manifestPath, "*.json.mini", SearchOption.TopDirectoryOnly).ToList(); CLogger.LogInfo("{0} {1} games found in library {2}", libFiles.Count, _name.ToUpper(), lib); } catch (Exception e) { CLogger.LogError(e, string.Format("{0} directory read error: {1}", _name.ToUpper(), lib)); continue; } foreach (string file in libFiles) { try { var options = new JsonDocumentOptions { AllowTrailingCommas = true }; string strDocumentData = File.ReadAllText(file); if (string.IsNullOrEmpty(strDocumentData)) { CLogger.LogWarn(string.Format("Malformed {0} file: {1}", _name.ToUpper(), file)); } else { using JsonDocument document = JsonDocument.Parse(@strDocumentData, options); string name = GetStringProperty(document.RootElement, "canonicalName"); if (ulong.TryParse(GetStringProperty(document.RootElement, "appId"), out ulong id)) { exePaths.Add(id, Path.Combine(lib, "Software", name, GetStringProperty(document.RootElement, "launchFile"))); } } } catch (Exception e) { CLogger.LogError(e, string.Format("Malformed {0} file: {1}", _name.ToUpper(), file)); } } } try { CultureInfo ci = new("en-GB"); TextInfo ti = ci.TextInfo; string userName = CConfig.GetConfigString(CConfig.CFG_OCULUSID); //ulong userId = 0; using SQLiteConnection con = new($"Data Source={db}"); con.Open(); // Get the user ID to check entitlements for expired trials /* * using (SQLiteCommand cmdU = new("SELECT hashkey, value FROM Objects WHERE typename = 'User'", con)) * { * using SQLiteDataReader rdrU = cmdU.ExecuteReader(); * while (rdrU.Read()) * { * byte[] valU = new byte[rdrU.GetBytes(1, 0, null, 0, int.MaxValue) - 1]; * rdrU.GetBytes(1, 0, valU, 0, valU.Length); * string strValU = System.Text.Encoding.Default.GetString(valU); * * string alias = ParseBlob(strValU, "alias", "app_entitlements"); * if (string.IsNullOrEmpty(userName)) * { * if (ulong.TryParse(rdrU.GetString(0), out userId)) * { * userName = alias; * break; * } * } * else if (userName.Equals(alias, CDock.IGNORE_CASE)) * { * ulong.TryParse(rdrU.GetString(0), out userId); * break; * } * } * } */ using SQLiteCommand cmd = new("SELECT hashkey, value FROM Objects WHERE typename = 'Application'", con); using SQLiteDataReader rdr = cmd.ExecuteReader(); while (rdr.Read()) { string strID = ""; string strTitle = ""; string strLaunch = ""; string strAlias = ""; string url = ""; /* * string exePath = "", exePath2d = "", exeParams = "", exeParams2d = ""; * string state = "", time = ""; * bool isInstalled = false; */ bool isInstalled = true; if (ulong.TryParse(rdr.GetString(0), out ulong id)) { strID = "oculus_" + id; } //else // strID = "oculus_" + name; if (id == OCULUS_ENV_RIFT) { continue; } byte[] val = new byte[rdr.GetBytes(1, 0, null, 0, int.MaxValue) - 1]; rdr.GetBytes(1, 0, val, 0, val.Length); string strVal = System.Text.Encoding.Default.GetString(val); _ = ulong.TryParse(ParseBlob(strVal, "ApplicationAssetBundle", "can_access_feature_keys", -1, 0), out ulong assets); //ulong.TryParse(ParseBlob(strVal, "PCBinary", "livestreaming_status", -1, 0), out ulong bin); string name = ParseBlob(strVal, "canonical_name", "category"); strTitle = ParseBlob(strVal, "display_name", "display_short_description"); if (!string.IsNullOrEmpty(name) && string.IsNullOrEmpty(strTitle)) { strTitle = ti.ToTitleCase(name.Replace('-', ' ')); } using (SQLiteCommand cmd2 = new($"SELECT value FROM Objects WHERE hashkey = '{assets}'", con)) { using SQLiteDataReader rdr2 = cmd2.ExecuteReader(); while (rdr2.Read()) { byte[] val2 = new byte[rdr2.GetBytes(0, 0, null, 0, int.MaxValue) - 1]; rdr2.GetBytes(0, 0, val2, 0, val2.Length); string strVal2 = System.Text.Encoding.Default.GetString(val2); url = ParseBlob(strVal2, "uri", "version_code", strStart1: "size"); } } // The exe's can be gotten from the .json files, which we have to get anyway to figure out the install path /* * using (SQLiteCommand cmd3 = new($"SELECT value FROM Objects WHERE hashkey = '{bin}'", con)) * { * using SQLiteDataReader rdr3 = cmd3.ExecuteReader(); * while (rdr3.Read()) * { * byte[] val3 = new byte[rdr3.GetBytes(0, 0, null, 0, int.MaxValue) - 1]; * rdr3.GetBytes(0, 0, val3, 0, val3.Length); * string strVal3 = System.Text.Encoding.Default.GetString(val3); * exePath = ParseBlob(strVal3, "launch_file", "launch_file_2d"); * exePath2d = ParseBlob(strVal3, "launch_file_2d", "launch_parameters"); * exeParams = ParseBlob(strVal3, "launch_parameters", "launch_parameters_2d"); * exeParams2d = ParseBlob(strVal3, "launch_parameters_2d", "manifest_signature"); * } * } * * if (userId > 0) * { * // TODO: If this is an expired trial, count it as not-installed * using SQLiteCommand cmd5 = new($"SELECT value FROM Objects WHERE hashkey = '{userId}:{id}'", con); * using SQLiteDataReader rdr5 = cmd5.ExecuteReader(); * while (rdr5.Read()) * { * byte[] val5 = new byte[rdr5.GetBytes(0, 0, null, 0, int.MaxValue) - 1]; * rdr5.GetBytes(0, 0, val5, 0, val5.Length); * string strVal5 = System.Text.Encoding.Default.GetString(val5); * state = ParseBlob(strVal5, "active_state", "expiration_time"); * if (state.Equals("PERMANENT")) * isInstalled = true; * else * { * time = ParseBlob(strVal5, "expiration_time", "grant_reason"); * CLogger.LogDebug($"expiry: {state} {time}"); * //if (!...expired) * isInstalled = true; * } * } * } * else * isInstalled = true; */ if (exePaths.ContainsKey(id)) { CLogger.LogDebug($"- {strTitle}"); strLaunch = exePaths[id]; strAlias = GetAlias(Path.GetFileNameWithoutExtension(exePaths[id])); if (strAlias.Length > strTitle.Length) { strAlias = GetAlias(strTitle); } if (strAlias.Equals(strTitle, CDock.IGNORE_CASE)) { strAlias = ""; } gameDataList.Add(new ImportGameData(strID, strTitle, strLaunch, strLaunch, "", strAlias, isInstalled, strPlatform)); } else { CLogger.LogDebug($"- *{strTitle}"); gameDataList.Add(new ImportGameData(strID, strTitle, "", "", "", "", false, strPlatform)); if (expensiveIcons && !string.IsNullOrEmpty(url)) { // Download missing icons string imgfile = Path.Combine(CDock.currentPath, CDock.IMAGE_FOLDER_NAME, string.Concat(strTitle.Split(Path.GetInvalidFileNameChars()))); bool iconFound = false; foreach (string ext in CDock.supportedImages) { if (File.Exists(imgfile + "." + ext)) { iconFound = true; break; } } if (iconFound) { continue; } string zipfile = $"tmp_{_name}_{id}.zip"; try { #if DEBUG // Don't re-download if file exists if (!File.Exists(zipfile)) { #endif using WebClient client = new(); client.DownloadFile(url, zipfile); #if DEBUG } #endif using ZipArchive archive = ZipFile.OpenRead(zipfile); foreach (ZipArchiveEntry entry in archive.Entries) { foreach (string ext in CDock.supportedImages) { if (entry.Name.Equals("cover_square_image." + ext, CDock.IGNORE_CASE)) { entry.ExtractToFile(imgfile + "." + ext); break; } } } //#if !DEBUG File.Delete(zipfile); //#endif } catch (Exception e) { CLogger.LogError(e, string.Format("Malformed {0} zip file!", _name.ToUpper())); } } } } con.Close(); } catch (Exception e) { CLogger.LogError(e, string.Format("Malformed {0} database output!", _name.ToUpper())); } //if (restartSvc) // sc.Start(); CLogger.LogDebug("--------------------"); }