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);
}
}
}