diff --git a/UWPHook/GamesWindow.xaml.cs b/UWPHook/GamesWindow.xaml.cs
index dd054a6..3eba4ba 100644
--- a/UWPHook/GamesWindow.xaml.cs
+++ b/UWPHook/GamesWindow.xaml.cs
@@ -40,7 +40,7 @@ public GamesWindow()
if (args?.Length > 1)
{
// When length is 1, the only argument is the path where the app is installed
- _ = LauncherAsync(args); // Launches the requested game
+ _ = LauncherAsync(args); // Launches the requested game
}
else
@@ -210,7 +210,7 @@ await Task.Run(() =>
stream.Close();
client.Dispose();
}
- });
+ });
}
///
@@ -218,16 +218,16 @@ await Task.Run(() =>
///
/// The user path to copy images to
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))
@@ -273,7 +273,7 @@ private async Task DownloadTempGridImages(string appName, string appTarget)
{
throw;
}
-
+
if (games != null)
{
var game = games[0];
@@ -348,7 +348,7 @@ private async Task ExportGames(bool restartSteam)
{
var users = SteamManager.GetUsers(steam_folder);
var selected_apps = Apps.Entries.Where(app => app.Selected);
- var exePath = @"""" + System.Reflection.Assembly.GetExecutingAssembly().Location + @"""";
+ var exePath = GenerateExePath();
var exeDir = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
List gridImagesDownloadTasks = new List();
@@ -370,89 +370,8 @@ private async Task ExportGames(bool restartSteam)
// 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
- {
- VDFEntry[] shortcuts = new VDFEntry[0];
- try
- {
- shortcuts = SteamManager.ReadShortcuts(user);
- }
- catch (Exception ex)
- {
- //If it's a short VDF, let's just overwrite it
- if (ex.GetType() != typeof(VDFTooShortException))
- {
- throw new Exception("Error: Program failed to load existing Steam shortcuts." + Environment.NewLine + ex.Message);
- }
- }
-
- if (shortcuts != null)
- {
- foreach (var app in selected_apps)
- {
- VDFEntry newApp = new VDFEntry()
- {
- AppName = app.Name,
- Exe = exePath,
- StartDir = exeDir,
- LaunchOptions = app.Aumid,
- AllowDesktopConfig = 1,
- AllowOverlay = 1,
- Icon = app.Icon,
- Index = shortcuts.Length,
- IsHidden = 0,
- OpenVR = 0,
- ShortcutPath = "",
- Tags = tags,
- Devkit = 0,
- DevkitGameID = "",
- LastPlayTime = (int)DateTimeOffset.UtcNow.ToUnixTimeSeconds(),
- };
- Boolean isFound = false;
- for (int i = 0; i < shortcuts.Length; i++)
- {
- Debug.WriteLine(shortcuts[i].ToString());
-
-
- if (shortcuts[i].AppName == app.Name)
- {
- isFound = true;
- Debug.WriteLine(app.Name + " already added to Steam. Updating existing shortcut.");
- shortcuts[i] = newApp;
- }
- }
-
- if (!isFound)
- {
- //Resize this array so it fits the new entries
- Array.Resize(ref shortcuts, shortcuts.Length + 1);
- shortcuts[shortcuts.Length - 1] = newApp;
- }
-
- }
-
- 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)
- {
- throw new Exception("Error: Program failed while trying to write your Steam shortcuts" + Environment.NewLine + ex.Message);
- }
- }
- }
- catch (Exception ex)
- {
- MessageBox.Show("Error: Program failed exporting your games:" + Environment.NewLine + ex.Message + ex.StackTrace);
- }
- }
+ ExportAppsToSteamShortcuts(tags, users, selected_apps, exePath, exeDir);
+ ExportAppsToShieldShortcuts(selected_apps, exePath, exeDir);
if (gridImagesDownloadTasks.Count > 0)
{
@@ -463,6 +382,7 @@ await Task.Run(() =>
foreach (var user in users)
{
CopyTempGridImagesToSteamUser(user);
+ CopyTempGridImagesToShieldStreamingAssets(selected_apps);
}
RemoveTempGridImages();
@@ -470,7 +390,7 @@ await Task.Run(() =>
}
}
- if(restartSteam)
+ if (restartSteam)
{
Func getSteam = () => Process.GetProcessesByName("steam").SingleOrDefault();
@@ -517,6 +437,103 @@ await Task.Run(() =>
return true;
}
+ ///
+ /// Extracted method to simplify the complexity of the ExportGames method.
+ ///
+ /// This method updates and existing steam vdf file to add or update shortcuts for the selected windows apps.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ private static void ExportAppsToSteamShortcuts(string[] tags, string[] users, IEnumerable selected_apps, string exePath, string exeDir)
+ {
+ foreach (var user in users)
+ {
+ try
+ {
+ VDFEntry[] shortcuts = new VDFEntry[0];
+ try
+ {
+ shortcuts = SteamManager.ReadShortcuts(user);
+ }
+ catch (Exception ex)
+ {
+ //If it's a short VDF, let's just overwrite it
+ if (ex.GetType() != typeof(VDFTooShortException))
+ {
+ throw new Exception("Error: Program failed to load existing Steam shortcuts." + Environment.NewLine + ex.Message);
+ }
+ }
+
+ if (shortcuts != null)
+ {
+ foreach (var app in selected_apps)
+ {
+ VDFEntry newApp = new VDFEntry()
+ {
+ AppName = app.Name,
+ Exe = exePath,
+ StartDir = exeDir,
+ LaunchOptions = app.Aumid,
+ AllowDesktopConfig = 1,
+ AllowOverlay = 1,
+ Icon = app.Icon,
+ Index = shortcuts.Length,
+ IsHidden = 0,
+ OpenVR = 0,
+ ShortcutPath = "",
+ Tags = tags,
+ Devkit = 0,
+ DevkitGameID = "",
+ LastPlayTime = (int)DateTimeOffset.UtcNow.ToUnixTimeSeconds(),
+ };
+ Boolean isFound = false;
+ for (int i = 0; i < shortcuts.Length; i++)
+ {
+ Debug.WriteLine(shortcuts[i].ToString());
+
+
+ if (shortcuts[i].AppName == app.Name)
+ {
+ isFound = true;
+ Debug.WriteLine(app.Name + " already added to Steam. Updating existing shortcut.");
+ shortcuts[i] = newApp;
+ }
+ }
+
+ if (!isFound)
+ {
+ //Resize this array so it fits the new entries
+ Array.Resize(ref shortcuts, shortcuts.Length + 1);
+ shortcuts[shortcuts.Length - 1] = newApp;
+ }
+
+ }
+
+ 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)
+ {
+ throw new Exception("Error: Program failed while trying to write your Steam shortcuts" + Environment.NewLine + ex.Message);
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show("Error: Program failed exporting your games:" + Environment.NewLine + ex.Message + ex.StackTrace);
+ }
+ }
+ }
+
public static void ClearAllShortcuts()
{
Debug.WriteLine("DBG: Clearing all elements in shortcuts.vdf");
@@ -695,5 +712,140 @@ private void Window_Loaded(object sender, RoutedEventArgs e)
}
}
}
+
+ ///
+ /// Generates the exe path used by Steam and NVIDIA Shield to call UWPHook
+ ///
+ ///
+ private static string GenerateExePath()
+ {
+ return @"""" + System.Reflection.Assembly.GetExecutingAssembly().Location + @"""";
+ }
+
+ ///
+ /// Iterates through the selected apps and creates windwos shortcut files for each inside the NVIDIA Shield Apps directory.
+ /// Will place an NVIDIA required placeholder box-art.png file inside the StreamingAssets/{app-name} dir.
+ ///
+ ///
+ ///
+ ///
+ private static void ExportAppsToShieldShortcuts(IEnumerable selected_apps, string exePath, string exeDir)
+ {
+ string shieldAppsDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "NVIDIA Corporation", "Shield Apps");
+ string streamingAssetsDir = Path.Combine(shieldAppsDir, "StreamingAssets");
+ if (!Directory.Exists(streamingAssetsDir))
+ {
+ DirectoryInfo di = Directory.CreateDirectory(streamingAssetsDir);
+ di.Attributes = FileAttributes.Directory | FileAttributes.Hidden;
+ }
+
+ foreach (AppEntry app in selected_apps)
+ {
+ string scrubbedAppName = app.Name;
+ foreach (char c in Path.GetInvalidFileNameChars())
+ {
+ scrubbedAppName = scrubbedAppName.Replace(c, '_');
+ }
+
+ string shortcutFile = Path.Combine(shieldAppsDir, scrubbedAppName + ".lnk");
+ Debug.WriteLine("Creating NVIDIA Shield shortcut: " + shortcutFile);
+
+ IWshRuntimeLibrary.IWshShell3 wsh = new IWshRuntimeLibrary.IWshShell_Class();
+ IWshRuntimeLibrary.IWshShortcut shortcut = wsh.CreateShortcut(shortcutFile);
+ shortcut.Arguments = app.Aumid;
+ shortcut.TargetPath = exePath;
+ // not sure about what this is for
+ shortcut.WindowStyle = 1;
+ shortcut.Description = "test link for " + app.Name;
+ shortcut.WorkingDirectory = exeDir;
+ //shortcut.IconLocation = "specify icon location";
+ shortcut.Save();
+
+ // Copy over placeholder box-art.png (required by NVIDIA)
+ string boxArtDir = Path.Combine(streamingAssetsDir, scrubbedAppName);
+ string boxArtFile = Path.Combine(streamingAssetsDir, scrubbedAppName, "box-art.png");
+ if (!Directory.Exists(boxArtDir))
+ {
+ Debug.WriteLine("creating directory for game streaming assets: " + boxArtDir);
+ try
+ {
+ Directory.CreateDirectory(boxArtDir);
+ }
+ catch (Exception e)
+ {
+ Console.Error.WriteLine("unable to create game streaming assets dir: {0}", e);
+ }
+
+ }
+ try
+ {
+ Debug.WriteLine("copying placeholder box-art to " + boxArtFile);
+ Properties.Resources.box_art.Save(boxArtFile);
+ }
+ catch (Exception e)
+ {
+ Console.Error.WriteLine("unable to copy placeholder box-art: {0}", e);
+ }
+
+ }
+
+ }
+
+ ///
+ /// Copies all temporary images to the {drive}:/Users/{user}/Appdata/Local/NVIDIA Corporation/Shield Apps/StreamingAssets/{scrubbed game name} dirs
+ ///
+ /// Selected app entrys to copy images for
+ private void CopyTempGridImagesToShieldStreamingAssets(IEnumerable selectedApps)
+ {
+ string tmpGridDirectory = Path.Combine(Path.GetTempPath(), "UWPHook", "tmp_grid");
+ string streamingAssetsDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "NVIDIA Corporation", "Shield Apps", "StreamingAssets");
+
+ // No images were downloaded, maybe the key is invalid or no app had an image
+ if (!Directory.Exists(tmpGridDirectory))
+ {
+ return;
+ }
+ if (!Directory.Exists(streamingAssetsDirectory))
+ {
+ DirectoryInfo di = Directory.CreateDirectory(streamingAssetsDirectory);
+ di.Attributes = FileAttributes.Directory | FileAttributes.Hidden;
+ }
+
+ foreach (AppEntry app in selectedApps)
+ {
+ string scrubbedAppName = app.Name;
+ foreach (char c in Path.GetInvalidFileNameChars())
+ {
+ scrubbedAppName = scrubbedAppName.Replace(c, '_');
+ }
+
+ ulong gameId = GenerateSteamGridAppId(app.Name, GenerateExePath());
+ string srcFile = Path.Combine(tmpGridDirectory, string.Format("{0}p.png", gameId));
+ string destDir = Path.Combine(streamingAssetsDirectory, scrubbedAppName);
+ string destFile = Path.Combine(destDir, "box-art.png");
+ if (!Directory.Exists(destDir))
+ {
+ try
+ {
+ Debug.WriteLine("Creating directory: ", destDir);
+ _ = Directory.CreateDirectory(destDir);
+ }
+ catch (Exception e)
+ {
+ Console.Error.WriteLine("unable to create directory: ", e);
+ }
+ }
+ try
+ {
+ Debug.WriteLine("Copying box-art image from {0} to {1}", new object[] { srcFile, destFile });
+ File.Copy(srcFile, destFile, true);
+ }
+ catch (Exception e)
+ {
+ Console.Error.WriteLine("unable to copy box-art: ", e);
+ }
+
+ }
+ }
}
}
diff --git a/UWPHook/Properties/Resources.Designer.cs b/UWPHook/Properties/Resources.Designer.cs
index 236c6b6..aa2687d 100644
--- a/UWPHook/Properties/Resources.Designer.cs
+++ b/UWPHook/Properties/Resources.Designer.cs
@@ -60,6 +60,16 @@ internal Resources() {
}
}
+ ///
+ /// Looks up a localized resource of type System.Drawing.Bitmap.
+ ///
+ public static System.Drawing.Bitmap box_art {
+ get {
+ object obj = ResourceManager.GetObject("box_art", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
///
/// Looks up a localized resource of type System.Byte[].
///
diff --git a/UWPHook/Properties/Resources.resx b/UWPHook/Properties/Resources.resx
index 4285897..8898583 100644
--- a/UWPHook/Properties/Resources.resx
+++ b/UWPHook/Properties/Resources.resx
@@ -118,6 +118,9 @@
System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+ ..\Resources\box-art.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
..\Resources\GetAUMIDScript.ps1;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
diff --git a/UWPHook/Resources/box-art.png b/UWPHook/Resources/box-art.png
new file mode 100644
index 0000000..80b8fb7
Binary files /dev/null and b/UWPHook/Resources/box-art.png differ
diff --git a/UWPHook/SettingsWindow.xaml b/UWPHook/SettingsWindow.xaml
index d1fe0dc..b624cd0 100644
--- a/UWPHook/SettingsWindow.xaml
+++ b/UWPHook/SettingsWindow.xaml
@@ -92,7 +92,6 @@
-
diff --git a/UWPHook/SettingsWindow.xaml.cs b/UWPHook/SettingsWindow.xaml.cs
index df850fb..da39f6e 100644
--- a/UWPHook/SettingsWindow.xaml.cs
+++ b/UWPHook/SettingsWindow.xaml.cs
@@ -98,13 +98,5 @@ private void key_Button_Click(object sender, RoutedEventArgs e)
System.Diagnostics.Process.Start("https://www.steamgriddb.com/profile/preferences/api");
}
- private void test()
- {
- FixHeight = 1280;
-
- FixWidth = 1024;
-
- Resolution.CResolution ChangeRes1024 = new Resolution.CResolution(FixHeight, FixWidth);
- }
}
}
\ No newline at end of file
diff --git a/UWPHook/SteamGridDb/SteamGridDbApi.cs b/UWPHook/SteamGridDb/SteamGridDbApi.cs
index b340a9f..e57a3eb 100644
--- a/UWPHook/SteamGridDb/SteamGridDbApi.cs
+++ b/UWPHook/SteamGridDb/SteamGridDbApi.cs
@@ -33,7 +33,8 @@ public SteamGridDbApi(string apiKey)
/// Array of games corresponding to the provided name
public async Task SearchGame(string gameName)
{
- string path = $"search/autocomplete/{gameName}";
+ // remove any forward slashes in the gameName to allow Games like FINAL FANTASY X/X-2 HD Remaster to be found
+ string path = $"search/autocomplete/{gameName.Replace('/', ' ')}";
GameResponse[] games = null;
HttpResponseMessage response = await httpClient.GetAsync(path);
diff --git a/UWPHook/UWPHook.csproj b/UWPHook/UWPHook.csproj
index 0362c98..bdd1753 100644
--- a/UWPHook/UWPHook.csproj
+++ b/UWPHook/UWPHook.csproj
@@ -67,9 +67,8 @@
..\packages\MaterialDesignColors.2.0.4\lib\net452\MaterialDesignColors.dll
True
-
- ..\packages\MaterialDesignThemes.4.3.0\lib\net452\MaterialDesignThemes.Wpf.dll
- True
+
+ ..\packages\MaterialDesignThemes.4.1.0\lib\net452\MaterialDesignThemes.Wpf.dll
..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll
@@ -216,6 +215,9 @@
+
+
+
@@ -223,9 +225,7 @@
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}.
-
-