Compare commits

...

62 Commits

Author SHA1 Message Date
Brian Lima 19354c3416 Wrap the shortcut clear button with a warning 2 months ago
Brian Lima fa07be2a4f Update installer script to use newer references 2 months ago
Brian Lima 9345438f02 Update dependencies to latest version 2 months ago
Brian Lima 8a84dd7be6 Update readme and version 2 months ago
Brian Lima 91cc228ca2 Allow for jpegs and attempt to not mess shortcuts form other apps
Co-Authored-By: David Ross Smith <5095074+dragredsim@users.noreply.github.com>
2 months ago
Brian Lima a07d1b8e5e Fix the missing appid when exporting apps 2 months ago
Brian Lima 1744817958 Backup users vdf files 2 months ago
Brian Lima c25f5098ea Improve temp image directory handling 2 months ago
Brian Lima d91ec0c270
Merge pull request #112 from alimbada/master
Create temp grid directory if it doesn't exist
1 year ago
Ammaar Limbada 82fc1eea41 Create temp grid directory if it doesn't exist 1 year ago
Brian Lima b9f746d5c3 Update installer script 2 years ago
Brian Lima 11ee11274e Check if icon exists before copying 2 years ago
Brian Lima faa6b36759 Fix icons being repeated between apps, default to app.Icon 2 years ago
Brian Lima 2dd9d96a96 Bump version, update dependencies 2 years ago
Brian Lima 903619ba0b Refactor PersistAppIcon to use optional parameter
DRY both PersistAppIcon functions, also handle exceptions if trying to copy an icon for an app with encrypted icon when the SteamGridDB integration is disabled, defaulting to the app.Icon itself
2 years ago
Brian Lima f1dac8e92e
Merge pull request #99 from stevealexandre/GameMissing
Add two methods to get target executable + get icon from image api
2 years ago
Brian Lima 826822c36d
Merge pull request #98 from stevealexandre/fix_logger_issue
fix: log admin permission issue
2 years ago
stevealexandre 108a3a580b Add two methods to get target executable + get icon from image api 2 years ago
stevealexandre ab58a6a64c fix: log admin permission issue 2 years ago
Brian Lima 80419cab7f Bump version 2 years ago
Brian Lima 15e0911930 Fix Taiko and Astroneer known apps entries 2 years ago
Brian Lima 8edf30d9a0
Merge pull request #96 from stevealexandre/SteamLauncherIssues
Check running child processes by executable name
2 years ago
stevealexandre 09e2032cf9 Add new logic to verify process path and name to handle mid launcher start 2 years ago
stevealexandre 266dab93b9 Init global logger from Serilog to file on Error level 2 years ago
stevealexandre 142e6529e7 Add executable getter/setter to put it in the steam startup option 2 years ago
stevealexandre 3f2c6c610e Update powershell script to add relative executable path from MS Config file 2 years ago
stevealexandre 99f1cd0e4d add Serilog package for clean logging 2 years ago
Brian Lima 04887bacbd Bump version 2 years ago
Brian Lima 3a6f8afa0b Move transient icon directory to %appdata% 2 years ago
Brian Lima c6bb692c07 Improve error response handling 2 years ago
Brian Lima 74cecfaa29 Update installer 2 years ago
Brian Lima 9c7a526d7c Update settings window 2 years ago
Brian Lima c4905da473 Update Settings 2 years ago
Brian Lima a61ee3ba78 Copy game icons to prevent "lost" icons 2 years ago
Brian Lima 0f5de2088a Do not block UI when restarting Steam 2 years ago
Brian Lima c278c6389b Fix SteamGridDB offer 2 years ago
Brian Lima 63ed7de1e7 Update broken dependencies, update to net 4.8
- Upgrade to .net 4.8
- Move System.Management.Automation from Powershell to system's
  - The older System.Management.Automation hass been deprecated for legacy .Net apps, so I have to either port UWPHook to .net core or use another legacy focused powershell package, not in the mood for either right now, this can be located at C:\Windows\assembly\GAC_MSIL\System.Management.Automation\1.0.0.0__31bf3856ad364e35\System.Management.Automation.dll
- Add System.Net.HTTP.formatting
- Migrate to PackageReference
2 years ago
Brian Lima 458fd24fea
Merge pull request #87 from novemberdobby/master
fixed process tracking for "advanced install" games, which are launched via an instance of GameLaunchHelper.exe
2 years ago
dobby 8f455b395c fixed process tracking for "advanced install" games, which are launched via an instance of GameLaunchHelper.exe 2 years ago
Jon Philpot 22ccfe146c Merge remote-tracking branch 'upstream/master' 2 years ago
Brian Lima a4627a75a1
Update KnownApps.json 2 years ago
Jon Philpot 8118695a6c
Merge branch 'BrianLima:master' into master 3 years ago
Jon f45e523ce3 dead cells added to known apps 3 years ago
Brian Lima b050329ea2 Improve error handler, prepare new settings 3 years ago
Brian Lima 4dba2373a6
Merge pull request #75 from GamerKingFaiz/patch-1 3 years ago
Brian Lima e8a1e0379d
Merge pull request #73 from novemberdobby/master 3 years ago
Faiz-ur Rahman e09dedc613
Update README.md
Updated the Troubleshooting section to enhance readability.
3 years ago
Jon fdb0040408 search by name + aumid (for Age of Empires IV) 3 years ago
Jon b3ec7375ef removed duplicate call 3 years ago
Jon 16522024cf added AppEntry.ToString()

							
						
3 years ago
Jon a5ea0db936 automatically restart steam after exporting apps 3 years ago
Jon d8c527e3c8 typo 3 years ago
Jon b8fb532fa9 removed bonus import 3 years ago
Jon Philpot b71495ba08
Merge branch 'BrianLima:master' into master 3 years ago
Brian Lima 24fb6ec64e Fix #72, update version and dependencies 3 years ago
Brian Lima c8143a7d01
Merge pull request #71 from EnumC/feat.apiErrorCatcher.cp 3 years ago
Brian Lima fa51d9d40f
Merge pull request #70 from EnumC/feat.duplicateDetect 3 years ago
EnumC 5c844a4a7d
Fix missing namespace from previous cherry-pick 3 years ago
EnumC 3bd6dee3d5
Reset tabs to spaces 3 years ago
EnumC d2f80be0e7
Display error when SteamGridDB request fails with 401 3 years ago
EnumC 4eb4316d6b
Prevent duplicate entries 3 years ago
Jon a4383412ed auto refresh games list on load 3 years ago

