mirror of
https://git.ryujinx.app/ryubing/ryujinx.git
synced 2025-08-01 02:30:08 -06:00

Launch the Ryujinx.exe, first argument --no-gui or nogui, and the rest of the arguments should be your normal headless script. You can include the new option --use-main-config which will provide any arguments that you don't, filled in from your main config made by the UI. Input config is not inherited at this time.
199 lines
6.8 KiB
C#
199 lines
6.8 KiB
C#
using Microsoft.Win32;
|
|
using Ryujinx.Common;
|
|
using Ryujinx.Common.Logging;
|
|
using System;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Runtime.InteropServices;
|
|
using System.Runtime.Versioning;
|
|
|
|
namespace Ryujinx.UI.Common.Helper
|
|
{
|
|
public static partial class FileAssociationHelper
|
|
{
|
|
private static readonly string[] _fileExtensions = [".nca", ".nro", ".nso", ".nsp", ".xci"];
|
|
|
|
[SupportedOSPlatform("linux")]
|
|
private static readonly string _mimeDbPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".local", "share", "mime");
|
|
|
|
private const int SHCNE_ASSOCCHANGED = 0x8000000;
|
|
private const int SHCNF_FLUSH = 0x1000;
|
|
|
|
[LibraryImport("shell32.dll", SetLastError = true)]
|
|
public static partial void SHChangeNotify(uint wEventId, uint uFlags, nint dwItem1, nint dwItem2);
|
|
|
|
public static bool IsTypeAssociationSupported => (OperatingSystem.IsLinux() || OperatingSystem.IsWindows());
|
|
|
|
public static bool AreMimeTypesRegistered
|
|
{
|
|
get
|
|
{
|
|
if (OperatingSystem.IsLinux())
|
|
{
|
|
return AreMimeTypesRegisteredLinux();
|
|
}
|
|
|
|
if (OperatingSystem.IsWindows())
|
|
{
|
|
return AreMimeTypesRegisteredWindows();
|
|
}
|
|
|
|
// TODO: Add macOS support.
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
[SupportedOSPlatform("linux")]
|
|
private static bool AreMimeTypesRegisteredLinux() => File.Exists(Path.Combine(_mimeDbPath, "packages", "Ryujinx.xml"));
|
|
|
|
[SupportedOSPlatform("linux")]
|
|
private static bool InstallLinuxMimeTypes(bool uninstall = false)
|
|
{
|
|
string installKeyword = uninstall ? "uninstall" : "install";
|
|
|
|
if ((uninstall && AreMimeTypesRegisteredLinux()) || (!uninstall && !AreMimeTypesRegisteredLinux()))
|
|
{
|
|
string mimeTypesFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "mime", "Ryujinx.xml");
|
|
string additionalArgs = !uninstall ? "--novendor" : string.Empty;
|
|
|
|
using Process mimeProcess = new();
|
|
|
|
mimeProcess.StartInfo.FileName = "xdg-mime";
|
|
mimeProcess.StartInfo.Arguments = $"{installKeyword} {additionalArgs} --mode user {mimeTypesFile}";
|
|
|
|
mimeProcess.Start();
|
|
mimeProcess.WaitForExit();
|
|
|
|
if (mimeProcess.ExitCode != 0)
|
|
{
|
|
Logger.Error?.PrintMsg(LogClass.Application, $"Unable to {installKeyword} mime types. Make sure xdg-utils is installed. Process exited with code: {mimeProcess.ExitCode}");
|
|
|
|
return false;
|
|
}
|
|
|
|
using Process updateMimeProcess = new();
|
|
|
|
updateMimeProcess.StartInfo.FileName = "update-mime-database";
|
|
updateMimeProcess.StartInfo.Arguments = _mimeDbPath;
|
|
|
|
updateMimeProcess.Start();
|
|
updateMimeProcess.WaitForExit();
|
|
|
|
if (updateMimeProcess.ExitCode != 0)
|
|
{
|
|
Logger.Error?.PrintMsg(LogClass.Application, $"Could not update local mime database. Process exited with code: {updateMimeProcess.ExitCode}");
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
[SupportedOSPlatform("windows")]
|
|
private static bool AreMimeTypesRegisteredWindows()
|
|
{
|
|
return _fileExtensions.Aggregate(false,
|
|
(current, ext) => current | CheckRegistering(ext)
|
|
);
|
|
|
|
static bool CheckRegistering(string ext)
|
|
{
|
|
RegistryKey key = Registry.CurrentUser.OpenSubKey(@$"Software\Classes\{ext}");
|
|
|
|
var openCmd = key?.OpenSubKey(@"shell\open\command");
|
|
|
|
if (openCmd is null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
string keyValue = (string)openCmd.GetValue(string.Empty);
|
|
|
|
return keyValue is not null && (keyValue.Contains("Ryujinx") || keyValue.Contains(AppDomain.CurrentDomain.FriendlyName));
|
|
}
|
|
}
|
|
|
|
[SupportedOSPlatform("windows")]
|
|
private static bool InstallWindowsMimeTypes(bool uninstall = false)
|
|
{
|
|
bool registered = _fileExtensions.Aggregate(false,
|
|
(current, ext) => current | RegisterExtension(ext, uninstall)
|
|
);
|
|
|
|
// Notify Explorer the file association has been changed.
|
|
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_FLUSH, nint.Zero, nint.Zero);
|
|
|
|
return registered;
|
|
|
|
static bool RegisterExtension(string ext, bool uninstall = false)
|
|
{
|
|
string keyString = @$"Software\Classes\{ext}";
|
|
|
|
if (uninstall)
|
|
{
|
|
// If the types don't already exist, there's nothing to do, and we can call this operation successful.
|
|
if (!AreMimeTypesRegisteredWindows())
|
|
{
|
|
return true;
|
|
}
|
|
Logger.Debug?.Print(LogClass.Application, $"Removing type association {ext}");
|
|
Registry.CurrentUser.DeleteSubKeyTree(keyString);
|
|
Logger.Debug?.Print(LogClass.Application, $"Removed type association {ext}");
|
|
}
|
|
else
|
|
{
|
|
using var key = Registry.CurrentUser.CreateSubKey(keyString);
|
|
|
|
if (key is null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
Logger.Debug?.Print(LogClass.Application, $"Adding type association {ext}");
|
|
using var openCmd = key.CreateSubKey(@"shell\open\command");
|
|
openCmd.SetValue(string.Empty, $"\"{Environment.ProcessPath}\" \"%1\"");
|
|
Logger.Debug?.Print(LogClass.Application, $"Added type association {ext}");
|
|
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
public static bool Install()
|
|
{
|
|
if (OperatingSystem.IsLinux())
|
|
{
|
|
return InstallLinuxMimeTypes();
|
|
}
|
|
|
|
if (OperatingSystem.IsWindows())
|
|
{
|
|
return InstallWindowsMimeTypes();
|
|
}
|
|
|
|
// TODO: Add macOS support.
|
|
|
|
return false;
|
|
}
|
|
|
|
public static bool Uninstall()
|
|
{
|
|
if (OperatingSystem.IsLinux())
|
|
{
|
|
return InstallLinuxMimeTypes(true);
|
|
}
|
|
|
|
if (OperatingSystem.IsWindows())
|
|
{
|
|
return InstallWindowsMimeTypes(true);
|
|
}
|
|
|
|
// TODO: Add macOS support.
|
|
|
|
return false;
|
|
}
|
|
}
|
|
}
|