Nexus-Mods / NexusMods.App

Home of the development of the Nexus Mods App
https://nexus-mods.github.io/NexusMods.App/
GNU General Public License v3.0
615 stars 40 forks source link

Exception when indexing Stardew Valley installed with Xbox Game Pass #1476

Open erri120 opened 1 month ago

erri120 commented 1 month ago
00:00:25.295 [ERROR] (NexusMods.App.Program) Encountered an exception published to an object with an unobserved ThrownExceptions property|System.UnauthorizedAccessException: Access to the path 'C:\Games\Xbox\Stardew Valley\Content\createdump.exe' is denied.
   at Microsoft.Win32.SafeHandles.SafeFileHandle.CreateFile(String fullPath, FileMode mode, FileAccess access, FileShare share, FileOptions options)
   at Microsoft.Win32.SafeHandles.SafeFileHandle.Open(String fullPath, FileMode mode, FileAccess access, FileShare share, FileOptions options, Int64 preallocationSize, Nullable`1 unixCreateMode)
   at System.IO.Strategies.OSFileStreamStrategy..ctor(String path, FileMode mode, FileAccess access, FileShare share, FileOptions options, Int64 preallocationSize, Nullable`1 unixCreateMode)
   at System.IO.FileStream..ctor(String path, FileStreamOptions options)
   at NexusMods.Paths.FileSystem.InternalCreateMemoryMappedFile(AbsolutePath absPath, FileMode mode, MemoryMappedFileAccess access)
   at NexusMods.Paths.BaseFileSystem.CreateMemoryMappedFile(AbsolutePath absPath, FileMode mode, MemoryMappedFileAccess access)
   at NexusMods.Extensions.Hashing.AbsolutePathExtensions.XxHash64MemoryMapped(AbsolutePath input, IActivitySource`1 job) in C:\Projects\NexusMods.App\src\Extensions\NexusMods.Extensions.Hashing\AbsolutePathExtensions.cs:line 44
   at NexusMods.DataModel.FileHashCache.<>c__DisplayClass7_0.<IndexFoldersAsync>b__4(IFileEntry info, CancellationToken _) in C:\Projects\NexusMods.App\src\NexusMods.DataModel\FileHashCache.cs:line 103
   at System.Threading.Tasks.Parallel.<>c__53`1.<<ForEachAsync>b__53_0>d.MoveNext()
--- End of stack trace from previous location ---
   at NexusMods.DataModel.FileHashCache.IndexFoldersAsync(IEnumerable`1 paths, CancellationToken token)+MoveNext() in C:\Projects\NexusMods.App\src\NexusMods.DataModel\FileHashCache.cs:line 92
   at NexusMods.DataModel.FileHashCache.IndexFoldersAsync(IEnumerable`1 paths, CancellationToken token)+System.Threading.Tasks.Sources.IValueTaskSource<System.Boolean>.GetResult()
   at System.Linq.AsyncEnumerable.<ToListAsync>g__Core|424_0[TSource](IAsyncEnumerable`1 source, CancellationToken cancellationToken) in /_/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToList.cs:line 36
   at System.Linq.AsyncEnumerable.<ToListAsync>g__Core|424_0[TSource](IAsyncEnumerable`1 source, CancellationToken cancellationToken) in /_/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToList.cs:line 36
   at NexusMods.DataModel.FileHashCache.IndexDiskState(GameInstallation installation) in C:\Projects\NexusMods.App\src\NexusMods.DataModel\FileHashCache.cs:line 142
   at NexusMods.Abstractions.Loadouts.Synchronizers.ALoadoutSynchronizer.GetOrCreateInitialDiskState(GameInstallation installation) in C:\Projects\NexusMods.App\src\Abstractions\NexusMods.Abstractions.Loadouts.Synchronizers\ALoadoutSynchronizer.cs:line 1212
   at NexusMods.Abstractions.Loadouts.Synchronizers.ALoadoutSynchronizer.CreateLoadout(GameInstallation installation, String suggestedName) in C:\Projects\NexusMods.App\src\Abstractions\NexusMods.Abstractions.Loadouts.Synchronizers\ALoadoutSynchronizer.cs:line 922
   at NexusMods.App.UI.Pages.MyGames.MyGamesViewModel.ManageGame(GameInstallation installation) in C:\Projects\NexusMods.App\src\NexusMods.App.UI\Pages\MyGames\MyGamesViewModel.cs:line 129
   at NexusMods.App.UI.Pages.MyGames.MyGamesViewModel.<>c__DisplayClass7_3.<<-ctor>b__11>d.MoveNext() in C:\Projects\NexusMods.App\src\NexusMods.App.UI\Pages\MyGames\MyGamesViewModel.cs:line 99
--- End of stack trace from previous location ---
   at NexusMods.App.UI.Pages.MyGames.MyGamesViewModel.<>c__DisplayClass7_3.<<-ctor>b__9>d.MoveNext() in C:\Projects\NexusMods.App\src\NexusMods.App.UI\Pages\MyGames\MyGamesViewModel.cs:line 99
Sewer56 commented 1 month ago

Some documentation I wrote in (very WIP) planning doc I'm working on: https://reloaded-project.github.io/Reloaded-III/Loader/Copy-Protection/Windows-MSStore/#what-r3-should-do (Consider also reading the rest)

And existing code I wrote: https://github.com/Reloaded-Project/Reloaded-II/blob/master/source/Reloaded.Mod.Launcher.Lib/Utility/TryUnprotectGamePassGame.cs

Those are the steps to decrypt Xbox Store binaries, so they can be read and modified.

It's a bit convoluted as it's a multi step process, and annoying to have to do, but it's been working flawlessly for the last 3-4 months on my end.

Al12rs commented 1 month ago

Is manually installed smapi supposed to work on GamePass version?

Al12rs commented 1 month ago

https://stardewvalleywiki.com/Modding:Installing_SMAPI_on_Windows#Xbox_app

erri120 commented 1 month ago

I think the easiest solution is to just skip the file if we encounter an UnauthorizedAccessException and the game store is set to Xbox Game Pass.

Sewer56 commented 1 month ago

Also this affects all Xbox games, or more specifically Win32 Centennial Apps, it is not Stardew Specific.

Sewer56 commented 1 month ago

I think the easiest solution is to just skip the file if we encounter an UnauthorizedAccessException and the game store is set to Xbox Game Pass.

If you want to go that route then at that point we should not take backups of these games by default.

A partial backup with all binaries missing is not useful if the game updates.

Edit: Also don't forget we move StardewValley.exe, if we don't have a backup of that, I'm not sure if our DataModel won't collapse on apply either way, even if you skip.