|
|
|
@ -348,7 +348,7 @@ namespace UWPHook
|
|
|
|
|
{
|
|
|
|
|
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<Task> gridImagesDownloadTasks = new List<Task>();
|
|
|
|
@ -370,6 +370,85 @@ namespace UWPHook
|
|
|
|
|
|
|
|
|
|
// Export the selected apps and the downloaded images to each user
|
|
|
|
|
// in the steam folder by modifying it's VDF file
|
|
|
|
|
ExportAppsToSteamShortcuts(tags, users, selected_apps, exePath, exeDir);
|
|
|
|
|
ExportAppsToShieldShortcuts(selected_apps, exePath, exeDir);
|
|
|
|
|
|
|
|
|
|
if (gridImagesDownloadTasks.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
await Task.WhenAll(gridImagesDownloadTasks);
|
|
|
|
|
|
|
|
|
|
await Task.Run(() =>
|
|
|
|
|
{
|
|
|
|
|
foreach (var user in users)
|
|
|
|
|
{
|
|
|
|
|
CopyTempGridImagesToSteamUser(user);
|
|
|
|
|
CopyTempGridImagesToShieldStreamingAssets(selected_apps);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RemoveTempGridImages();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (restartSteam)
|
|
|
|
|
{
|
|
|
|
|
Func<Process> getSteam = () => Process.GetProcessesByName("steam").SingleOrDefault();
|
|
|
|
|
|
|
|
|
|
Process steam = getSteam();
|
|
|
|
|
if (steam != null)
|
|
|
|
|
{
|
|
|
|
|
string steamExe = steam.MainModule.FileName;
|
|
|
|
|
|
|
|
|
|
//we always ask politely
|
|
|
|
|
Debug.WriteLine("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 (watch.Elapsed.TotalSeconds < waitSeconds)
|
|
|
|
|
{
|
|
|
|
|
Thread.Sleep(TimeSpan.FromSeconds(0.5f));
|
|
|
|
|
if (getSteam() == null)
|
|
|
|
|
{
|
|
|
|
|
Debug.WriteLine("Restarting Steam");
|
|
|
|
|
Process.Start(steamExe);
|
|
|
|
|
restarted = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!restarted)
|
|
|
|
|
{
|
|
|
|
|
Debug.WriteLine("Steam instance not restarted");
|
|
|
|
|
MessageBox.Show("Failed to restart Steam, please launch it manually", "Error", MessageBoxButton.OK, MessageBoxImage.Warning);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Debug.WriteLine("Steam instance not found to be restarted");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 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.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="tags"></param>
|
|
|
|
|
/// <param name="users"></param>
|
|
|
|
|
/// <param name="selected_apps"></param>
|
|
|
|
|
/// <param name="exePath"></param>
|
|
|
|
|
/// <param name="exeDir"></param>
|
|
|
|
|
private static void ExportAppsToSteamShortcuts(string[] tags, string[] users, IEnumerable<AppEntry> selected_apps, string exePath, string exeDir)
|
|
|
|
|
{
|
|
|
|
|
foreach (var user in users)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
@ -453,68 +532,6 @@ namespace UWPHook
|
|
|
|
|
MessageBox.Show("Error: Program failed exporting your games:" + Environment.NewLine + ex.Message + ex.StackTrace);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (gridImagesDownloadTasks.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
await Task.WhenAll(gridImagesDownloadTasks);
|
|
|
|
|
|
|
|
|
|
await Task.Run(() =>
|
|
|
|
|
{
|
|
|
|
|
foreach (var user in users)
|
|
|
|
|
{
|
|
|
|
|
CopyTempGridImagesToSteamUser(user);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RemoveTempGridImages();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(restartSteam)
|
|
|
|
|
{
|
|
|
|
|
Func<Process> getSteam = () => Process.GetProcessesByName("steam").SingleOrDefault();
|
|
|
|
|
|
|
|
|
|
Process steam = getSteam();
|
|
|
|
|
if (steam != null)
|
|
|
|
|
{
|
|
|
|
|
string steamExe = steam.MainModule.FileName;
|
|
|
|
|
|
|
|
|
|
//we always ask politely
|
|
|
|
|
Debug.WriteLine("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 (watch.Elapsed.TotalSeconds < waitSeconds)
|
|
|
|
|
{
|
|
|
|
|
Thread.Sleep(TimeSpan.FromSeconds(0.5f));
|
|
|
|
|
if (getSteam() == null)
|
|
|
|
|
{
|
|
|
|
|
Debug.WriteLine("Restarting Steam");
|
|
|
|
|
Process.Start(steamExe);
|
|
|
|
|
restarted = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!restarted)
|
|
|
|
|
{
|
|
|
|
|
Debug.WriteLine("Steam instance not restarted");
|
|
|
|
|
MessageBox.Show("Failed to restart Steam, please launch it manually", "Error", MessageBoxButton.OK, MessageBoxImage.Warning);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Debug.WriteLine("Steam instance not found to be restarted");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void ClearAllShortcuts()
|
|
|
|
@ -695,5 +712,140 @@ namespace UWPHook
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Generates the exe path used by Steam and NVIDIA Shield to call UWPHook
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
private static string GenerateExePath()
|
|
|
|
|
{
|
|
|
|
|
return @"""" + System.Reflection.Assembly.GetExecutingAssembly().Location + @"""";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 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.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="selected_apps"></param>
|
|
|
|
|
/// <param name="exePath"></param>
|
|
|
|
|
/// <param name="exeDir"></param>
|
|
|
|
|
private static void ExportAppsToShieldShortcuts(IEnumerable<AppEntry> 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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Copies all temporary images to the {drive}:/Users/{user}/Appdata/Local/NVIDIA Corporation/Shield Apps/StreamingAssets/{scrubbed game name} dirs
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="selectedApps">Selected app entrys to copy images for</param>
|
|
|
|
|
private void CopyTempGridImagesToShieldStreamingAssets(IEnumerable<AppEntry> 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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|