@ -4,7 +4,7 @@
Small project to link UWP games and XboxGamePass to Steam
If you want to add Windows Store or Xbox Game Pass Games to Steam, you need to do a bit of a warkaround because Steam can't see UWP apps, and there's a chance Steam won't show it on your "Currently playing" status. This app aims to simplify a little bit the process where it is possible by automating the scripting and launching of Windows Store apps and Xbox Game Pass games.
If you want to add Windows Store or Xbox Game Pass Games to Steam, you need to do a bit of a workaround because Steam can't see UWP apps, and there's a chance Steam won't show it on your "Currently playing" status. This app aims to simplify a little bit the process where it is possible by automating the scripting and launching of Windows Store apps and Xbox Game Pass games.
# To add UWP or XGP games to Steam #
@ -18,7 +18,7 @@ Select every app you want to add to Steam, you can change the name by double cli
![](https://i.imgur.com/on46CMQ.png)
Close UWPHook, restart Steam, click play on your UWP game, and Steam will show your current game on your status as long as you are playing it!
Close UWPHook, restart Steam if prompted, click play on your UWP game, and Steam will show your current game on your status as long as you are playing it!
----------
@ -41,23 +41,42 @@ Special thanks to @FusRoDah061 for implementing the base feature!
# Troubleshooting #
- **Steam's Overlay isn't working!**
- Unfortunately, it's a Steam limitation, Valve has to update it in order to work properly with UWP, DXTory is a recommended overlay for UWP games.
- Unfortunately, it's a Steam limitation, Valve has to update it in order to work properly with UWP, DXTory is a recommended overlay for UWP games.
- **Using Steam Link**
- Check the option "Streaming" mode inside the settings screen
- **Steam Deck?**
- This app is not compatible with the Steam Deck in any way.
If you are facing an error of any kind, please check the contents of the file
- **I have shortcuts from other application that broke when i used UWPHook**
- You can find a backup of your `shortcuts.vdf` file in `%appdata%\Roaming\Briano\UWPHook\backups`, each file in this directory is a backup of the original `shortcuts.vdf` before manipulation by UWPHook, the files are renamed `{userid}_{timestamp}_shortcut.vdf`, you can restore these files to their original location for usage.
- **My question isn't listed here!**
- Drop by our subreddit and ask a question over there, maybe someone will help you, i surely will as soon as i can:
**[https://www.reddit.com/r/uwphook](https://www.reddit.com/r/uwphook)**
- Please also paste the contents of the file `%appdata%Roaming\Briano\UWPHook\application.log` so i can try to understand better the problem.
----------
- **Steam Link launches the game but input doesn't work!**
- Unfortunately, another limitation by Steam, i have some ideas as to why it isn't working, but i can't give an ETA for when i can fix this, or even if it's fixable on my end, since Valve didn't released the Link in Brazil and i can't get one to test.
# Building
- **Steam Controller isn't working**
- Another limitation by Steam, some people reported it works with "Desktop Mode" configuration, but i can't verify this.
- Clone project or forked project.
- Install Visual Studio 2022 with .NET Framework 4.8.
- Install [SharpSteam by BrianLima](https://github.com/BrianLima/SharpSteam/releases/) and [VDFParser](https://github.com/brianlima/VDFParser) and build.
- If the project asks for the references for VDFParser and Sharpsteam, point it to the most recent build.
- Press run!
- **My question isn't listed here!**
- Drop by our subreddit and ask a question over there, maybe someone will help you, i surely will as soon as i can
**[https://www.reddit.com/r/uwphook](https://www.reddit.com/r/uwphook)**
## Installer
The installer is built with [NSIS](https://nsis.sourceforge.io/Download), just run the script `UWPHook.nsi` and things **should** work. Modify any hardcoded paths to suit your setup.
The installation consists of zipping the application and creating some of the paths for the user, since the application is mostly static/dynamic and does not depend a lot on where it is installed, the installer is made for convenience.
----------
# About #
# About
This software is open-source under the MIT License.
It will mostly likely break withouth any heads up, since any API, file format, script and many other things used by it may be changed by Valve or Microsoft withouth prior notice.
I am not responsible if anything breaks.
If you like what i did with it and want to suport me, you can cheer me up at my [Twitter](http://www.twitter.com/brianostorm "Twitter") or [pay me a coffee via Paypal, it will help me to continue to build amazing open source tools for you!"](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=9YPV3FHEFRAUQ)

@ -11,8 +11,8 @@
!define APP_NAME "UWPHook"
!define COMP_NAME "Briano"
!define WEB_SITE "https://briano.dev"
!define VERSION "2.8.00.00"
!define COPYRIGHT "Briano <20> 2020"
!define VERSION "2.14.00.00"
!define COPYRIGHT "Briano <20> 2020 2021 2022"
!define DESCRIPTION "The easy way to add UWP and XGP games to Steam"
!define LICENSE_TXT "C:\Users\Brian\Documents\GitHub\UWPHook\README.md"
!define INSTALLER_NAME "C:\Users\Brian\Documents\GitHub\UWPHook\UWPHook.exe"
@ -44,7 +44,7 @@ OutFile "${INSTALLER_NAME}"
BrandingText "${APP_NAME}"
XPStyle on
InstallDirRegKey "${REG_ROOT}" "${REG_APP_PATH}" ""
InstallDir "$PROGRAMFILES\Briano\UWPHook"
InstallDir "$APPDATA\Briano\UWPHook"
######################################################################
@ -88,17 +88,31 @@ Section -MainProgram
${INSTALL_TYPE}
SetOverwrite ifnewer
SetOutPath "$INSTDIR"
File "C:\Users\Brian\Documents\GitHub\UWPHook\UWPHook\bin\Release\Crc32.NET.dll"
File "C:\Users\Brian\Documents\GitHub\UWPHook\UWPHook\bin\Release\MaterialDesignColors.dll"
File "C:\Users\Brian\Documents\GitHub\UWPHook\UWPHook\bin\Release\MaterialDesignThemes.Wpf.dll"
File "C:\Users\Brian\Documents\GitHub\UWPHook\UWPHook\bin\Release\Microsoft.Management.Infrastructure.dll"
File "C:\Users\Brian\Documents\GitHub\UWPHook\UWPHook\bin\Release\Microsoft.Xaml.Behaviors.dll"
File "C:\Users\Brian\Documents\GitHub\UWPHook\UWPHook\bin\Release\Newtonsoft.Json.Bson.dll"
File "C:\Users\Brian\Documents\GitHub\UWPHook\UWPHook\bin\Release\Newtonsoft.Json.dll"
File "C:\Users\Brian\Documents\GitHub\UWPHook\UWPHook\bin\Release\Serilog.dll"
File "C:\Users\Brian\Documents\GitHub\UWPHook\UWPHook\bin\Release\Serilog.Sinks.Console.dll"
File "C:\Users\Brian\Documents\GitHub\UWPHook\UWPHook\bin\Release\Serilog.Sinks.File.dll"
File "C:\Users\Brian\Documents\GitHub\UWPHook\UWPHook\bin\Release\SharpSteam.dll"
File "C:\Users\Brian\Documents\GitHub\UWPHook\UWPHook\bin\Release\System.Buffers.dll"
File "C:\Users\Brian\Documents\GitHub\UWPHook\UWPHook\bin\Release\System.Diagnostics.DiagnosticSource.dll"
File "C:\Users\Brian\Documents\GitHub\UWPHook\UWPHook\bin\Release\System.Management.Automation.dll"
File "C:\Users\Brian\Documents\GitHub\UWPHook\UWPHook\bin\Release\System.Memory.dll"
File "C:\Users\Brian\Documents\GitHub\UWPHook\UWPHook\bin\Release\System.Net.Http.Formatting.dll"
File "C:\Users\Brian\Documents\GitHub\UWPHook\UWPHook\bin\Release\System.Numerics.Vectors.dll"
File "C:\Users\Brian\Documents\GitHub\UWPHook\UWPHook\bin\Release\System.Runtime.CompilerServices.Unsafe.dll"
File "C:\Users\Brian\Documents\GitHub\UWPHook\UWPHook\bin\Release\System.Threading.Tasks.Extensions.dll"
File "C:\Users\Brian\Documents\GitHub\UWPHook\UWPHook\bin\Release\VDFParser.dll"
File "C:\Users\Brian\Documents\GitHub\UWPHook\UWPHook\bin\Release\UWPHook.exe"
File "C:\Users\Brian\Documents\GitHub\UWPHook\UWPHook\bin\Release\UWPHook.exe.config"
File "C:\Users\Brian\Documents\GitHub\UWPHook\UWPHook\bin\Release\VDFParser.dll"
File "C:\Users\Brian\Documents\GitHub\UWPHook\UWPHook\bin\Release\Crc32.NET.dll"
File "C:\Users\Brian\Documents\GitHub\UWPHook\UWPHook\bin\Release\System.Net.Http.Formatting.dll"
File "C:\Users\Brian\Documents\GitHub\UWPHook\UWPHook\bin\Release\Newtonsoft.Json.dll"
CreateDirectory "$INSTDIR\Resources"
SetOutPath "$INSTDIR\Resources"
File "C:\Users\Brian\Documents\GitHub\UWPHook\UWPHook\bin\Release\Resources\KnownApps.json"
SectionEnd
@ -165,10 +179,15 @@ Delete "$INSTDIR\Crc32.NET.xml"
Delete "$INSTDIR\uninstall.exe"
Delete "$INSTDIR\System.Net.Http.Formatting.dll"
Delete "$INSTDIR\Newtonsoft.Json.dll"
Delete "$INSTDIR\System.dll"
Delete "$INSTDIR\Resources\KnownApps.json"
!ifdef WEB_SITE
Delete "$INSTDIR\${APP_NAME} website.url"
!endif
RmDir /r "$APPDATA\Briano"
RmDir "$INSTDIR\Resources"
RmDir "$INSTDIR"
!ifdef REG_START_MENU

@ -1,12 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<section name="UWPHook.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false"/>
<section name="UWPHook.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
</sectionGroup>
</configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2"/>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" />
</startup>
<userSettings>
<UWPHook.Properties.Settings>
@ -14,7 +14,7 @@
<value>False</value>
</setting>
<setting name="TargetLanguage" serializeAs="String">
<value/>
<value />
</setting>
<setting name="Seconds" serializeAs="String">
<value>5</value>
@ -23,11 +23,29 @@
<value>False</value>
</setting>
<setting name="SteamGridDbApiKey" serializeAs="String">
<value>617eb1e4ce186060a4b1e2ab0d468a44</value>
<value />
</setting>
<setting name="SelectedSteamGridDB_Style" serializeAs="String">
<value>0</value>
</setting>
<setting name="SelectedSteamGridDB_Type" serializeAs="String">
<value>0</value>
</setting>
<setting name="SelectedSteamGridDB_nfsw" serializeAs="String">
<value>0</value>
</setting>
<setting name="SelectedSteamGridDB_Humor" serializeAs="String">
<value>0</value>
</setting>
<setting name="OfferedSteamGridDB" serializeAs="String">
<value>False</value>
</setting>
<setting name="Tags" serializeAs="String">
<value>READY TO PLAY,XBOX</value>
</setting>
<setting name="SteamGridDB_Style" serializeAs="Xml">
<value>
<ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ArrayOfString xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<string>any</string>
<string>alternate</string>
<string>blurred</string>
@ -39,7 +57,7 @@
</setting>
<setting name="SteamGridDB_Type" serializeAs="Xml">
<value>
<ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ArrayOfString xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<string>any</string>
<string>static</string>
<string>animated</string>
@ -48,7 +66,7 @@
</setting>
<setting name="SteamGridDB_nfsw" serializeAs="Xml">
<value>
<ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ArrayOfString xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<string>false</string>
<string>any</string>
<string>true</string>
@ -57,39 +75,33 @@
</setting>
<setting name="SteamGridDB_Humor" serializeAs="Xml">
<value>
<ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ArrayOfString xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<string>false</string>
<string>any</string>
<string>true</string>
</ArrayOfString>
</value>
</setting>
<setting name="SelectedSteamGridDB_Style" serializeAs="String">
<value>0</value>
</setting>
<setting name="SelectedSteamGridDB_Type" serializeAs="String">
<value>0</value>
</setting>
<setting name="SelectedSteamGridDB_nfsw" serializeAs="String">
<value>0</value>
<setting name="LogLevel" serializeAs="Xml">
<value>
<ArrayOfString xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<string>ERROR</string>
<string>DEBUG</string>
<string>TRACE</string>
</ArrayOfString>
</value>
</setting>
<setting name="SelectedSteamGridDB_Humor" serializeAs="String">
<setting name="SelectedLogLevel" serializeAs="String">
<value>0</value>
</setting>
<setting name="OfferedSteamGridDB" serializeAs="String">
<value>False</value>
</setting>
<setting name="Tags" serializeAs="String">
<value>READY TO PLAY,XBOX</value>
</setting>
</UWPHook.Properties.Settings>
</userSettings>
<runtime>
<AppContextSwitchOverrides value="Switch.System.IO.UseLegacyPathHandling=false;Switch.System.IO.BlockLongPaths=false"/>
<AppContextSwitchOverrides value="Switch.System.IO.UseLegacyPathHandling=false;Switch.System.IO.BlockLongPaths=false" />
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0"/>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>

@ -1,15 +1,15 @@
<Application x:Class="UWPHook.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:UWPHook"
xmlns:local="clr-namespace:UWPHook" xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
StartupUri="GamesWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<materialDesign:CustomColorTheme BaseTheme="Light" PrimaryColor="Blue" SecondaryColor="MediumPurple" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Light.xaml"/>
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Defaults.xaml"/>
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesign3.Defaults.xaml"/>
<ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Primary/MaterialDesignColor.Blue.xaml"/>
<ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Accent/MaterialDesignColor.deeppurple.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>

@ -35,6 +35,16 @@ namespace UWPHook
set { _name = value; }
}
private string _executable;
/// <summary>
/// Gets or sets the executable of the application
/// </summary>
public string Executable
{
get { return _executable; }
set { _executable = value; }
}
private string _aumid;
/// <summary>
/// Gets or sets the aumid of the application
@ -77,8 +87,10 @@ namespace UWPHook
try
{
//Get every png in this directory, Steam only allows for .png's
//Get every png, jpg or jpeg in this directory, Steam only allows for .png's but jpgs work too
images.AddRange(Directory.GetFiles(_icon_path, "*.png"));
images.AddRange(Directory.GetFiles(_icon_path, "*.jpg"));
images.AddRange(Directory.GetFiles(_icon_path, "*.jpeg"));
}
catch (DirectoryNotFoundException)
{
@ -118,14 +130,11 @@ namespace UWPHook
public string isKnownApp()
{
if (_aumid.Contains("Microsoft.SeaofThieves"))
if(AppManager.IsKnownApp(_aumid, out string name))
{
return "Sea of Thieves";
}
else if (_aumid.Contains("Microsoft.DeltaPC"))
{
return "Gears of War: Ultimate Edition";
return name;
}
return "Name not found, double click here to edit";
}
@ -135,5 +144,10 @@ namespace UWPHook
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public override string ToString()
{
return $"{Name} ({Aumid})";
}
}
}

@ -1,11 +1,16 @@
using System;
using Serilog;
using Serilog.Core;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Management;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading;
using UWPHook.Properties;
namespace UWPHook
{
@ -14,7 +19,9 @@ namespace UWPHook
/// </summary>
static class AppManager
{
private static int id;
private static int runningProcessId;
private static bool isLauncherProcess;
private static string executablePath;
/// <summary>
/// Launch a UWP App using a ApplicationActivationManager and sets a internal id to launched proccess id
@ -22,29 +29,33 @@ namespace UWPHook
/// <param name="aumid">The AUMID of the app to launch</param>
public static void LaunchUWPApp(string[] args)
{
string aumid = args[1]; // We receive the args from Steam,
// 0 is application location,
// 1 is the aumid, the rest are extras
// We receive the args from Steam,
// 0 is application location,
// 1 is the aumid,
// 2 is the executable, the rest are extras
string aumid = args[1];
executablePath = args[2].Contains("/") ? args[2].Replace('/', '\\') : args[2];
Log.Verbose("Arguments => " + String.Join("/", args));
var mgr = new ApplicationActivationManager();
uint processId;
string extra_args = String.Join(" ", args.Skip(2)
.Take(args.Length - 2)
string extra_args = String.Join(" ", args.Skip(3)
.Take(args.Length - 3)
.Select(eachElement => eachElement.Clone()
).ToArray());
try
{
mgr.ActivateApplication(aumid, extra_args, ActivateOptions.None, out processId);
//Bring the launched app to the foreground, this fixes in-home streaming
id = (int)processId;
runningProcessId = (int) processId;
Log.Verbose("Process ID => " + runningProcessId.ToString());
//Bring the launched app to the foreground, this fixes in-home streaming
BringProcess();
}
catch (Exception e)
{
Log.Error("Error while trying to launch your app." + Environment.NewLine + e.Message);
throw new Exception("Error while trying to launch your app." + Environment.NewLine + e.Message);
}
}
@ -55,25 +66,91 @@ namespace UWPHook
/// <returns>True if the perviously launched app is running, false otherwise</returns>
public static Boolean IsRunning()
{
//If 0, no app was launched most probably
if (id == 0)
try
{
return false;
Log.Debug("Checking PID => " + runningProcessId.ToString());
// PID 0 means an error during launch for the game
// (Example : Game no more available on gamepass or problem with installation) so instant exit in this case
if (runningProcessId == 0)
{
Log.Debug("PID is 0");
return false;
}
Process.GetProcessById(runningProcessId);
Log.Debug("Process is running");
return true;
}
try
catch
{
Process.GetProcessById(id);
// Check only at launch if started by a launcher
if (!isLauncherProcess)
{
Log.Debug("initial PID is not running anymore, checking other possible process runing before stop");
bool secondCheck = false;
do
{
// Handle process running by some launcher by checking their executable path and name
var processes = GetProcess();
foreach (var process in processes)
{
string executableFile = executablePath.Contains('\\') ? executablePath.Substring(executablePath.LastIndexOf('\\') + 1) : executablePath;
Log.Verbose("Process " + process.Value.Path + " contains " + executablePath + " ? : " + process.Value.Path.Contains(executablePath).ToString());
Log.Verbose("Process " + process.Key + " contains " + executableFile + " ? : " + process.Key.Contains(executableFile).ToString());
if (process.Value.Path.Contains(executablePath) || process.Key.Contains(executableFile))
{
int pid = process.Value.Pid;
Log.Verbose($"Launcher opened child process ({runningProcessId}->{pid}), using new process as target");
runningProcessId = pid;
isLauncherProcess = true;
//bring the "real" launched process
BringProcess();
return true;
}
}
// Handle the last chance if process was not found due to slow running like Farming Simulator 2022 or Halo MCC
secondCheck = !secondCheck;
if (secondCheck)
{
Log.Debug("Process has not been found. Last chance to find it !");
Thread.Sleep(Settings.Default.Seconds * 5000);
}
} while (secondCheck);
}
}
catch (Exception)
return false;
}
/// <summary>
/// Find process path with their dedicated pid
/// </summary>
/// <returns>Map of processes to their path and pid. Any process in this object may have already terminated</returns>
private static Dictionary<string, (string Path, int Pid)> GetProcess()
{
var result = new Dictionary<string, (string Path, int Pid)>();
using (var searcher = new ManagementObjectSearcher("select processid, Name, ExecutablePath from win32_process"))
{
return false;
foreach (var process in searcher.Get())
{
string processName = Convert.ToString(process.Properties["Name"].Value);
int processId = Convert.ToInt32(process.Properties["processid"].Value);
string processPath = Convert.ToString(process.Properties["ExecutablePath"].Value);
if (String.IsNullOrWhiteSpace(processName) || result.ContainsKey(processName)) continue;
result.Add(processName, (processPath, processId));
}
}
return true;
return result;
}
/// <summary>
/// Gets a list of installed UWP Apps on the system, containing each app name + AUMID, separated by '|'
/// Gets a list of installed UWP Apps on the system, containing each app name + AUMID + executable path, separated by '|'
/// </summary>
/// <returns>List of installed UWP Apps</returns>
public static List<String> GetInstalledApps()
@ -95,12 +172,37 @@ namespace UWPHook
}
catch (Exception e)
{
Log.Error("Error trying to get installed apps on your PC " + Environment.NewLine + e.Message, e.InnerException);
throw new Exception("Error trying to get installed apps on your PC " + Environment.NewLine + e.Message, e.InnerException);
}
return result;
}
/// <summary>
/// Try to convert an aumid into a human-readable app name
/// </summary>
/// <param name="appName">Application user model ID (aumid)</param>
/// <param name="readableName">User-friendly app name</param>
/// <returns>Whether this is a known app</returns>
public static bool IsKnownApp(string appName, out string readableName)
{
string appsJson = File.ReadAllText(@"Resources\KnownApps.json");
var apps = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, string>>(appsJson);
foreach (var kvp in apps)
{
if (appName.StartsWith(kvp.Key + "_"))
{
readableName = kvp.Value;
return true;
}
}
readableName = null;
return false;
}
[DllImport("user32.dll")]
private static extern
bool SetForegroundWindow(IntPtr hWnd);
@ -123,8 +225,7 @@ namespace UWPHook
        const int SW_SHOWDEFAULT = 10;
        */
var me = Process.GetCurrentProcess();
var arrProcesses = Process.GetProcessById(id);
var arrProcesses = Process.GetProcessById(runningProcessId);
// get the window handle
IntPtr hWnd = arrProcesses.MainWindowHandle;

@ -20,7 +20,7 @@
<RowDefinition Height="147*"/>
<RowDefinition Height="65.6"/>
</Grid.RowDefinitions>
<materialDesign:ColorZone Padding="16" materialDesign:ShadowAssist.ShadowDepth="Depth2" Mode="PrimaryMid" Height="80" Margin="0,0,-0.4,0">
<materialDesign:ColorZone Padding="16" materialDesign:ShadowAssist.Darken="True" Mode="PrimaryMid" Height="80" Margin="0,0,-0.4,0">
<Label x:Name="label1" Content="Welcome to UWPHook, the easier way to add UWP games and apps to Steam!" HorizontalAlignment="Left" Margin="172,-14,0,0" VerticalAlignment="Top" Foreground="#DDFFFFFF"/>
</materialDesign:ColorZone>
<Image x:Name="image" HorizontalAlignment="Left" Width="178" Height="80" VerticalAlignment="Top" Source="Resources/WhiteTransparent.png" Stretch="UniformToFill" ToolTip="Welcome to UWPHook, add your UWP apps and games to Steam!"/>

@ -30,7 +30,7 @@ namespace UWPHook
BaseTheme darkTheme = BaseTheme.Dark;
var theme = Theme.Create(darkTheme.GetBaseTheme(),
var theme = Theme.Create(darkTheme,
SwatchHelper.Lookup[(MaterialDesignColor)PrimaryColor.DeepPurple],
SwatchHelper.Lookup[(MaterialDesignColor)SecondaryColor.Lime]);

@ -18,7 +18,7 @@
<RowDefinition Height="144*"/>
<RowDefinition Height="19*"/>
</Grid.RowDefinitions>
<materialDesign:ColorZone Padding="16" materialDesign:ShadowAssist.ShadowDepth="Depth2" Mode="PrimaryMid" Height="80">
<materialDesign:ColorZone Padding="16" materialDesign:ShadowAssist.Darken="True" Mode="PrimaryMid" Height="80">
<Label x:Name="label1" Content="Welcome to UWPHook, the easier way to add UWP apps and XGP games and apps to Steam!" HorizontalAlignment="Left" Margin="172,-14,0,0" VerticalAlignment="Top" Foreground="#DDFFFFFF"/>
</materialDesign:ColorZone>
<Image x:Name="image" HorizontalAlignment="Left" Width="178" Height="80" VerticalAlignment="Top" Source="Resources/WhiteTransparent.png" Stretch="UniformToFill" ToolTip="Welcome to UWPHook, add your UWP apps and games to Steam!"/>
@ -39,7 +39,7 @@
</Grid>
<Button Content="Export selected apps to Steam" Click="ExportButton_Click" HorizontalAlignment="Right" Margin="0,0,10,10" Grid.Row="2" VerticalAlignment="Bottom" Width="227"/>
<ProgressBar Visibility="Collapsed" x:Name="progressBar" Margin="10,215,10,174" Grid.Row="1" IsIndeterminate="True" />
<Label Content="Filter AUMIDs:" HorizontalAlignment="Left" Margin="5,16,0,0" Grid.Row="2" VerticalAlignment="Top"/>
<TextBox x:Name="textBox" HorizontalAlignment="Left" Height="25" Margin="104,17,0,0" Grid.Row="2" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="217" TextChanged="textBox_TextChanged"/>
<Label Content="Filter:" HorizontalAlignment="Left" Margin="5,16,0,0" Grid.Row="2" VerticalAlignment="Top"/>
<TextBox x:Name="textBox" HorizontalAlignment="Left" Height="25" Margin="50,17,0,0" Grid.Row="2" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="271" TextChanged="textBox_TextChanged"/>
</Grid>
</Window>

@ -1,8 +1,11 @@
using Force.Crc32;
using Force.Crc32;
using Serilog;
using Serilog.Core;
using SharpSteam;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.Globalization;
@ -27,21 +30,40 @@ namespace UWPHook
{
AppEntryModel Apps;
BackgroundWorker bwrLoad;
static LoggingLevelSwitch levelSwitch = new LoggingLevelSwitch();
public GamesWindow()
{
InitializeComponent();
Log.Debug("Init GamesWindow");
Apps = new AppEntryModel();
var args = Environment.GetCommandLineArgs();
//If null or 1, the app was launched normally
if (args != null)
// Init log file to AppData\Roaming\Briano\UWPHook directory with size rotation on 10Mb with max 5 files
System.Reflection.Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly();
FileVersionInfo fvi = System.Diagnostics.FileVersionInfo.GetVersionInfo(assembly.Location);
string loggerFilePath = String.Join("\\", Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), fvi.CompanyName, fvi.ProductName, "application.log");
Log.Logger = new LoggerConfiguration()
.MinimumLevel.ControlledBy(levelSwitch)
.WriteTo.File(path: loggerFilePath, rollOnFileSizeLimit: true, fileSizeLimitBytes: 10485760, retainedFileCountLimit: 5)
.WriteTo.Console()
.CreateLogger();
// Switch to Info by default to inform logger level in log file and switch to the correct log level
levelSwitch.MinimumLevel = Serilog.Events.LogEventLevel.Information;
SetLogLevel();
// If null or 1, the app was launched normally
if (args?.Length > 1)
{
//When length is 1, the only argument is the path where the app is installed
if (Environment.GetCommandLineArgs().Length > 1)
{
_ = LauncherAsync(args);
}
// When length is 1, the only argument is the path where the app is installed
_ = LauncherAsync(args); // Launches the requested game
}
else
{
//auto refresh on load
LoadButton_Click(null, null);
}
}
@ -54,6 +76,12 @@ namespace UWPHook
await Task.Delay(10000);
}
/// <summary>
/// Main task that launches a game
/// Usually invoked by steam
/// </summary>
/// <param name="args">launch args received from the program execution</param>
/// <returns></returns>
private async Task LauncherAsync(string[] args)
{
FullScreenLauncher launcher = null;
@ -112,6 +140,13 @@ namespace UWPHook
}
}
/// <summary>
/// Generates a CRC32 hash expected by Steam to link an image with a game in the library
/// See https://blog.yo1.dog/calculate-id-for-non-steam-games-js/ for an example
/// </summary>
/// <param name="appName">The name of the executable to be displayed</param>
/// <param name="appTarget">The executable target path</param>
/// <returns></returns>
private UInt64 GenerateSteamGridAppId(string appName, string appTarget)
{
byte[] nameTargetBytes = Encoding.UTF8.GetBytes(appTarget + appName + "");
@ -121,18 +156,55 @@ namespace UWPHook
return gameId;
}
/// <summary>
/// Task responsible for triggering the export, blocks the UI, and shows a message
/// once the task is finished, unlocking the UI
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private async void ExportButton_Click(object sender, RoutedEventArgs e)
{
grid.IsEnabled = false;
progressBar.Visibility = Visibility.Visible;
await ExportGames();
bool result = false, restartSteam = true;
string msg = String.Empty;
try
{
await ExportGames();
await RestartSteam(restartSteam);
msg = "Your apps were successfuly exported!";
if (!restartSteam)
{
msg += " Please restart Steam in order to see them.";
}
else if (result)
{
msg += " Steam has been restarted.";
}
}
catch (TaskCanceledException exception)
{
Log.Error(exception.Message);
msg = exception.Message;
}
grid.IsEnabled = true;
progressBar.Visibility = Visibility.Collapsed;
MessageBox.Show("Your apps were successfuly exported, please restart Steam in order to see your apps.", "UWPHook", MessageBoxButton.OK, MessageBoxImage.Information);
MessageBox.Show(msg, "UWPHook", MessageBoxButton.OK, MessageBoxImage.Information);
}
/// <summary>
/// Downloads the given image in the url to a given path in a given format
/// </summary>
/// <param name="imageUrl">The url for the image</param>
/// <param name="destinationFilename">Path to store the image</param>
/// <param name="format"></param>
/// <returns></returns>
private async Task SaveImage(string imageUrl, string destinationFilename, ImageFormat format)
{
await Task.Run(() =>
@ -143,8 +215,9 @@ namespace UWPHook
{
stream = client.OpenRead(imageUrl);
}
catch (Exception e)
catch (Exception exception)
{
Log.Error(exception.Message);
//Image with error?
//Skip for now
}
@ -157,20 +230,24 @@ namespace UWPHook
stream.Close();
client.Dispose();
}
});
});
}
/// <summary>
/// Copies all temporary images to the given user
/// </summary>
/// <param name="user">The user path to copy images to</param>
private void CopyTempGridImagesToSteamUser(string user)
{
{
string tmpGridDirectory = Path.GetTempPath() + "UWPHook\\tmp_grid\\";
string userGridDirectory = user + "\\config\\grid\\";
// No images were downloaded, maybe the key is invalid or no app had an image
if (!Directory.Exists(tmpGridDirectory))
{
return;
}
string[] images = Directory.GetFiles(tmpGridDirectory);
if (!Directory.Exists(userGridDirectory))
@ -194,28 +271,44 @@ namespace UWPHook
}
}
/// <summary>
/// Task responsible for downloading grid images to a temporary location,
/// generates the steam ID for the game based in the receiving parameters,
/// Throws TaskCanceledException if cannot communicate with SteamGridDB properly
/// </summary>
/// <param name="appName">The name of the app</param>
/// <param name="appTarget">The target path of the executable</param>
/// <returns></returns>
private async Task DownloadTempGridImages(string appName, string appTarget)
{
SteamGridDbApi api = new SteamGridDbApi(Properties.Settings.Default.SteamGridDbApiKey);
string tmpGridDirectory = Path.GetTempPath() + "UWPHook\\tmp_grid\\";
GameResponse[] games = null;
var games = await api.SearchGame(appName);
try
{
games = await api.SearchGame(appName);
}
catch (TaskCanceledException exception)
{
Log.Error(exception.Message);
}
if (games != null)
{
var game = games[0];
Log.Verbose("Detected Game: " + game.ToString());
UInt64 gameId = GenerateSteamGridAppId(appName, appTarget);
if (!Directory.Exists(tmpGridDirectory))
{
Directory.CreateDirectory(tmpGridDirectory);
}
SafellyCreateTmpGridDirectory(tmpGridDirectory);
var gameGridsVertical = api.GetGameGrids(game.Id, "600x900,342x482,660x930");
var gameGridsHorizontal = api.GetGameGrids(game.Id, "460x215,920x430");
var gameHeroes = api.GetGameHeroes(game.Id);
var gameLogos = api.GetGameLogos(game.Id);
Log.Verbose("Game ID: " + game.Id);
await Task.WhenAll(
gameGridsVertical,
gameGridsHorizontal,
@ -258,7 +351,32 @@ namespace UWPHook
}
}
private async Task ExportGames()
private void SafellyCreateTmpGridDirectory(string tmpGridDirectory)
{
if (!Directory.Exists(tmpGridDirectory))
{
try
{
Directory.CreateDirectory(tmpGridDirectory);
Log.Information("Created directory: " + tmpGridDirectory);
}
catch (Exception exception)
{
Log.Error(exception.Message);
Log.Error(exception.StackTrace);
throw new Exception("UWPHook was not able to create the tmp directory for some reason." + Environment.NewLine +
"You may solve this by manually creating the following folder:" + Environment.NewLine +
tmpGridDirectory);
}
}
}
/// <summary>
/// Main Task to export the selected games to steam
/// </summary>
/// <param name="restartSteam"></param>
/// <returns></returns>
private async Task<bool> ExportGames()
{
string[] tags = Settings.Default.Tags.Split(',');
string steam_folder = SteamManager.GetSteamFolder();
@ -272,18 +390,25 @@ namespace UWPHook
List<Task> gridImagesDownloadTasks = new List<Task>();
bool downloadGridImages = !String.IsNullOrEmpty(Properties.Settings.Default.SteamGridDbApiKey);
//To make things faster, decide icons and download grid images before looping users
Log.Verbose("downloadGridImages: " + (downloadGridImages));
foreach (var app in selected_apps)
{
app.Icon = app.widestSquareIcon();
if (downloadGridImages)
{
Log.Verbose("Downloading grid images for app " + app.Name);
gridImagesDownloadTasks.Add(DownloadTempGridImages(app.Name, exePath));
}
}
await Task.WhenAll(gridImagesDownloadTasks);
// Export the selected apps and the downloaded images to each user
// in the steam folder by modifying it's VDF file
foreach (var user in users)
{
try
@ -298,6 +423,7 @@ namespace UWPHook
//If it's a short VDF, let's just overwrite it
if (ex.GetType() != typeof(VDFTooShortException))
{
Log.Error("Error: Program failed to load existing Steam shortcuts." + Environment.NewLine + ex.Message);
throw new Exception("Error: Program failed to load existing Steam shortcuts." + Environment.NewLine + ex.Message);
}
}
@ -306,12 +432,35 @@ namespace UWPHook
{
foreach (var app in selected_apps)
{
try
{
app.Icon = PersistAppIcon(app);
Log.Verbose("Defaulting to app.Icon for app " + app.Name);
}
catch (System.IO.IOException)
{
Log.Verbose("Using backup icon for app " + app.Name);
await Task.Run(() =>
{
string tmpGridDirectory = Path.GetTempPath() + "UWPHook\\tmp_grid\\";
SafellyCreateTmpGridDirectory(tmpGridDirectory);
string[] images = Directory.GetFiles(tmpGridDirectory);
UInt64 gameId = GenerateSteamGridAppId(app.Name, exePath);
app.Icon = PersistAppIcon(app, tmpGridDirectory + gameId + "_logo.png");
});
}
VDFEntry newApp = new VDFEntry()
{
appid = ((int)GenerateSteamGridAppId(app.Name, exePath)),
AppName = app.Name,
Exe = exePath,
StartDir = exeDir,
LaunchOptions = app.Aumid,
LaunchOptions = app.Aumid + " " + app.Executable,
AllowDesktopConfig = 1,
AllowOverlay = 1,
Icon = app.Icon,
@ -324,10 +473,25 @@ namespace UWPHook
DevkitGameID = "",
LastPlayTime = (int)DateTimeOffset.UtcNow.ToUnixTimeSeconds(),
};
Boolean shortcutAlreadyExists = false;
for (int i = 0; i < shortcuts.Length; i++)
{
Log.Verbose(shortcuts[i].ToString());
if (shortcuts[i].AppName == app.Name && shortcuts[i].Exe == exePath)
{
shortcutAlreadyExists = true;
Log.Verbose(app.Name + " already added to Steam. Updating existing shortcut.");
shortcuts[i] = newApp;
}
}
//Resize this array so it fits the new entries
Array.Resize(ref shortcuts, shortcuts.Length + 1);
shortcuts[shortcuts.Length - 1] = newApp;
if (!shortcutAlreadyExists)
{
//Resize this array so it fits the new entries
Array.Resize(ref shortcuts, shortcuts.Length + 1);
shortcuts[shortcuts.Length - 1] = newApp;
}
}
try
@ -336,17 +500,23 @@ namespace UWPHook
{
Directory.CreateDirectory(user + @"\\config\\");
}
BackupShortcutsVDF(user, @"\\config\\shortcuts.vdf");
//Write the file with all the shortcuts
File.WriteAllBytes(user + @"\\config\\shortcuts.vdf", VDFSerializer.Serialize(shortcuts));
Log.Debug("Shortcuts written to " + user + @"\\config\\shortcuts.vdf");
}
catch (Exception ex)
{
Log.Error("Error: Program failed while trying to write your Steam shortcuts" + Environment.NewLine + ex.InnerException + ex.StackTrace);
throw new Exception("Error: Program failed while trying to write your Steam shortcuts" + Environment.NewLine + ex.Message);
}
}
}
catch (Exception ex)
{
Log.Error("Error: Program failed exporting your games:" + Environment.NewLine + ex.Message + ex.StackTrace);
MessageBox.Show("Error: Program failed exporting your games:" + Environment.NewLine + ex.Message + ex.StackTrace);
}
}
@ -366,8 +536,168 @@ namespace UWPHook
});
}
}
return true;
}
private void BackupShortcutsVDF(string userPath, string vdfSubPath)
{
string backupFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Briano", "UWPHook", "backups");
if (!Directory.Exists(backupFolder))
{
Directory.CreateDirectory(backupFolder);
Log.Debug("Created backup folder: " + backupFolder);
}
string user_id = userPath.Split('\\').Last();
string sourceFilePath = Path.Combine(userPath, "config", "shortcuts.vdf");
string destinationFileName = Path.Combine(backupFolder, $"{user_id}_{DateTime.Now.ToString("yyyyMMddHHmmss")}_shortcuts.vdf");
File.Copy(sourceFilePath, destinationFileName);
Log.Debug("Backup created: " + destinationFileName);
}
/// <summary>
/// Copies an apps icon to a intermediate location
/// Due to some apps changing the icon location when they update, which causes icons to be "lost"
/// </summary>
/// <param name="app">App to copy the icon to</param>
/// <param name="forcedIcon">Overwrites the app.icon to be copied</param>
/// <returns>string, the path to the usable and persisted icon</returns>
private string PersistAppIcon(AppEntry app, string forcedIcon = "")
{
string path = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
string icons_path = path + @"\Briano\UWPHook\icons\";
// If we do not have an specific icon to copy, copy app.icon, if we do, copy the specified icon
string icon_to_copy = String.IsNullOrEmpty(forcedIcon) ? app.Icon : forcedIcon;
if (!Directory.Exists(icons_path))
{
Directory.CreateDirectory(icons_path);
}
string dest_file = String.Join(String.Empty, icons_path, app.Aumid + Path.GetFileName(icon_to_copy));
try
{
if (File.Exists(icon_to_copy))
{
File.Copy(icon_to_copy, dest_file, true);
}
else
{
dest_file = app.Icon;
}
}
catch (System.IO.IOException e)
{
Log.Warning(e, "Could not copy icon " + app.Icon);
throw e;
}
return dest_file;
}
/// <summary>
/// Restarts the Steam.exe process
/// </summary>
/// <param name="restartSteam"></param>
/// <returns></returns>
private async Task<bool> RestartSteam(bool restartSteam)
{
Func<Process> getSteam = () => Process.GetProcessesByName("steam").SingleOrDefault();
Process steam = getSteam();
if (steam != null)
{
string steamExe = steam.MainModule.FileName;
//we always ask politely
Log.Debug("Requesting Steam shutdown");
Process.Start(steamExe, "-exitsteam");
bool restarted = false;
Stopwatch watch = new Stopwatch();
watch.Start();
//give it N seconds to sort itself out
int waitSeconds = 8;
while (!restarted || watch.Elapsed.TotalSeconds < waitSeconds)
{
await Task.Delay(TimeSpan.FromSeconds(0.5f));
if (getSteam() == null)
{
Log.Debug("Restarting Steam");
Process.Start(steamExe);
restarted = true;
break;
}
}
if (!restarted)
{
Log.Debug("Steam instance not restarted");
MessageBox.Show("Failed to restart Steam, please launch it manually", "Error", MessageBoxButton.OK, MessageBoxImage.Warning);
return false;
}
}
else
{
Log.Debug("Steam instance not found to be restarted");
}
return true;
}
public static void ClearAllShortcuts()
{
Log.Debug("Clearing all elements in shortcuts.vdf");
string[] tags = Settings.Default.Tags.Split(',');
string steam_folder = SteamManager.GetSteamFolder();
if (Directory.Exists(steam_folder))
{
var users = SteamManager.GetUsers(steam_folder);
var exePath = @"""" + System.Reflection.Assembly.GetExecutingAssembly().Location + @"""";
var exeDir = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
foreach (var user in users)
{
try
{
VDFEntry[] shortcuts = new VDFEntry[0];
try
{
if (!Directory.Exists(user + @"\\config\\"))
{
Directory.CreateDirectory(user + @"\\config\\");
}
//Write the file with all the shortcuts
File.WriteAllBytes(user + @"\\config\\shortcuts.vdf", VDFSerializer.Serialize(shortcuts));
}
catch (Exception ex)
{
Log.Error("Error: Program failed while trying to write your Steam shortcuts" + Environment.NewLine + ex.Message);
throw new Exception("Error: Program failed while trying to write your Steam shortcuts" + Environment.NewLine + ex.Message);
}
}
catch (Exception ex)
{
Log.Error("Error: Program failed while trying to clear your Steam shortcuts:" + Environment.NewLine + ex.Message + ex.StackTrace);
MessageBox.Show("Error: Program failed while trying to clear your Steam shortcuts:" + Environment.NewLine + ex.Message + ex.StackTrace);
}
}
MessageBox.Show("All non-Steam shortcuts has been cleared.");
}
}
/// <summary>
/// Fires the Bwr_DoWork, to load the apps installed at the machine
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void LoadButton_Click(object sender, RoutedEventArgs e)
{
bwrLoad = new BackgroundWorker();
@ -375,12 +705,19 @@ namespace UWPHook
bwrLoad.RunWorkerCompleted += Bwr_RunWorkerCompleted;
grid.IsEnabled = false;
label.Content = "Loading your installed apps";
progressBar.Visibility = Visibility.Visible;
Apps.Entries = new System.Collections.ObjectModel.ObservableCollection<AppEntry>();
bwrLoad.RunWorkerAsync();
}
/// <summary>
/// Callback for restoring the grid list interactivity
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Bwr_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
listGames.ItemsSource = Apps.Entries;
@ -393,6 +730,11 @@ namespace UWPHook
label.Content = "Installed Apps";
}
/// <summary>
/// Worker responsible for loading the apps installed in the machine
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Bwr_DoWork(object sender, DoWorkEventArgs e)
{
try
@ -417,30 +759,26 @@ namespace UWPHook
//Remove end lines from the String and split both values, I split the appname and the AUMID using |
//I hope no apps have that in their name. Ever.
var values = app.Replace("\r\n", "").Split('|');
if (values.Length >= 3 && AppManager.IsKnownApp(values[2], out string readableName))
{
values[0] = readableName;
}
if (!String.IsNullOrWhiteSpace(values[0]))
{
//We get the default square tile to find where the app stores it's icons, then we resolve which one is the widest
string logosPath = Path.GetDirectoryName(values[1]);
Application.Current.Dispatcher.BeginInvoke((Action)delegate ()
{
Apps.Entries.Add(new AppEntry() { Name = values[0], IconPath = logosPath, Aumid = values[2], Selected = false });
Apps.Entries.Add(new AppEntry() { Name = values[0], Executable = values[3], IconPath = logosPath, Aumid = values[2], Selected = false });
});
}
if (values.Length > 2)
{
if (values[2].Contains("Microsoft.SeaofThieves"))
{
values[0] = "Sea of Thieves";
}
else if (values[2].Contains("Microsoft.DeltaPC"))
{
values[0] = "Gears of War: Ultimate Edition";
}
}
}
}
catch (Exception ex)
{
Log.Error(ex.Message);
MessageBox.Show(ex.Message, "UWPHook", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
@ -463,7 +801,7 @@ namespace UWPHook
public bool Contains(object o)
{
AppEntry appEntry = o as AppEntry;
return (appEntry.Aumid.ToLower().Contains(textBox.Text.ToLower()));
return (appEntry.Aumid.ToLower().Contains(textBox.Text.ToLower()) || appEntry.Name.ToLower().Contains(textBox.Text.ToLower()));
}
private void SettingsButton_Click(object sender, RoutedEventArgs e)
@ -472,10 +810,18 @@ namespace UWPHook
window.ShowDialog();
}
/// <summary>
/// Function that executes when the Games Window is loaded
/// Will inform the user of the possibility of using the SteamGridDB API
/// redirecting him to the settings page if he wishes to use the functionality
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Window_Loaded(object sender, RoutedEventArgs e)
{
if (String.IsNullOrEmpty(Settings.Default.SteamGridDbApiKey) && !Settings.Default.OfferedSteamGridDB)
if (!Settings.Default.OfferedSteamGridDB)
{
Settings.Default.SteamGridDbApiKey = "";
Settings.Default.OfferedSteamGridDB = true;
Settings.Default.Save();
@ -486,5 +832,24 @@ namespace UWPHook
}
}
}
public static void SetLogLevel()
{
switch (Settings.Default.SelectedLogLevel)
{
case 1:
Log.Information("Init log with DEBUG level.");
levelSwitch.MinimumLevel = Serilog.Events.LogEventLevel.Debug;
break;
case 2:
Log.Information("Init log with TRACE level.");
levelSwitch.MinimumLevel = Serilog.Events.LogEventLevel.Verbose;
break;
default:
Log.Information("Init log with ERROR level.");
levelSwitch.MinimumLevel = Serilog.Events.LogEventLevel.Error;
break;
}
}
}
}

