Add startup application support and dialog for user prompts
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net8.0-windows</TargetFramework>
|
||||
<UseWindowsForms>true</UseWindowsForms>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
|
||||
@@ -36,6 +36,12 @@ public class DevDriveConfig
|
||||
/// </summary>
|
||||
[JsonPropertyName("paths")]
|
||||
public List<SymlinkEntry> Paths { get; set; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// List of applications to prompt for launch after mounting.
|
||||
/// </summary>
|
||||
[JsonPropertyName("startupApps")]
|
||||
public List<StartupApp> StartupApps { get; set; } = [];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -55,3 +61,39 @@ public class SymlinkEntry
|
||||
[JsonPropertyName("path")]
|
||||
public string Path { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents an application to launch after mounting.
|
||||
/// </summary>
|
||||
public class StartupApp
|
||||
{
|
||||
/// <summary>
|
||||
/// Display name shown in the dialog.
|
||||
/// </summary>
|
||||
[JsonPropertyName("name")]
|
||||
public string Name { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Path to the executable.
|
||||
/// </summary>
|
||||
[JsonPropertyName("path")]
|
||||
public string Path { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Command line arguments (optional).
|
||||
/// </summary>
|
||||
[JsonPropertyName("arguments")]
|
||||
public string Arguments { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Working directory (optional, defaults to executable's directory).
|
||||
/// </summary>
|
||||
[JsonPropertyName("workingDirectory")]
|
||||
public string WorkingDirectory { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Whether this app is checked by default in the dialog.
|
||||
/// </summary>
|
||||
[JsonPropertyName("checkedByDefault")]
|
||||
public bool CheckedByDefault { get; set; } = true;
|
||||
}
|
||||
|
||||
@@ -301,6 +301,12 @@ public static class Program
|
||||
MountDrive();
|
||||
SyncSymlinksFromConfig(config);
|
||||
_lastConfig = config;
|
||||
|
||||
if (config.StartupApps.Count > 0)
|
||||
{
|
||||
var driveName = config.DriveName ?? "Dev Drive";
|
||||
Task.Run(() => StartupDialog.ShowIfNeeded(config.StartupApps, driveName));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
201
StartupDialog.cs
Normal file
201
StartupDialog.cs
Normal file
@@ -0,0 +1,201 @@
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.Versioning;
|
||||
|
||||
namespace DevDrive;
|
||||
|
||||
/// <summary>
|
||||
/// Dialog that prompts the user to select which startup apps to launch.
|
||||
/// </summary>
|
||||
[SupportedOSPlatform("windows")]
|
||||
public class StartupDialog : Form
|
||||
{
|
||||
private readonly List<StartupApp> _apps;
|
||||
private readonly List<CheckBox> _checkboxes = [];
|
||||
private readonly Button _launchButton;
|
||||
private readonly Button _cancelButton;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new startup dialog for the given apps.
|
||||
/// </summary>
|
||||
/// <param name="apps">List of startup apps to display.</param>
|
||||
/// <param name="driveName">Name of the drive for the title.</param>
|
||||
public StartupDialog(List<StartupApp> apps, string driveName)
|
||||
{
|
||||
_apps = apps;
|
||||
|
||||
Text = $"{driveName} - Startup Apps";
|
||||
FormBorderStyle = FormBorderStyle.FixedDialog;
|
||||
StartPosition = FormStartPosition.CenterScreen;
|
||||
MaximizeBox = false;
|
||||
MinimizeBox = false;
|
||||
AutoScaleMode = AutoScaleMode.Dpi;
|
||||
|
||||
var padding = 16;
|
||||
var checkboxHeight = 28;
|
||||
var buttonHeight = 32;
|
||||
var buttonWidth = 100;
|
||||
|
||||
var contentHeight = padding + (_apps.Count * checkboxHeight) + padding + buttonHeight + padding;
|
||||
var contentWidth = 350;
|
||||
|
||||
ClientSize = new Size(contentWidth, contentHeight);
|
||||
|
||||
var yPos = padding;
|
||||
|
||||
foreach (var app in _apps)
|
||||
{
|
||||
var checkbox = new CheckBox
|
||||
{
|
||||
Text = app.Name,
|
||||
Tag = app,
|
||||
Checked = app.CheckedByDefault,
|
||||
Location = new Point(padding, yPos),
|
||||
Size = new Size(contentWidth - (padding * 2), checkboxHeight),
|
||||
Font = new Font("Segoe UI", 10)
|
||||
};
|
||||
|
||||
_checkboxes.Add(checkbox);
|
||||
Controls.Add(checkbox);
|
||||
yPos += checkboxHeight;
|
||||
}
|
||||
|
||||
yPos += padding;
|
||||
|
||||
_launchButton = new Button
|
||||
{
|
||||
Text = "Launch",
|
||||
DialogResult = DialogResult.OK,
|
||||
Location = new Point(contentWidth - padding - buttonWidth - 8 - buttonWidth, yPos),
|
||||
Size = new Size(buttonWidth, buttonHeight),
|
||||
Font = new Font("Segoe UI", 9)
|
||||
};
|
||||
_launchButton.Click += OnLaunchClick;
|
||||
Controls.Add(_launchButton);
|
||||
|
||||
_cancelButton = new Button
|
||||
{
|
||||
Text = "Skip",
|
||||
DialogResult = DialogResult.Cancel,
|
||||
Location = new Point(contentWidth - padding - buttonWidth, yPos),
|
||||
Size = new Size(buttonWidth, buttonHeight),
|
||||
Font = new Font("Segoe UI", 9)
|
||||
};
|
||||
Controls.Add(_cancelButton);
|
||||
|
||||
AcceptButton = _launchButton;
|
||||
CancelButton = _cancelButton;
|
||||
}
|
||||
|
||||
private void OnLaunchClick(object? sender, EventArgs e)
|
||||
{
|
||||
LaunchSelectedApps();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Launches all selected apps.
|
||||
/// </summary>
|
||||
private void LaunchSelectedApps()
|
||||
{
|
||||
foreach (var checkbox in _checkboxes)
|
||||
{
|
||||
if (!checkbox.Checked)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (checkbox.Tag is not StartupApp app)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var startInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = Environment.ExpandEnvironmentVariables(app.Path),
|
||||
UseShellExecute = true
|
||||
};
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(app.Arguments))
|
||||
{
|
||||
startInfo.Arguments = Environment.ExpandEnvironmentVariables(app.Arguments);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(app.WorkingDirectory))
|
||||
{
|
||||
startInfo.WorkingDirectory = Environment.ExpandEnvironmentVariables(app.WorkingDirectory);
|
||||
}
|
||||
|
||||
Process.Start(startInfo);
|
||||
Console.WriteLine($"[DevDrive] Launched: {app.Name}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"[DevDrive] Failed to launch {app.Name}: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shows the startup dialog if there are apps to display.
|
||||
/// </summary>
|
||||
/// <param name="apps">List of startup apps.</param>
|
||||
/// <param name="driveName">Name of the drive.</param>
|
||||
public static void ShowIfNeeded(List<StartupApp> apps, string driveName)
|
||||
{
|
||||
if (apps.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (apps.Count == 1)
|
||||
{
|
||||
var app = apps[0];
|
||||
var result = MessageBox.Show(
|
||||
$"Launch {app.Name}?",
|
||||
$"{driveName} - Startup",
|
||||
MessageBoxButtons.YesNo,
|
||||
MessageBoxIcon.Question
|
||||
);
|
||||
|
||||
if (result == DialogResult.Yes)
|
||||
{
|
||||
LaunchSingleApp(app);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
Application.EnableVisualStyles();
|
||||
using var dialog = new StartupDialog(apps, driveName);
|
||||
dialog.ShowDialog();
|
||||
}
|
||||
|
||||
private static void LaunchSingleApp(StartupApp app)
|
||||
{
|
||||
try
|
||||
{
|
||||
var startInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = Environment.ExpandEnvironmentVariables(app.Path),
|
||||
UseShellExecute = true
|
||||
};
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(app.Arguments))
|
||||
{
|
||||
startInfo.Arguments = Environment.ExpandEnvironmentVariables(app.Arguments);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(app.WorkingDirectory))
|
||||
{
|
||||
startInfo.WorkingDirectory = Environment.ExpandEnvironmentVariables(app.WorkingDirectory);
|
||||
}
|
||||
|
||||
Process.Start(startInfo);
|
||||
Console.WriteLine($"[DevDrive] Launched: {app.Name}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"[DevDrive] Failed to launch {app.Name}: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user