Skip to content

Commit

Permalink
support to run app in removable storage device
Browse files Browse the repository at this point in the history
  • Loading branch information
Scighost committed Jan 18, 2025
1 parent 8d0d3e8 commit 340f34b
Show file tree
Hide file tree
Showing 15 changed files with 295 additions and 69 deletions.
79 changes: 79 additions & 0 deletions src/Starward.RPC/AppConfig.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Reflection;
using System.Security.Principal;
using Vanara.PInvoke;

namespace Starward.RPC;

Expand All @@ -18,14 +19,92 @@ internal static class AppConfig
public const string StartupMagic = "zb8L3ShgFjeyDxeA";


public static string? StarwardLauncherExecutePath { get; private set; }


public static bool IsPortable { get; private set; }


public static bool IsAppInRemovableStorage { get; private set; }


public static string CacheFolder { get; private set; }




static AppConfig()
{
AppVersion = typeof(Program).Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion ?? "";
IsAdmin = new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator);

IsAppInRemovableStorage = IsDeviceRemovableOrOnUSB(AppContext.BaseDirectory);
string? parentFolder = new DirectoryInfo(AppContext.BaseDirectory).Parent?.FullName;
string launcherExe = Path.Join(parentFolder, "Starward.exe");
if (Directory.Exists(parentFolder) && File.Exists(launcherExe))
{
IsPortable = true;
StarwardLauncherExecutePath = launcherExe;
}

if (IsAppInRemovableStorage && IsPortable)
{
CacheFolder = Path.Combine(parentFolder!, ".cache");
}
else if (IsAppInRemovableStorage)
{
CacheFolder = Path.Combine(Path.GetPathRoot(AppContext.BaseDirectory)!, ".StarwardCache");
}
else if (IsPortable)
{
CacheFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Starward");
}
else
{
CacheFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Starward");
}
Directory.CreateDirectory(CacheFolder);
}




public static bool IsDeviceRemovableOrOnUSB(string path)
{
try
{
if (Directory.Exists(path))
{
DriveInfo drive = new DriveInfo(path);
if (drive.DriveType is DriveType.Removable)
{
return true;
}
string fileName = $@"\\.\{drive.Name.Trim('\\')}";
using Kernel32.SafeHFILE hDevice = Kernel32.CreateFile(fileName, 0, FileShare.ReadWrite | FileShare.Delete, null, FileMode.Open, 0, HFILE.NULL);
if (hDevice.IsInvalid)
{
return false;
}
Kernel32.STORAGE_PROPERTY_QUERY query = new()
{
PropertyId = Kernel32.STORAGE_PROPERTY_ID.StorageDeviceProperty,
QueryType = Kernel32.STORAGE_QUERY_TYPE.PropertyStandardQuery,
};
bool result = Kernel32.DeviceIoControl(hDevice, Kernel32.IOControlCode.IOCTL_STORAGE_QUERY_PROPERTY, query, out Kernel32.STORAGE_DEVICE_DESCRIPTOR_MGD desc);
if (result)
{
if (desc.BusType == Kernel32.STORAGE_BUS_TYPE.BusTypeUsb)
{
return true;
}
}
}
}
catch { }
return false;
}



}
2 changes: 1 addition & 1 deletion src/Starward.RPC/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
var builder = WebApplication.CreateBuilder(args);


var logFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"Starward\log");
var logFolder = Path.Combine(AppConfig.CacheFolder, "log");
Directory.CreateDirectory(logFolder);
var logFile = Path.Combine(logFolder, $"Starward_{DateTime.Now:yyMMdd}.log");
Log.Logger = new LoggerConfiguration().WriteTo.File(path: logFile, shared: true, outputTemplate: $$"""[{Timestamp:HH:mm:ss.fff}] [{Level:u4}] [{{Path.GetFileName(Environment.ProcessPath)}} ({{Environment.ProcessId}})] {SourceContext}{NewLine}{Message}{NewLine}{Exception}{NewLine}""")
Expand Down
1 change: 1 addition & 0 deletions src/Starward.RPC/Starward.RPC.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
<ItemGroup>
<PackageReference Include="Grpc.AspNetCore" Version="2.67.0" />
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
<PackageReference Include="Vanara.PInvoke.Kernel32" Version="4.0.4" />
</ItemGroup>

<ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion src/Starward.RPC/Update/UpdateService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ public async Task PrepareForUpdateAsync(ReleaseVersion release, string targetPat
{
file.Path = Path.GetFullPath(file.Path, targetPath);
}
updateCacheFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Starward\\update");
updateCacheFolder = Path.Combine(AppConfig.CacheFolder, "Starward\\update");
Directory.CreateDirectory(updateCacheFolder);
await GetCurrentVersionFilesHashAsync(cancellationToken);
GetSameAndDownloadFiles();
Expand Down
2 changes: 1 addition & 1 deletion src/Starward/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public App()

private void App_UnhandledException(object sender, Microsoft.UI.Xaml.UnhandledExceptionEventArgs e)
{
var folder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Starward", "crash");
var folder = Path.Combine(AppSetting.CacheFolder, "crash");
Directory.CreateDirectory(folder);
var file = Path.Combine(folder, $"crash_{DateTime.Now:yyyyMMdd_HHmmss}.txt");
File.WriteAllText(file, e.Exception.ToString());
Expand Down
2 changes: 1 addition & 1 deletion src/Starward/AppConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ private static void Initialize()
{
AppVersion = typeof(AppConfig).Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion;
var webviewFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"Starward\webview");
Environment.SetEnvironmentVariable("WEBVIEW2_USER_DATA_FOLDER", webviewFolder, EnvironmentVariableTarget.Process);
//Environment.SetEnvironmentVariable("WEBVIEW2_USER_DATA_FOLDER", webviewFolder, EnvironmentVariableTarget.Process);

string? baseDir = Path.GetDirectoryName(AppContext.BaseDirectory.TrimEnd('\\'));
string exe = Path.Join(baseDir, "Starward.exe");
Expand Down
3 changes: 2 additions & 1 deletion src/Starward/Controls/CachedImage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Media.Imaging;
using Scighost.WinUI.ImageEx;
using Starward.Frameworks;
using Starward.Services.Cache;
using System;
using System.Collections.Concurrent;
Expand Down Expand Up @@ -110,7 +111,7 @@ public bool IsThumbnail



private static readonly string CacheFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Starward", "cache");
private static readonly string CacheFolder = Path.Combine(AppSetting.CacheFolder, "cache");


public static async Task<string> GetImageThumbnailAsync(string path)
Expand Down
2 changes: 1 addition & 1 deletion src/Starward/Features/Background/BackgroundService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public BackgroundService(ILogger<BackgroundService> logger, HoYoPlayService hoYo
[return: NotNullIfNotNull(nameof(name))]
private static string? GetBgFilePath(string? name)
{
string cache = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"Starward\cache");
string cache = Path.Combine(AppSetting.CacheFolder, "cache");
return Path.Join(cache, name);
}

Expand Down
10 changes: 4 additions & 6 deletions src/Starward/Features/GameLauncher/GameLauncherPage.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -176,14 +176,12 @@ private async Task LocateGameAsync()
{
try
{
string? folder = await FileDialogHelper.PickFolderAsync(this.XamlRoot);
if (string.IsNullOrWhiteSpace(folder))
string? folder = await _gameLauncherService.ChangeGameInstallPathAsync(CurrentGameId, this.XamlRoot);
if (!string.IsNullOrWhiteSpace(folder))
{
return;
CheckGameVersion();
WeakReferenceMessenger.Default.Send(new GameInstallPathChangedMessage());
}
AppSetting.SetGameInstallPath(CurrentGameBiz, folder);
AppSetting.SetGameInstallPathRemovable(CurrentGameBiz, DriveHelper.IsDeviceRemovableOrOnUSB(folder));
CheckGameVersion();
}
catch (Exception ex)
{
Expand Down
131 changes: 122 additions & 9 deletions src/Starward/Features/GameLauncher/GameLauncherService.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
using Microsoft.Extensions.Logging;
using Microsoft.UI.Xaml;
using Starward.Core;
using Starward.Core.HoYoPlay;
using Starward.Features.HoYoPlay;
using Starward.Features.PlayTime;
using Starward.Frameworks;
using Starward.Helpers;
using System;
using System.ComponentModel;
using System.Diagnostics;
Expand Down Expand Up @@ -45,18 +47,22 @@ public GameLauncherService(ILogger<GameLauncherService> logger, HoYoPlayService
public string? GetGameInstallPath(GameId gameId)
{
var path = AppSetting.GetGameInstallPath(gameId.GameBiz);
if (string.IsNullOrWhiteSpace(path))
{
return null;
}
path = GetFullPathIfRelativePath(path);
if (Directory.Exists(path))
{
return Path.GetFullPath(path);
}
else if (!string.IsNullOrWhiteSpace(path) && AppSetting.GetGameInstallPathRemovable(gameId.GameBiz))
else if (AppSetting.GetGameInstallPathRemovable(gameId.GameBiz))
{
return path;
}
else
{
AppSetting.SetGameInstallPath(gameId.GameBiz, null);
AppSetting.SetGameInstallPathRemovable(gameId.GameBiz, false);
ChangeGameInstallPath(gameId, null);
return null;
}
}
Expand All @@ -73,19 +79,23 @@ public GameLauncherService(ILogger<GameLauncherService> logger, HoYoPlayService
{
storageRemoved = false;
var path = AppSetting.GetGameInstallPath(gameId.GameBiz);
if (string.IsNullOrWhiteSpace(path))
{
return null;
}
path = GetFullPathIfRelativePath(path);
if (Directory.Exists(path))
{
return Path.GetFullPath(path);
return path;
}
else if (!string.IsNullOrWhiteSpace(path) && AppSetting.GetGameInstallPathRemovable(gameId.GameBiz))
else if (AppSetting.GetGameInstallPathRemovable(gameId.GameBiz))
{
storageRemoved = true;
return path;
}
else
{
AppSetting.SetGameInstallPath(gameId.GameBiz, null);
AppSetting.SetGameInstallPathRemovable(gameId.GameBiz, false);
ChangeGameInstallPath(gameId, null);
return null;
}
}
Expand Down Expand Up @@ -214,7 +224,7 @@ public async Task<bool> IsGameExeExistsAsync(GameId gameId, string? installPath
bool thirdPartyTool = false;
if (string.IsNullOrWhiteSpace(exe) && AppSetting.GetEnableThirdPartyTool(gameId.GameBiz))
{
exe = AppSetting.GetThirdPartyToolPath(gameId.GameBiz);
exe = GetThirdPartyToolPath(gameId);
if (File.Exists(exe))
{
thirdPartyTool = true;
Expand All @@ -223,7 +233,7 @@ public async Task<bool> IsGameExeExistsAsync(GameId gameId, string? installPath
else
{
exe = null;
AppSetting.SetThirdPartyToolPath(gameId.GameBiz, null);
SetThirdPartyToolPath(gameId, null);
_logger.LogWarning("Third party tool not found: {path}", exe);
}
}
Expand Down Expand Up @@ -275,5 +285,108 @@ public async Task<bool> IsGameExeExistsAsync(GameId gameId, string? installPath



public async Task<string?> ChangeGameInstallPathAsync(GameId gameId, XamlRoot xamlRoot)
{
string? folder = await FileDialogHelper.PickFolderAsync(xamlRoot);
if (string.IsNullOrWhiteSpace(folder))
{
return null;
}
string relativePath = GetRelativePathIfInRemovableStorage(folder, out bool removable);
AppSetting.SetGameInstallPath(gameId.GameBiz, relativePath);
AppSetting.SetGameInstallPathRemovable(gameId.GameBiz, removable);
return folder;
}



public string? ChangeGameInstallPath(GameId gameId, string? path)
{
if (Directory.Exists(path))
{
path = Path.GetFullPath(path);
string relativePath = GetRelativePathIfInRemovableStorage(path, out bool removable);
AppSetting.SetGameInstallPath(gameId.GameBiz, relativePath);
AppSetting.SetGameInstallPathRemovable(gameId.GameBiz, removable);
}
else
{
path = null;
AppSetting.SetGameInstallPath(gameId.GameBiz, null);
AppSetting.SetGameInstallPathRemovable(gameId.GameBiz, false);
}
return path;
}




public static string GetRelativePathIfInRemovableStorage(string path, out bool removableStorage)
{
removableStorage = DriveHelper.IsDeviceRemovableOrOnUSB(path);
if (removableStorage && Path.GetPathRoot(AppSetting.StarwardExecutePath) == Path.GetPathRoot(path))
{
path = Path.GetRelativePath(Path.GetDirectoryName(AppSetting.ConfigPath)!, path);
}
return path;
}




public static string GetFullPathIfRelativePath(string path)
{
if (Path.IsPathFullyQualified(path))
{
return Path.GetFullPath(path);
}
else
{
return Path.GetFullPath(path, Path.GetDirectoryName(AppSetting.ConfigPath)!);
}
}





public static string? GetThirdPartyToolPath(GameId gameId)
{
string? path = AppSetting.GetThirdPartyToolPath(gameId.GameBiz);
if (!string.IsNullOrWhiteSpace(path))
{
path = GetFullPathIfRelativePath(path);
}
if (File.Exists(path))
{
return path;
}
else
{
AppSetting.SetThirdPartyToolPath(gameId.GameBiz, null);
return null;
}
}



public static string? SetThirdPartyToolPath(GameId gameId, string? path)
{
if (File.Exists(path))
{
path = Path.GetFullPath(path);
string relativePath = GetRelativePathIfInRemovableStorage(path, out bool removable);
AppSetting.SetThirdPartyToolPath(gameId.GameBiz, relativePath);
}
else
{
path = null;
AppSetting.SetThirdPartyToolPath(gameId.GameBiz, null);
}
return path;
}




}
Loading

0 comments on commit 340f34b

Please sign in to comment.