using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; namespace VRCX { /// /// The class responsible for launching user-defined applications when VRChat opens/closes. /// public class AutoAppLaunchManager { public static AutoAppLaunchManager Instance { get; private set; } public bool Enabled = true; public readonly string AppShortcutDirectory; private DateTime startTime = DateTime.Now; private List startedProcesses = new List(); private static readonly byte[] shortcutSignatureBytes = { 0x4C, 0x00, 0x00, 0x00 }; // signature for ShellLinkHeader\ static AutoAppLaunchManager() { Instance = new AutoAppLaunchManager(); } public AutoAppLaunchManager() { AppShortcutDirectory = Path.Combine(Program.AppDataDirectory, "startup"); if (!Directory.Exists(AppShortcutDirectory)) { Directory.CreateDirectory(AppShortcutDirectory); } ProcessMonitor.Instance.ProcessStarted += OnProcessStarted; ProcessMonitor.Instance.ProcessExited += OnProcessExited; } private void OnProcessExited(MonitoredProcess monitoredProcess) { if (startedProcesses.Count == 0 || !monitoredProcess.HasName("VRChat")) return; foreach (var process in startedProcesses) { if (!process.HasExited) process.Kill(); } startedProcesses.Clear(); } private void OnProcessStarted(MonitoredProcess monitoredProcess) { if (!monitoredProcess.HasName("VRChat") || monitoredProcess.Process.StartTime < startTime) return; if (startedProcesses.Count > 0) { foreach (var process in startedProcesses) { if (!process.HasExited) process.Kill(); } startedProcesses.Clear(); } var shortcutFiles = FindShortcutFiles(AppShortcutDirectory); if (shortcutFiles.Length > 0) { foreach (var file in shortcutFiles) { var process = Process.Start(file); startedProcesses.Add(process); } } } internal void Init() { // What are you lookin at? } internal void Exit() { Enabled = false; foreach (var process in startedProcesses) { if (!process.HasExited) process.Kill(); } } /// /// Finds windows shortcut files in a given folder. /// /// The folder path. /// An array of shortcut paths. If none, then empty. private static string[] FindShortcutFiles(string folderPath) { DirectoryInfo directoryInfo = new DirectoryInfo(folderPath); FileInfo[] files = directoryInfo.GetFiles(); List ret = new List(); foreach (FileInfo file in files) { if (IsShortcutFile(file.FullName)) { ret.Add(file.FullName); } } return ret.ToArray(); } /// /// Determines whether the specified file path is a shortcut by checking the file header. /// /// The file path. /// true if the given file path is a shortcut, otherwise false private static bool IsShortcutFile(string filePath) { byte[] headerBytes = new byte[4]; using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { if (fileStream.Length >= 4) { fileStream.Read(headerBytes, 0, 4); } } return headerBytes.SequenceEqual(shortcutSignatureBytes); } } }