@ -12,7 +12,7 @@ using System.Windows;
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Briano")]
[assembly: AssemblyProduct("UWPHook")]
[assembly: AssemblyCopyright("Copyright Brian Lima © 2020")]
[assembly: AssemblyCopyright("Copyright Brian Lima © 2020 2021 2022")]
[assembly: AssemblyTrademark("Briano")]
[assembly: AssemblyCulture("")]
@ -51,6 +51,6 @@ using System.Windows;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.9.2.0")]
[assembly: AssemblyFileVersion("2.9.2.0")]
[assembly: AssemblyVersion("2.14.0.0")]
[assembly: AssemblyFileVersion("2.14.0.0")]
[assembly: NeutralResourcesLanguage("en")]

@ -19,7 +19,7 @@ namespace UWPHook.Properties {
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
public class Resources {

@ -1,10 +1,10 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
// Ce code a été généré par un outil.
// Version du runtime :4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// Les modifications apportées à ce fichier peuvent provoquer un comportement incorrect et seront perdues si
// le code est régénéré.
// </auto-generated>
//------------------------------------------------------------------------------
@ -12,7 +12,7 @@ namespace UWPHook.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.8.1.0")]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.3.0.0")]
public sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
@ -73,7 +73,7 @@ namespace UWPHook.Properties {
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("617eb1e4ce186060a4b1e2ab0d468a44")]
[global::System.Configuration.DefaultSettingValueAttribute("")]
public string SteamGridDbApiKey {
get {
return ((string)(this["SteamGridDbApiKey"]));
@ -85,138 +85,165 @@ namespace UWPHook.Properties {
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute(@"<?xml version=""1.0"" encoding=""utf-16""?>
<ArrayOfString xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"">
<string>any</string>
<string>alternate</string>
<string>blurred</string>
<string>white_logo</string>
<string>material</string>
<string>no_logo </string>
</ArrayOfString>")]
public global::System.Collections.Specialized.StringCollection SteamGridDB_Style {
[global::System.Configuration.DefaultSettingValueAttribute("0")]
public int SelectedSteamGridDB_Style {
get {
return ((global::System.Collections.Specialized.StringCollection)(this["SteamGridDB_Style"]));
return ((int)(this["SelectedSteamGridDB_Style"]));
}
set {
this["SteamGridDB_Style"] = value;
this["SelectedSteamGridDB_Style"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("<?xml version=\"1.0\" encoding=\"utf-16\"?>\r\n<ArrayOfString xmlns:xsi=\"http://www.w3." +
"org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">\r\n <s" +
"tring>any</string>\r\n <string>static</string>\r\n <string>animated</string>\r\n</Ar" +
"rayOfString>")]
public global::System.Collections.Specialized.StringCollection SteamGridDB_Type {
[global::System.Configuration.DefaultSettingValueAttribute("0")]
public int SelectedSteamGridDB_Type {
get {
return ((global::System.Collections.Specialized.StringCollection)(this["SteamGridDB_Type"]));
return ((int)(this["SelectedSteamGridDB_Type"]));
}
set {
this["SteamGridDB_Type"] = value;
this["SelectedSteamGridDB_Type"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("<?xml version=\"1.0\" encoding=\"utf-16\"?>\r\n<ArrayOfString xmlns:xsi=\"http://www.w3." +
"org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">\r\n <s" +
"tring>false</string>\r\n <string>any</string>\r\n <string>true</string>\r\n</ArrayOf" +
"String>")]
public global::System.Collections.Specialized.StringCollection SteamGridDB_nfsw {
[global::System.Configuration.DefaultSettingValueAttribute("0")]
public int SelectedSteamGridDB_nfsw {
get {
return ((global::System.Collections.Specialized.StringCollection)(this["SteamGridDB_nfsw"]));
return ((int)(this["SelectedSteamGridDB_nfsw"]));
}
set {
this["SteamGridDB_nfsw"] = value;
this["SelectedSteamGridDB_nfsw"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("<?xml version=\"1.0\" encoding=\"utf-16\"?>\r\n<ArrayOfString xmlns:xsi=\"http://www.w3." +
"org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">\r\n <s" +
"tring>false</string>\r\n <string>any</string>\r\n <string>true</string>\r\n</ArrayOf" +
"String>")]
public global::System.Collections.Specialized.StringCollection SteamGridDB_Humor {
[global::System.Configuration.DefaultSettingValueAttribute("0")]
public int SelectedSteamGridDB_Humor {
get {
return ((global::System.Collections.Specialized.StringCollection)(this["SteamGridDB_Humor"]));
return ((int)(this["SelectedSteamGridDB_Humor"]));
}
set {
this["SteamGridDB_Humor"] = value;
this["SelectedSteamGridDB_Humor"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("0")]
public int SelectedSteamGridDB_Style {
[global::System.Configuration.DefaultSettingValueAttribute("False")]
public bool OfferedSteamGridDB {
get {
return ((int)(this["SelectedSteamGridDB_Style"]));
return ((bool)(this["OfferedSteamGridDB"]));
}
set {
this["SelectedSteamGridDB_Style"] = value;
this["OfferedSteamGridDB"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("0")]
public int SelectedSteamGridDB_Type {
[global::System.Configuration.DefaultSettingValueAttribute("READY TO PLAY,XBOX")]
public string Tags {
get {
return ((int)(this["SelectedSteamGridDB_Type"]));
return ((string)(this["Tags"]));
}
set {
this["SelectedSteamGridDB_Type"] = value;
this["Tags"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("0")]
public int SelectedSteamGridDB_nfsw {
[global::System.Configuration.DefaultSettingValueAttribute(@"<?xml version=""1.0"" encoding=""utf-16""?>
<ArrayOfString xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"">
<string>any</string>
<string>alternate</string>
<string>blurred</string>
<string>white_logo</string>
<string>material</string>
<string>no_logo </string>
</ArrayOfString>")]
public global::System.Collections.Specialized.StringCollection SteamGridDB_Style {
get {
return ((int)(this["SelectedSteamGridDB_nfsw"]));
return ((global::System.Collections.Specialized.StringCollection)(this["SteamGridDB_Style"]));
}
set {
this["SelectedSteamGridDB_nfsw"] = value;
this["SteamGridDB_Style"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("0")]
public int SelectedSteamGridDB_Humor {
[global::System.Configuration.DefaultSettingValueAttribute("<?xml version=\"1.0\" encoding=\"utf-16\"?>\r\n<ArrayOfString xmlns:xsd=\"http://www.w3." +
"org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\r\n <s" +
"tring>any</string>\r\n <string>static</string>\r\n <string>animated</string>\r\n</Ar" +
"rayOfString>")]
public global::System.Collections.Specialized.StringCollection SteamGridDB_Type {
get {
return ((int)(this["SelectedSteamGridDB_Humor"]));
return ((global::System.Collections.Specialized.StringCollection)(this["SteamGridDB_Type"]));
}
set {
this["SelectedSteamGridDB_Humor"] = value;
this["SteamGridDB_Type"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("False")]
public bool OfferedSteamGridDB {
[global::System.Configuration.DefaultSettingValueAttribute("<?xml version=\"1.0\" encoding=\"utf-16\"?>\r\n<ArrayOfString xmlns:xsd=\"http://www.w3." +
"org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\r\n <s" +
"tring>false</string>\r\n <string>any</string>\r\n <string>true</string>\r\n</ArrayOf" +
"String>")]
public global::System.Collections.Specialized.StringCollection SteamGridDB_nfsw {
get {
return ((bool)(this["OfferedSteamGridDB"]));
return ((global::System.Collections.Specialized.StringCollection)(this["SteamGridDB_nfsw"]));
}
set {
this["OfferedSteamGridDB"] = value;
this["SteamGridDB_nfsw"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("READY TO PLAY,XBOX")]
public string Tags {
[global::System.Configuration.DefaultSettingValueAttribute("<?xml version=\"1.0\" encoding=\"utf-16\"?>\r\n<ArrayOfString xmlns:xsd=\"http://www.w3." +
"org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\r\n <s" +
"tring>false</string>\r\n <string>any</string>\r\n <string>true</string>\r\n</ArrayOf" +
"String>")]
public global::System.Collections.Specialized.StringCollection SteamGridDB_Humor {
get {
return ((string)(this["Tags"]));
return ((global::System.Collections.Specialized.StringCollection)(this["SteamGridDB_Humor"]));
}
set {
this["Tags"] = value;
this["SteamGridDB_Humor"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("<?xml version=\"1.0\" encoding=\"utf-16\"?>\r\n<ArrayOfString xmlns:xsd=\"http://www.w3." +
"org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\r\n <s" +
"tring>ERROR</string>\r\n <string>DEBUG</string>\r\n <string>TRACE</string>\r\n</Arra" +
"yOfString>")]
public global::System.Collections.Specialized.StringCollection LogLevel {
get {
return ((global::System.Collections.Specialized.StringCollection)(this["LogLevel"]));
}
set {
this["LogLevel"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("0")]
public int SelectedLogLevel {
get {
return ((int)(this["SelectedLogLevel"]));
}
set {
this["SelectedLogLevel"] = value;
}
}
}

@ -15,11 +15,29 @@
<Value Profile="(Default)">False</Value>
</Setting>
<Setting Name="SteamGridDbApiKey" Type="System.String" Scope="User">
<Value Profile="(Default)">617eb1e4ce186060a4b1e2ab0d468a44</Value>
<Value Profile="(Default)" />
</Setting>
<Setting Name="SelectedSteamGridDB_Style" Type="System.Int32" Scope="User">
<Value Profile="(Default)">0</Value>
</Setting>
<Setting Name="SelectedSteamGridDB_Type" Type="System.Int32" Scope="User">
<Value Profile="(Default)">0</Value>
</Setting>
<Setting Name="SelectedSteamGridDB_nfsw" Type="System.Int32" Scope="User">
<Value Profile="(Default)">0</Value>
</Setting>
<Setting Name="SelectedSteamGridDB_Humor" Type="System.Int32" Scope="User">
<Value Profile="(Default)">0</Value>
</Setting>
<Setting Name="OfferedSteamGridDB" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">False</Value>
</Setting>
<Setting Name="Tags" Type="System.String" Scope="User">
<Value Profile="(Default)">READY TO PLAY,XBOX</Value>
</Setting>
<Setting Name="SteamGridDB_Style" Type="System.Collections.Specialized.StringCollection" Scope="User">
<Value Profile="(Default)">&lt;?xml version="1.0" encoding="utf-16"?&gt;
&lt;ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"&gt;
&lt;ArrayOfString xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&gt;
&lt;string&gt;any&lt;/string&gt;
&lt;string&gt;alternate&lt;/string&gt;
&lt;string&gt;blurred&lt;/string&gt;
@ -30,7 +48,7 @@
</Setting>
<Setting Name="SteamGridDB_Type" Type="System.Collections.Specialized.StringCollection" Scope="User">
<Value Profile="(Default)">&lt;?xml version="1.0" encoding="utf-16"?&gt;
&lt;ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"&gt;
&lt;ArrayOfString xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&gt;
&lt;string&gt;any&lt;/string&gt;
&lt;string&gt;static&lt;/string&gt;
&lt;string&gt;animated&lt;/string&gt;
@ -38,7 +56,7 @@
</Setting>
<Setting Name="SteamGridDB_nfsw" Type="System.Collections.Specialized.StringCollection" Scope="User">
<Value Profile="(Default)">&lt;?xml version="1.0" encoding="utf-16"?&gt;
&lt;ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"&gt;
&lt;ArrayOfString xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&gt;
&lt;string&gt;false&lt;/string&gt;
&lt;string&gt;any&lt;/string&gt;
&lt;string&gt;true&lt;/string&gt;
@ -46,29 +64,22 @@
</Setting>
<Setting Name="SteamGridDB_Humor" Type="System.Collections.Specialized.StringCollection" Scope="User">
<Value Profile="(Default)">&lt;?xml version="1.0" encoding="utf-16"?&gt;
&lt;ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"&gt;
&lt;ArrayOfString xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&gt;
&lt;string&gt;false&lt;/string&gt;
&lt;string&gt;any&lt;/string&gt;
&lt;string&gt;true&lt;/string&gt;
&lt;/ArrayOfString&gt;</Value>
</Setting>
<Setting Name="SelectedSteamGridDB_Style" Type="System.Int32" Scope="User">
<Value Profile="(Default)">0</Value>
</Setting>
<Setting Name="SelectedSteamGridDB_Type" Type="System.Int32" Scope="User">
<Value Profile="(Default)">0</Value>
</Setting>
<Setting Name="SelectedSteamGridDB_nfsw" Type="System.Int32" Scope="User">
<Value Profile="(Default)">0</Value>
<Setting Name="LogLevel" Type="System.Collections.Specialized.StringCollection" Scope="User">
<Value Profile="(Default)">&lt;?xml version="1.0" encoding="utf-16"?&gt;
&lt;ArrayOfString xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&gt;
&lt;string&gt;ERROR&lt;/string&gt;
&lt;string&gt;DEBUG&lt;/string&gt;
&lt;string&gt;TRACE&lt;/string&gt;
&lt;/ArrayOfString&gt;</Value>
</Setting>
<Setting Name="SelectedSteamGridDB_Humor" Type="System.Int32" Scope="User">
<Setting Name="SelectedLogLevel" Type="System.String" Scope="User">
<Value Profile="(Default)">0</Value>
</Setting>
<Setting Name="OfferedSteamGridDB" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">False</Value>
</Setting>
<Setting Name="Tags" Type="System.String" Scope="User">
<Value Profile="(Default)">READY TO PLAY,XBOX</Value>
</Setting>
</Settings>
</SettingsFile>

@ -10,20 +10,46 @@ foreach ($app in $installedapps)
{
$appx = Get-AppxPackageManifest $app;
$name = $appx.Package.Properties.DisplayName;
$executable = $appx.Package.Applications.Application.Executable;
if($name -like '*DisplayName*' -or $name -like '*ms-resource*')
{
$name = $appx.Package.Applications.Application.VisualElements.DisplayName;
# Handle app running with microsoft launcher or which doesn't have an executable in the manifest
if([string]::IsNullOrWhitespace($executable) -or $executable -eq "GameLaunchHelper.exe") {
if(Test-Path -Path ($app.InstallLocation + "\MicrosoftGame.Config")) {
[xml]$msconfig = Get-Content ($app.InstallLocation + "\MicrosoftGame.Config");
$executable = $msconfig.Game.ExecutableList.Executable.Name;
}
else {
# Cannot handle app which doesn't have any configuration to read
continue;
}
}
# Convert object to ensure is the String of execuble (cf Halo Master Chief Collection example below)
# mcclauncher.exe
# MCC\Binaries\Win64\MCCWinStore-Win64-Shipping.exe
if($executable -is [Object[]]) { $executable = $executable[1].ToString() }
# Exclude apps without a name acceptable
if($name -like '*DisplayName*' -or $name -like '*ms-resource*')
{
$name = "App name not found, double click here to edit it";
continue;
}
$logo = $app.InstallLocation + "\" + $appx.Package.Applications.Application.VisualElements.Square150x150Logo;
# Check for possible duplicate game like Halo MCC which have two version (one with AC and one witohut AC)
$duplicate = $false;
foreach($item in $aumidList) {
#Write-host $item - $name
if($item.StartsWith($name)) {
$duplicate = $true;
break;
}
}
$aumidList += $name + "|" + $logo + "|" +
$app.packagefamilyname + "!" + $id+ ";"
# Insert if not duplicated
if(!$duplicate) {
$aumidList += $name + "|" + $logo + "|" + $app.packagefamilyname + "!" + $id + "|" + $executable + ";"
}
}
}
}

@ -0,0 +1,7 @@
{
"Microsoft.SeaofThieves": "Sea of Thieves",
"Microsoft.DeltaPC": "Gears of War: Ultimate Edition",
"MotionTwin.DeadCellsWin10": "Dead Cells",
"SystemEraSoftworks.29415440E1269": "ASTRONEER",
"NAMCOBANDAIGamesInc.TTablet": "Taiko no Tatsujin: The Drum Master!"
}

@ -11,27 +11,36 @@
TextElement.FontWeight="Medium"
TextElement.FontSize="14"
FontFamily="Segoe UI Light"
Title="Settings" Height="638" Width="800" Icon="Resources/hook2.ico">
Title="Settings" Height="750" Width="800" Icon="Resources/hook2.ico">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="27*"/>
<ColumnDefinition Width="17*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="41*"/>
<RowDefinition Height="80"/>
<RowDefinition Height="179*"/>
</Grid.RowDefinitions>
<materialDesign:ColorZone Padding="16" materialDesign:ShadowAssist.ShadowDepth="Depth2" Mode="PrimaryMid" VerticalAlignment="Top" Height="80" Grid.ColumnSpan="2" Margin="0,0,-0.4,0"/>
<materialDesign:ColorZone Padding="16" Mode="PrimaryMid" VerticalAlignment="Top" Height="80" Grid.ColumnSpan="2" Margin="0,0,-0.4,0"/>
<Image x:Name="image" HorizontalAlignment="Left" Width="178" Height="80" VerticalAlignment="Top" Source="Resources/WhiteTransparent.png" Stretch="UniformToFill" ToolTip="Welcome to UWPHook, add your UWP apps and games to Steam!"/>
<Grid Margin="10,9.4,10.2,10.2" Grid.Row="1">
<Grid Margin="10,10,10,10" Grid.RowSpan="1" Grid.Row="1">
<Grid.RowDefinitions>
<RowDefinition Height="62"/>
<RowDefinition Height="40"/>
<RowDefinition Height="68*"/>
<RowDefinition Height="213*"/>
<RowDefinition Height="43*"/>
<RowDefinition Height="48*"/>
<RowDefinition Height="30"/>
<RowDefinition Height="44*"/>
<RowDefinition Height="44*"/>
<RowDefinition Height="44*"/>
<RowDefinition Height="44*"/>
<RowDefinition Height="44*"/>
<RowDefinition Height="44*"/>
<RowDefinition Height="30"/>
<RowDefinition Height="40*"/>
<RowDefinition Height="40*"/>
<RowDefinition Height="40*"/>
<RowDefinition Height="40*"/>
<RowDefinition Height="40*"/>
<RowDefinition Height="80"/>
<RowDefinition Height="50*"/>
<RowDefinition Height="50*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="62*"/>
@ -39,27 +48,37 @@
<ColumnDefinition Width="124*"/>
<ColumnDefinition Width="113*"/>
</Grid.ColumnDefinitions>
<materialDesign:ColorZone Padding="16" materialDesign:ShadowAssist.ShadowDepth="Depth2" Mode="PrimaryMid" VerticalAlignment="Top" Height="27" Grid.ColumnSpan="4">
<!-- Settings Section -->
<materialDesign:ColorZone Padding="16" Mode="PrimaryMid" VerticalAlignment="Top" Height="30" Grid.ColumnSpan="4" Grid.Row="0">
<Label Content="Settings" HorizontalAlignment="Left" Margin="-10,-15,0,-17" VerticalAlignment="Top" FontFamily="Segoe UI Semibold" FontSize="14" Height="32" Foreground="#DDFFFFFF"/>
</materialDesign:ColorZone>
<ToggleButton x:Name="language_toggle" Style="{StaticResource MaterialDesignSwitchToggleButton}" VerticalAlignment="Top" Margin="6,34,0,0" ToolTip="MaterialDesignSwitchToggleButton" IsChecked="False" Height="18" HorizontalAlignment="Left" Width="46" RenderTransformOrigin="0.304,0.444" />
<Label ToolTip="Some apps use the system language to choose what language to display, this setting will store your current language, change it so you can play in another language and then revert your system back to your default display language." x:Name="label1" Content="Set system language when launching an app*" Margin="5,31,0,0" VerticalAlignment="Top" Height="29" Grid.Column="1" Grid.ColumnSpan="2"/>
<ComboBox ToolTip="Some apps use the system language to choose what language to display, this setting will store your current language, change it so you can play in another language and then revert your system back to your default display language." x:Name="cultures_comboBox" Margin="0,29,10,0" VerticalAlignment="Top" Height="31" Grid.Column="3" HorizontalAlignment="Right" Width="93"/>
<Button x:Name="save_button" Content="Save" HorizontalAlignment="Right" VerticalAlignment="Top" Width="93" Click="saveButton_Click" Grid.Column="3" Grid.Row="4" Margin="0,2,0,0"/>
<Label x:Name="label3" Content="Check if the launched app is running every" Margin="5,7,0,0" VerticalAlignment="Top" Height="29" Grid.Column="1" Grid.Row="1" Grid.ColumnSpan="2"/>
<ComboBox x:Name="seconds_comboBox" Margin="0,7,10,0" VerticalAlignment="Top" Height="31" Grid.Column="3" HorizontalAlignment="Right" Width="93" Grid.Row="1"/>
<Button x:Name="update_button" Click="update_button_Click" Content="Check for updates" Margin="0,0,8,9" Grid.Row="5" VerticalAlignment="Bottom" HorizontalAlignment="Right" Width="162" Grid.ColumnSpan="2"/>
<Button x:Name="help_button" Click="help_button_Click" Content="Get help at our Reddit" Grid.Column="2" Margin="0,0,0,9" Grid.Row="5" VerticalAlignment="Bottom" Grid.ColumnSpan="2" HorizontalAlignment="Left" Width="163"/>
<ToggleButton x:Name="streaming_toggle" Style="{StaticResource MaterialDesignSwitchToggleButton}" VerticalAlignment="Top" Margin="6,6,0,0" ToolTip="MaterialDesignSwitchToggleButton" IsChecked="False" Height="18" HorizontalAlignment="Left" Width="46" Grid.Row="2" />
<Label ToolTip="This fixes Steam in-home Streaming, set this in the host computer." x:Name="label1_Copy" Content="Enable streaming mode" Margin="5,1,0,0" VerticalAlignment="Top" Height="29" Grid.Column="1" Grid.ColumnSpan="2" Grid.Row="2"/>
<Label ToolTip="SteamGridDB API key used to download Steam's library artwork. Leave it blank if you don't want to download artwork." x:Name="label1_Copy1" Content="Api Key" Margin="5,39,0,0" VerticalAlignment="Top" Height="29" Grid.Row="3" Grid.Column="1"/>
<TextBox x:Name="steamgriddb_api_key" Grid.Column="2" Height="29" Margin="5,39,10,0" Grid.Row="3" TextWrapping="Wrap" VerticalAlignment="Top" Grid.ColumnSpan="2"/>
<materialDesign:ColorZone Padding="16" materialDesign:ShadowAssist.ShadowDepth="Depth2" Mode="PrimaryMid" VerticalAlignment="Top" Height="27" Grid.ColumnSpan="4" Margin="0,7,0,0" Grid.Row="3">
<ToggleButton x:Name="language_toggle" Style="{StaticResource MaterialDesignSwitchToggleButton}" ToolTip="MaterialDesignSwitchToggleButton" IsChecked="False" RenderTransformOrigin="0.304,0.444" Grid.Row="1" Margin="5,3,6,4" />
<Label ToolTip="Some apps use the system language to choose what language to display, this setting will store your current language, change it so you can play in another language and then revert your system back to your default display language." x:Name="label_cultures" Content="Set system language when launching an app*" VerticalAlignment="Center" Height="29" Grid.Column="1" Grid.ColumnSpan="2" Grid.Row="1"/>
<ComboBox ToolTip="Some apps use the system language to choose what language to display, this setting will store your current language, change it so you can play in another language and then revert your system back to your default display language." x:Name="cultures_comboBox" Margin="0,0,10,0" VerticalAlignment="Center" Height="32" Grid.Column="3" HorizontalAlignment="Right" Width="92" Grid.Row="1"/>
<Label x:Name="label_seconds" ToolTip="If 0, UWPHook will not run in the background and will not update the in-game status" Content="Check if the launched app is running every" VerticalAlignment="Center" Height="29" Grid.Column="1" Grid.Row="2" Grid.ColumnSpan="2"/>
<ComboBox x:Name="seconds_comboBox" Margin="0,0,10,0" VerticalAlignment="Center" Height="32" Grid.Column="3" HorizontalAlignment="Right" Width="92" Grid.Row="2"/>
<ToggleButton x:Name="streaming_toggle" Style="{DynamicResource MaterialDesignSwitchToggleButton}" ToolTip="MaterialDesignSwitchToggleButton" IsChecked="False" Grid.Row="3" Margin="6,3,5,4" />
<Label ToolTip="This fixes Steam in-home Streaming, set this in the host computer." x:Name="label_streaming" Content="Enable streaming mode" VerticalAlignment="Center" Height="29" Grid.Column="1" Grid.ColumnSpan="2" Grid.Row="3"/>
<ToggleButton x:Name="change_resolution_toggle" Style="{StaticResource MaterialDesignSwitchToggleButton}" ToolTip="Change host resolution on streaming mode" IsChecked="False" Grid.Row="4" Width="NaN" Margin="5,3,6,3" />
<Label ToolTip="Change the host computer resolution on launch, return to previous after." x:Name="label_resolution" Content="Change host resolution to:" VerticalAlignment="Center" Height="29" Grid.Column="1" Grid.Row="4"/>
<ComboBox x:Name="resolution_comboBox" Margin="0,0,10,0" VerticalAlignment="Center" Height="32" Grid.Column="2" Width="220" Grid.Row="4" Grid.ColumnSpan="2" HorizontalAlignment="Right"/>
<Label ToolTip="Add these tags to exported games, use comma separated values" x:Name="label_tags" Content="Export with these tags:" Margin="0,0,8,0" VerticalAlignment="Center" Height="29" Grid.Column="1" Grid.Row="5"/>
<TextBox x:Name="tags_textBox" Grid.Column="2" Height="32" Margin="0,0,10,0" Grid.Row="5" TextWrapping="Wrap" VerticalAlignment="Center" Grid.ColumnSpan="2" Width="220" HorizontalAlignment="Right"/>
<Label x:Name="label_logLevel" Content="Define log severity level" VerticalAlignment="Center" Height="29" Grid.Column="1" Grid.Row="6" Grid.ColumnSpan="2"/>
<ComboBox x:Name="logLevel_comboBox" Margin="0,0,10,0" VerticalAlignment="Center" Height="32" Grid.Column="3" Width="92" Grid.Row="6" SelectedIndex="0" HorizontalAlignment="Right" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Padding="10,0,0,0">
<ComboBoxItem Content="ERROR"/>
<ComboBoxItem Content="DEBUG"/>
<ComboBoxItem Content="TRACE"/>
</ComboBox>
<!-- SteamGrid Section -->
<materialDesign:ColorZone Padding="16" Mode="PrimaryMid" VerticalAlignment="Top" Height="30" Grid.ColumnSpan="4" Grid.Row="7">
<Label Content="SteamGrid" HorizontalAlignment="Left" Margin="-10,-15,0,-17" FontFamily="Segoe UI Semibold" FontSize="14" Foreground="#DDFFFFFF"/>
</materialDesign:ColorZone>
<Button x:Name="key_Button" Content="{materialDesign:PackIcon Key}" ToolTip="Get a new API Key" Margin="6,39,7,147" Grid.Row="3" Height="Auto" Click="key_Button_Click" />
<Label ToolTip="The main style of the artwork." x:Name="label1_Copy2" Content="Artwork Style" Margin="5,73,0,0" VerticalAlignment="Top" Height="29" Grid.Row="3" Grid.Column="1"/>
<ComboBox x:Name="style_comboBox" Margin="0,73,10,0" VerticalAlignment="Top" Height="31" Grid.Column="2" HorizontalAlignment="Right" Width="222" Grid.Row="3" Grid.ColumnSpan="2">
<Button x:Name="key_Button" Content="{materialDesign:PackIcon Key}" ToolTip="Go to SteamGridDB.com to generate a new key" Grid.Row="8" Height="Auto" Click="key_Button_Click" HorizontalAlignment="Center" VerticalAlignment="Center" />
<Label ToolTip="SteamGridDB API key used to download Steam's library artwork. Leave it blank if you don't want to download artwork." x:Name="label_apiKey" Content="Api Key" VerticalAlignment="Center" Height="29" Grid.Row="8" Grid.Column="1"/>
<TextBox x:Name="steamgriddb_api_key" Grid.Column="2" Height="32" Grid.Row="8" TextWrapping="Wrap" VerticalAlignment="Center" Grid.ColumnSpan="2" Margin="0,0,10,0" Width="220" HorizontalAlignment="Right"/>
<Label ToolTip="The main style of the artwork." x:Name="label_artworkStyle" Content="Artwork Style" VerticalAlignment="Center" Height="29" Grid.Row="9" Grid.Column="1"/>
<ComboBox x:Name="style_comboBox" Margin="0,0,10,0" VerticalAlignment="Center" Height="32" Grid.Column="2" Width="220" Grid.Row="9" Grid.ColumnSpan="2" HorizontalAlignment="Right">
<ComboBoxItem Content="Any"/>
<ComboBoxItem Content="Alternate"/>
<ComboBoxItem Content="Blurred"/>
@ -67,75 +86,79 @@
<ComboBoxItem Content="Material"/>
<ComboBoxItem Content="No Logo"/>
</ComboBox>
<Label ToolTip="Type of the artwork, animated, static or both." x:Name="label1_Copy3" Content="Artwork Type" Margin="5,109,0,0" VerticalAlignment="Top" Height="29" Grid.Row="3" Grid.Column="1"/>
<ComboBox x:Name="type_comboBox" Margin="0,109,10,0" VerticalAlignment="Top" Height="31" Grid.Column="2" HorizontalAlignment="Right" Width="222" Grid.Row="3" Grid.ColumnSpan="2">
<Label ToolTip="Type of the artwork, animated, static or both." x:Name="label_artworkType" Content="Artwork Type" VerticalAlignment="Center" Height="29" Grid.Row="10" Grid.Column="1"/>
<ComboBox x:Name="type_comboBox" Margin="0,0,10,0" VerticalAlignment="Center" Height="32" Grid.Column="2" Width="220" Grid.Row="10" Grid.ColumnSpan="2" HorizontalAlignment="Right">
<ComboBoxItem Content="Any"/>
<ComboBoxItem Content="Static"/>
<ComboBoxItem Content="Animated"/>
</ComboBox>
<Label ToolTip="Consider NSFW artwork?" x:Name="label1_Copy4" Content="Artwork nsfw" Margin="5,142,0,0" VerticalAlignment="Top" Height="29" Grid.Row="3" Grid.Column="1"/>
<ComboBox x:Name="nfsw_comboBox" Margin="0,145,10,0" VerticalAlignment="Top" Height="31" Grid.Column="2" HorizontalAlignment="Right" Width="222" Grid.Row="3" Grid.ColumnSpan="2">
<Label ToolTip="Consider NSFW artwork?" x:Name="label_artworkNSFW" Content="Artwork nsfw" VerticalAlignment="Center" Height="29" Grid.Row="11" Grid.Column="1"/>
<ComboBox x:Name="nfsw_comboBox" Margin="0,0,10,0" VerticalAlignment="Center" Height="32" Grid.Column="2" Width="220" Grid.Row="11" Grid.ColumnSpan="2" HorizontalAlignment="Right">
<ComboBoxItem Content="No"/>
<ComboBoxItem Content="Any"/>
<ComboBoxItem Content="Yes"/>
</ComboBox>
<Label ToolTip="Consider meme and humorous artwork?" x:Name="label1_Copy5" Content="Artwork humorous" Margin="5,176,0,0" VerticalAlignment="Top" Height="29" Grid.Row="3" Grid.Column="1"/>
<ComboBox x:Name="humor_comboBox" Margin="0,181,10,0" VerticalAlignment="Top" Height="31" Grid.Column="2" HorizontalAlignment="Right" Width="222" Grid.Row="3" Grid.ColumnSpan="2">
<Label ToolTip="Consider meme and humorous artwork?" x:Name="label_artworkHumor" Content="Artwork humorous" VerticalAlignment="Center" Height="29" Grid.Row="12" Grid.Column="1"/>
<ComboBox x:Name="humor_comboBox" Margin="0,0,10,0" VerticalAlignment="Center" Height="32" Grid.Column="2" Width="220" Grid.Row="12" Grid.ColumnSpan="2" HorizontalAlignment="Right">
<ComboBoxItem Content="No"/>
<ComboBoxItem Content="Any"/>
<ComboBoxItem Content="Yes"/>
</ComboBox>
<Label ToolTip="Add these tags to exported games, use comma separated values" x:Name="label1_Copy6" Content="Export with these tags" Margin="5,35,8,0" VerticalAlignment="Top" Height="29" Grid.Column="1" Grid.Row="2"/>
<TextBox x:Name="tags_textBox" Grid.Column="2" Height="29" Margin="5,35,10,0" Grid.Row="2" TextWrapping="Wrap" VerticalAlignment="Top" Grid.ColumnSpan="2"/>
<!-- Bottom Section -->
<Button x:Name="save_button" Content="Save" HorizontalAlignment="Right" VerticalAlignment="Top" Width="93" Click="saveButton_Click" Grid.Column="3" Grid.Row="13" Grid.ColumnSpan="1" Height="32" Margin="0,5,10,0"/>
<Button x:Name="update_button" Click="update_button_Click" Content="Check for updates" Margin="0,0,10,0" Grid.Row="14" VerticalAlignment="Center" HorizontalAlignment="Right" Width="165" Grid.ColumnSpan="2" Grid.Column="0" Height="32"/>
<Button x:Name="help_button" Click="help_button_Click" Content="Get help at our Reddit" Grid.Column="2" Grid.Row="14" VerticalAlignment="Center" Grid.ColumnSpan="2" HorizontalAlignment="Left" Width="165" Height="32" Margin="10,0,0,0"/>
<Button x:Name="clearAll_button" Click="clearAll_button_Click" Content="Debug: Clear shortcuts.vdf" Grid.Row="18" VerticalAlignment="Center" HorizontalAlignment="Center" Width="200" Grid.Column="1" Grid.ColumnSpan="2" Height="32"/>
</Grid>
<Grid Margin="10,9,9,1" Grid.Column="1" Grid.Row="1">
<!-- Sidebar -->
<Grid Margin="10,10,10,10" Grid.Column="1" Grid.RowSpan="1" Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="63*"/>
<ColumnDefinition Width="164*"/>
<ColumnDefinition Width="59*"/>
<ColumnDefinition Width="290*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="266*"/>
<RowDefinition Height="48*"/>
<RowDefinition Height="48*"/>
<RowDefinition Height="48*"/>
<RowDefinition Height="58*"/>
<RowDefinition Height="30"/>
<RowDefinition Height="150"/>
<RowDefinition Height="80"/>
<RowDefinition Height="40"/>
<RowDefinition Height="40"/>
<RowDefinition Height="40"/>
<RowDefinition Height="60*"/>
</Grid.RowDefinitions>
<materialDesign:ColorZone Padding="16" Mode="PrimaryMid" VerticalAlignment="Top" Height="30" Grid.ColumnSpan="3">
<Label Content="About" HorizontalAlignment="Left" Margin="-10,-15,0,-17" VerticalAlignment="Top" FontFamily="Segoe UI Semibold" FontSize="14" Height="32" Foreground="#DDFFFFFF"/>
</materialDesign:ColorZone>
<Image x:Name="image2" Height="150" VerticalAlignment="Center" Source="Resources/briano.png" Stretch="UniformToFill" HorizontalAlignment="Center" Width="150" Grid.Column="0" Grid.Row="1"/>
<TextBlock TextWrapping="WrapWithOverflow" x:Name="textBlock" Text="Developed by Brian Lima, @brianostorm, if you like my work cheer me up at my Twitter or pay me a coffee via Paypal, this way i can keep building amazing open-source tools for you!" TextAlignment="Justify" VerticalAlignment="Center" Grid.ColumnSpan="1" Grid.RowSpan="1" Grid.Row="2" HorizontalAlignment="Center"/>
<materialDesign:Chip Content="Projects @ GitHub"
IconBackground="{DynamicResource PrimaryHueDarkBrush}"
IconForeground="{DynamicResource PrimaryHueDarkForegroundBrush}"
Margin="8,3,0,4" Click="Chip1_Click" HorizontalAlignment="Stretch" Height="Auto" Grid.Row="1" Grid.Column="1">
Margin="0,0,0,0" Click="Chip1_Click" HorizontalAlignment="Center" Height="32" Grid.Row="3" Grid.Column="0" VerticalAlignment="Center" Width="160">
<materialDesign:Chip.Icon>
<materialDesign:PackIcon Kind="MicrosoftGithub"></materialDesign:PackIcon>
<materialDesign:PackIcon Kind="Github" Foreground="{DynamicResource MaterialDesign.Brush.Primary.Dark}"/>
</materialDesign:Chip.Icon>
</materialDesign:Chip>
<materialDesign:Chip Content="Paypal donate"
IconBackground="{DynamicResource PrimaryHueDarkBrush}"
IconForeground="{DynamicResource PrimaryHueDarkForegroundBrush}"
Margin="8,4,0,5" Click="Chip2_Click" HorizontalAlignment="Stretch" Height="Auto" Grid.Row="2" Grid.Column="1">
Margin="0,0,0,0" Click="Chip2_Click" HorizontalAlignment="Center" Height="32" Grid.Row="4" Grid.Column="0" VerticalAlignment="Center" Width="160">
<materialDesign:Chip.Icon>
<materialDesign:PackIcon Kind="Coffee"></materialDesign:PackIcon>
<materialDesign:PackIcon Kind="Coffee" Foreground="{DynamicResource MaterialDesign.Brush.Primary.Dark}"></materialDesign:PackIcon>
</materialDesign:Chip.Icon>
</materialDesign:Chip>
<materialDesign:Chip Content="@brianostorm"
IconBackground="{DynamicResource PrimaryHueDarkBrush}"
IconForeground="{DynamicResource PrimaryHueDarkForegroundBrush}"
Margin="8,4,0,3" Click="Chip_Click" HorizontalAlignment="Stretch" Height="Auto" Grid.Row="3" Grid.Column="1">
Margin="0,0,0,0" Click="Chip_Click" HorizontalAlignment="Center" Height="32" Grid.Row="5" Grid.Column="0" VerticalAlignment="Center" Width="160">
<materialDesign:Chip.Icon>
<materialDesign:PackIcon Kind="Twitter" />
<materialDesign:PackIcon Kind="Twitter" Foreground="{DynamicResource MaterialDesign.Brush.Primary.Dark}" />
</materialDesign:Chip.Icon>
</materialDesign:Chip>
<TextBlock TextWrapping="WrapWithOverflow" x:Name="textBlock" Margin="0,185,0,0" Text="Developed by Brian Lima, @brianostorm, if you like my work cheer me up at my Twitter or pay me a coffee via Paypal, this way i can keep building amazing open-source tools for you!" TextAlignment="Justify" Height="91" VerticalAlignment="Top" Grid.ColumnSpan="3" Grid.RowSpan="2"/>
<materialDesign:ColorZone Padding="16" materialDesign:ShadowAssist.ShadowDepth="Depth2" Mode="PrimaryMid" VerticalAlignment="Top" Height="27" Grid.ColumnSpan="3">
<Label Content="About" HorizontalAlignment="Left" Margin="-10,-15,0,-17" VerticalAlignment="Top" FontFamily="Segoe UI Semibold" FontSize="14" Height="32" Foreground="#DDFFFFFF"/>
</materialDesign:ColorZone>
<Image x:Name="image2" Height="150" VerticalAlignment="Top" Source="Resources/briano.png" Stretch="UniformToFill" Margin="8,32,0,0" HorizontalAlignment="Left" Width="150" Grid.Column="1"/>
<TextBlock TextWrapping="WrapWithOverflow" x:Name="textBlock_Copy" VerticalAlignment="Top" Height="59" TextAlignment="Justify" Grid.Row="3" Grid.ColumnSpan="3" Margin="0,44,0,0" Grid.RowSpan="2"><Run Text="Special thanks to /r/Forza and /r/Steam communities at Reddit"/><Run Text=", and to all the "/><Hyperlink NavigateUri="https://github.com/BrianLima/UWPHook/graphs/contributors"> contributors </Hyperlink><Run Text=" who have dealt with my bad code"/><Run Text="."/><Run Text=" "/><Run Text=":)"/></TextBlock>
<TextBlock TextWrapping="WrapWithOverflow" x:Name="textBlock_Copy" Height="59" TextAlignment="Justify" Grid.Row="6" Grid.ColumnSpan="1" VerticalAlignment="Top" Margin="0,10,0,0"><Run Text="Special thanks to /r/Forza and /r/Steam communities at Reddit"/><Run Text=", and to all the "/><Hyperlink NavigateUri="https://github.com/BrianLima/UWPHook/graphs/contributors"> contributors </Hyperlink><Run Text=" who have dealt with my bad code"/><Run Text="."/><Run Text=" "/><Run Text=":)"/></TextBlock>
</Grid>
<Grid Margin="10,9.8,10.2,0.4" Grid.Row="2" Visibility="Hidden">
<Image HorizontalAlignment="Left" Height="111" VerticalAlignment="Top" Width="111" Source="Resources/square.png"/>
<TextBlock Margin="116,0,0,0" TextWrapping="Wrap" Text="Checkout OverFy, my new app, it add Spotify's now playing status into Rivatuner/MSI Afterburner overlay, Free and Open Source!" VerticalAlignment="Top" Height="63" TextAlignment="Justify" HorizontalAlignment="Left" Width="341"/>
<Button x:Name="update_button_Copy" Click="update_button_Copy_Click" Content="Get OverFy!" Margin="206,0,0,10" VerticalAlignment="Bottom" HorizontalAlignment="Left" Width="162"/>
<Button x:Name="update_button_Copy" Click="update_button_Click" Content="Get OverFy!" Margin="206,0,0,10" VerticalAlignment="Bottom" HorizontalAlignment="Left" Width="162"/>
</Grid>
</Grid>
</Window>

@ -19,19 +19,20 @@ namespace UWPHook
{
cultures_comboBox.Items.Add(culture.TextInfo.CultureName);
}
for (int i = 1; i < 10; i++)
for (int i = 0; i < 10; i++)
{
seconds_comboBox.Items.Add(i + " seconds");
if (i == Properties.Settings.Default.Seconds)
{
seconds_comboBox.SelectedIndex = i - 1;
seconds_comboBox.SelectedIndex = i;
}
}
cultures_comboBox.SelectedItem = Properties.Settings.Default.TargetLanguage;
language_toggle.IsChecked = Properties.Settings.Default.ChangeLanguage;
streaming_toggle.IsChecked = Properties.Settings.Default.StreamMode;
logLevel_comboBox.SelectedIndex = Properties.Settings.Default.SelectedLogLevel;
steamgriddb_api_key.Text = Properties.Settings.Default.SteamGridDbApiKey;
style_comboBox.SelectedIndex = Properties.Settings.Default.SelectedSteamGridDB_Style;
type_comboBox.SelectedIndex = Properties.Settings.Default.SelectedSteamGridDB_Type;
@ -46,13 +47,15 @@ namespace UWPHook
Properties.Settings.Default.TargetLanguage = cultures_comboBox.SelectedItem.ToString();
Properties.Settings.Default.Seconds = Int32.Parse(seconds_comboBox.SelectedItem.ToString().Substring(0, 1));
Properties.Settings.Default.StreamMode = (bool)streaming_toggle.IsChecked;
Properties.Settings.Default.SteamGridDbApiKey = steamgriddb_api_key.Text;
Properties.Settings.Default.SelectedLogLevel = logLevel_comboBox.SelectedIndex;
Properties.Settings.Default.SteamGridDbApiKey = steamgriddb_api_key.Text.Trim('\r', '\n');
Properties.Settings.Default.SelectedSteamGridDB_Style = style_comboBox.SelectedIndex;
Properties.Settings.Default.SelectedSteamGridDB_Type = type_comboBox.SelectedIndex;
Properties.Settings.Default.SelectedSteamGridDB_nfsw = nfsw_comboBox.SelectedIndex;
Properties.Settings.Default.SelectedSteamGridDB_Humor = humor_comboBox.SelectedIndex;
Properties.Settings.Default.Tags = tags_textBox.Text;
Properties.Settings.Default.Save();
GamesWindow.SetLogLevel();
this.Close();
}
@ -81,16 +84,20 @@ namespace UWPHook
System.Diagnostics.Process.Start("https://reddit.com/r/UWPHook/");
}
private void update_button_Copy_Click(object sender, RoutedEventArgs e)
private void clearAll_button_Click(object sender, RoutedEventArgs e)
{
System.Diagnostics.Process.Start("https://github.com/BrianLima/OverFy/releases");
MessageBoxResult result = MessageBox.Show("This action will remove ALL shortcuts from non-Steam games." + Environment.NewLine + " Are you sure you want to continue?", "Warning", MessageBoxButton.YesNo, MessageBoxImage.Warning);
if (result == MessageBoxResult.Yes)
{
GamesWindow.ClearAllShortcuts();
}
}
private void key_Button_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show(messageBoxText: "You are being redirected to SteamGridDB website!\r\n" +
"Log-in, or create your account, go to your profile preferences and click 'Generate API Key', then paste the key back on UWPHook.", "Attention!", MessageBoxButton.OK, MessageBoxImage.Information );
System.Diagnostics.Process.Start("https://www.steamgriddb.com/profile/preferences");
System.Diagnostics.Process.Start("https://www.steamgriddb.com/profile/preferences/api");
}
}
}

@ -3,6 +3,8 @@ using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using UWPHook.Properties;
using System.Diagnostics;
using Serilog;
namespace UWPHook.SteamGridDb
{
@ -36,12 +38,22 @@ namespace UWPHook.SteamGridDb
GameResponse[] games = null;
HttpResponseMessage response = await httpClient.GetAsync(path);
if (response.IsSuccessStatusCode)
{
var parsedResponse = await response.Content.ReadAsAsync<ResponseWrapper<GameResponse>>();
games = parsedResponse.Data;
}
else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized)
{
Log.Verbose("ERROR RESPONSE: " + response.ToString());
settings.SteamGridDbApiKey = String.Empty;
settings.Save();
Log.Error("Warning: SteamGrid API Key Invalid. Please generate a new key and add it to settings.");
throw new TaskCanceledException("Warning: SteamGrid API Key Invalid. Please generate a new key and add it to settings.");
}
return games;
}
@ -91,7 +103,13 @@ namespace UWPHook.SteamGridDb
if (response.IsSuccessStatusCode)
{
var parsedResponse = await response.Content.ReadAsAsync<ResponseWrapper<ImageResponse>>();
images = parsedResponse.Data;
if (parsedResponse != null)
{
if (parsedResponse.Success)
{
images = parsedResponse.Data;
}
}
}
return images;

@ -9,7 +9,7 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>UWPHook</RootNamespace>
<AssemblyName>UWPHook</AssemblyName>
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WarningLevel>4</WarningLevel>
@ -59,29 +59,18 @@
<StartupObject>UWPHook.App</StartupObject>
</PropertyGroup>
<ItemGroup>
<Reference Include="Crc32.NET, Version=1.0.0.0, Culture=neutral, PublicKeyToken=dc0b95cf99bf4e99, processorArchitecture=MSIL">
<HintPath>..\packages\Crc32.NET.1.2.0\lib\net20\Crc32.NET.dll</HintPath>
</Reference>
<Reference Include="MaterialDesignColors, Version=1.2.7.1979, Culture=neutral, PublicKeyToken=df2a72020bd7962a, processorArchitecture=MSIL">
<HintPath>..\packages\MaterialDesignColors.1.2.7\lib\net45\MaterialDesignColors.dll</HintPath>
</Reference>
<Reference Include="MaterialDesignThemes.Wpf, Version=3.2.0.1979, Culture=neutral, PublicKeyToken=df2a72020bd7962a, processorArchitecture=MSIL">
<HintPath>..\packages\MaterialDesignThemes.3.2.0\lib\net45\MaterialDesignThemes.Wpf.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="SharpSteam">
<HintPath>..\..\SharpSteam\SharpSteam\bin\Release\SharpSteam.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System">
<HintPath>..\..\..\..\..\..\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.2\System.dll</HintPath>
</Reference>
<Reference Include="System.Data" />
<Reference Include="System.Drawing" />
<Reference Include="System.Management" />
<Reference Include="System.Management.Automation, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.PowerShell.5.ReferenceAssemblies.1.1.0\lib\net4\System.Management.Automation.dll</HintPath>
</Reference>
<Reference Include="System.Net.Http.Formatting, Version=5.2.7.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNet.WebApi.Client.5.2.7\lib\net45\System.Net.Http.Formatting.dll</HintPath>
<HintPath>..\..\..\..\..\..\Windows\assembly\GAC_MSIL\System.Management.Automation\1.0.0.0__31bf3856ad364e35\System.Management.Automation.dll</HintPath>
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="System.Xml" />
<Reference Include="Microsoft.CSharp" />
@ -156,12 +145,15 @@
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<None Include="packages.config" />
<None Include="bin\Release\_Resources\KnownApps.json" />
<None Include="Properties\Settings.settings">
<Generator>PublicSettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<AppDesigner Include="Properties\" />
<EmbeddedResource Include="Resources\KnownApps.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
@ -205,14 +197,33 @@
<ItemGroup>
<Resource Include="Resources\square.png" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Crc32.NET">
<Version>1.2.0</Version>
</PackageReference>
<PackageReference Include="MaterialDesignColors">
<Version>3.0.0</Version>
</PackageReference>
<PackageReference Include="MaterialDesignThemes">
<Version>5.0.0</Version>
</PackageReference>
<PackageReference Include="Microsoft.AspNet.WebApi.Client">
<Version>6.0.0</Version>
</PackageReference>
<PackageReference Include="Newtonsoft.Json">
<Version>13.0.3</Version>
</PackageReference>
<PackageReference Include="Serilog">
<Version>3.1.1</Version>
</PackageReference>
<PackageReference Include="Serilog.Sinks.Console">
<Version>5.0.1</Version>
</PackageReference>
<PackageReference Include="Serilog.Sinks.File">
<Version>5.0.0</Version>
</PackageReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\packages\MaterialDesignThemes.3.2.0\build\MaterialDesignThemes.targets" Condition="Exists('..\packages\MaterialDesignThemes.3.2.0\build\MaterialDesignThemes.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\MaterialDesignThemes.3.2.0\build\MaterialDesignThemes.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\MaterialDesignThemes.3.2.0\build\MaterialDesignThemes.targets'))" />
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Crc32.NET" version="1.2.0" targetFramework="net461" />
<package id="MaterialDesignColors" version="1.2.7" targetFramework="net461" />
<package id="MaterialDesignThemes" version="3.2.0" targetFramework="net461" />
<package id="Microsoft.AspNet.WebApi.Client" version="5.2.7" targetFramework="net461" />
<package id="Microsoft.PowerShell.5.ReferenceAssemblies" version="1.1.0" targetFramework="net461" />
<package id="Newtonsoft.Json" version="12.0.3" targetFramework="net461" />
<package id="System.Management.Automation" version="7.1.0" targetFramework="net461" />
</packages>
Loading…
Cancel
Save