windows顺序程序启动器
一、前言:为什么要做这个工具?
给客户部署,有时候如果程序很多都需要开机自启,所以做了这个工具。
二、工具核心功能亮点
核心能力:支持添加 EXE、BAT 文件,按自定义顺序批量启动
配置持久化:配置文件(config.json)与 EXE 同级
人性化设计:使用日志记录启动记录,窗口居中
程序备注:支持给每个程序加备注
重复校验:避免添加相同路径的程序
序号自动校准:删除 / 移动程序后,序号自动连续
双启动模式:
普通模式:可视化界面操作(添加 / 删除 / 调整顺序 / 手动启动)
自动模式:静默运行,启动完所有程序后自动退出(支持 1 分钟超时强制退出)
四、使用教程:两步上手
4.1 普通模式(可视化操作)
运行工具:主窗口自动居中,显示已保存的程序列表
添加程序:点击「添加」→ 选择 EXE/BAT 文件(自动填充备注)→ 确认
管理列表:选中程序后可「删除」「上移 / 下移」调整顺序
启动程序:点击「启动」,按序号依次启动,状态栏显示进度
4.3 配置文件说明
路径:与启动器 EXE 同级,文件名config.json
手动修改:可直接编辑 JSON 调整程序顺序、备注(注意序号连续)
备份恢复:复制config.json即可备份,换设备时粘贴到新 EXE 目录
使用教程
双击显示启动倒计时,如果没有取消就会自动启动,点击取消就会进入图形界面可以编辑启动顺序

点击立即执行就会立刻启动执行程序,点击取消会进入编辑界面,可以手动启动。

代码
项目入口
csharp
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace SequentialProgramLauncher
{
internal static class Program
{
private static readonly string LogFilePath = Path.Combine(
Path.GetDirectoryName(Application.ExecutablePath) ?? AppDomain.CurrentDomain.BaseDirectory,
"ProgramLauncher.log");
/// <summary>
/// 应用程序的主入口点
/// </summary>
[STAThread]
static void Main(string[] args)
{
LogMessage("----------", "------------------------------");
// 初始化日志
LogMessage("程序启动", $"命令行参数: {(args.Length > 0 ? string.Join(" ", args) : "无")}");
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
// 检查命令行参数:如果有 --auto 参数,则自动执行
if (args.Length > 0 && args[0].Equals("--auto", StringComparison.OrdinalIgnoreCase))
{
LogMessage("模式选择", "使用命令行自动执行模式");
// 自动执行程序
RunAutoModeAsync().Wait();
}
else
{
LogMessage("模式选择", "使用图形界面模式");
// 图形界面模式
Application.Run(new Form1());
}
}
/// <summary>
/// 异步执行命令行自动模式逻辑
/// </summary>
private static async Task RunAutoModeAsync()
{
LogMessage("自动模式", "开始执行自动启动程序");
// 1. 定时30分钟自毁(安全备份)- 修改为30分钟
_ = Task.Run(async () =>
{
await Task.Delay(TimeSpan.FromMinutes(30));
LogMessage("超时保护", "30分钟超时,强制退出");
Environment.Exit(0);
});
// 2. 执行自动任务
Form1 form = new Form1();
await form.AutoRunPrograms();
LogMessage("自动模式", "任务完成,程序退出");
Environment.Exit(0);
}
/// <summary>
/// 记录日志消息
/// </summary>
/// <param name="category">日志类别</param>
/// <param name="message">日志内容</param>
public static void LogMessage(string category, string message)
{
try
{
string logEntry = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} [{category}] {message}";
File.AppendAllText(LogFilePath, logEntry + Environment.NewLine);
Console.WriteLine(logEntry); // 同时在控制台输出(如果有)
}
catch (Exception ex)
{
Console.WriteLine($"日志写入失败: {ex.Message}");
}
}
}
}
项目逻辑
csharp
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace SequentialProgramLauncher
{
public partial class Form1 : Form
{
/// <summary>
/// 程序列表 - 存储所有待启动程序的配置信息
/// </summary>
private List<ProgramItem> _programList = new List<ProgramItem>();
/// <summary>
/// 配置文件路径 - 存储程序列表配置的JSON文件路径(与EXE同目录)
/// </summary>
private readonly string _configPath;
/// <summary>
/// 等待时间
/// </summary>
private readonly int _waitingTime = 2000;
private System.Windows.Forms.Timer _countdownTimer;
private int _countdownSeconds = 10;
private bool _autoStarted = false;
/// <summary>
/// 主窗体构造函数
/// </summary>
public Form1()
{
InitializeComponent();
// 设置主窗口启动时在屏幕正中间
this.StartPosition = FormStartPosition.CenterScreen;
// 配置文件路径设置:与当前执行程序(EXE)同级目录
string exePath = Application.ExecutablePath; // 获取EXE完整路径(含文件名)
string exeDirectory = Path.GetDirectoryName(exePath); // 提取EXE所在文件夹路径
_configPath = Path.Combine(exeDirectory, "config.json"); // 拼接配置文件完整路径
// 初始化列表视图列结构(包含序号、程序名称、备注、程序路径)
InitListViewColumns();
// 加载已保存的配置信息并更新界面显示
LoadConfig();
UpdateProgramList();
// 启动倒计时提示
StartCountdownPrompt();
}
/// <summary>
/// 启动倒计时提示
/// </summary>
private void StartCountdownPrompt()
{
Program.LogMessage("界面提示", "显示倒计时提示窗口");
// 创建倒计时标签
Label countdownLabel = new Label
{
Text = $"10秒内不关闭提示窗口会自动开始执行自动启动程序。\n\n倒计时: 10秒",
Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))),
TextAlign = System.Drawing.ContentAlignment.MiddleCenter,
AutoSize = false,
Size = new System.Drawing.Size(400, 100),
Location = new System.Drawing.Point(20, 20)
};
// 创建提示窗体
Form promptForm = new Form
{
Text = "自动启动提示",
Size = new System.Drawing.Size(440, 200),
StartPosition = FormStartPosition.CenterParent,
FormBorderStyle = FormBorderStyle.FixedDialog,
MaximizeBox = false,
MinimizeBox = false,
ShowInTaskbar = false,
TopMost = true
};
// 创建关闭按钮
Button closeButton = new Button
{
Text = "取消",
Size = new System.Drawing.Size(100, 30),
Location = new System.Drawing.Point(170, 130)
};
closeButton.Click += (s, e) =>
{
Program.LogMessage("用户操作", "用户取消了自动启动");
promptForm.DialogResult = DialogResult.Cancel;
promptForm.Close();
};
// 创建立即执行按钮
Button executeNowButton = new Button
{
Text = "立即执行",
Size = new System.Drawing.Size(100, 30),
Location = new System.Drawing.Point(50, 130)
};
executeNowButton.Click += (s, e) =>
{
Program.LogMessage("用户操作", "用户选择立即执行");
_autoStarted = true;
promptForm.DialogResult = DialogResult.OK;
promptForm.Close();
};
promptForm.Controls.Add(countdownLabel);
promptForm.Controls.Add(closeButton);
promptForm.Controls.Add(executeNowButton);
// 创建倒计时定时器
_countdownTimer = new System.Windows.Forms.Timer
{
Interval = 1000 // 1秒
};
_countdownSeconds = 10;
_countdownTimer.Tick += (s, e) =>
{
_countdownSeconds--;
if (_countdownSeconds > 0)
{
countdownLabel.Text = $"10秒内不关闭提示窗口会自动开始执行自动启动程序。\n\n倒计时: {_countdownSeconds}秒";
Application.DoEvents(); // 强制刷新UI
}
else
{
_countdownTimer.Stop();
Program.LogMessage("自动启动", "倒计时结束,开始自动执行程序");
_autoStarted = true;
promptForm.DialogResult = DialogResult.OK;
promptForm.Close();
}
};
promptForm.FormClosed += async (s, e) =>
{
_countdownTimer?.Stop();
if (_autoStarted && promptForm.DialogResult == DialogResult.OK)
{
await StartProgramsAsync();
}
};
// 显示提示窗体
_countdownTimer.Start();
promptForm.ShowDialog(this);
}
/// <summary>
/// 初始化列表视图的列结构
/// 定义列名、宽度等显示属性,支持程序信息的多维度展示
/// </summary>
private void InitListViewColumns()
{
lvPrograms.Columns.Clear();
lvPrograms.Columns.AddRange(new ColumnHeader[]
{
new ColumnHeader { Text = "序号", Width = 60 }, // 程序执行顺序序号
new ColumnHeader { Text = "程序名称", Width = 150 },// 程序文件名(不含扩展名)
new ColumnHeader { Text = "备注", Width = 180 }, // 程序描述备注信息
new ColumnHeader { Text = "程序路径", Width = 400 } // 程序文件完整路径
});
}
#region 配置文件操作模块
/// <summary>
/// 从配置文件加载程序列表数据
/// 支持JSON格式反序列化,自动处理序号连续性
/// </summary>
private void LoadConfig()
{
try
{
// 检查配置文件是否存在
if (File.Exists(_configPath))
{
// 读取JSON配置内容(UTF-8编码)
string jsonContent = File.ReadAllText(_configPath, System.Text.Encoding.UTF8);
// 反序列化为程序列表对象,若解析失败则创建空列表
_programList = JsonConvert.DeserializeObject<List<ProgramItem>>(jsonContent) ?? new List<ProgramItem>();
// 确保程序序号连续且按升序排列
_programList = _programList.OrderBy(item => item.Order).ToList();
for (int i = 0; i < _programList.Count; i++)
{
_programList[i].Order = i + 1; // 重新分配连续序号(1开始)
}
Program.LogMessage("配置加载", $"成功加载 {_programList.Count} 个程序配置");
}
else
{
Program.LogMessage("配置加载", "配置文件不存在,使用空列表");
}
}
catch (Exception ex)
{
// 异常处理:提示加载失败信息并初始化空列表
Program.LogMessage("配置加载错误", ex.Message);
MessageBox.Show($"配置加载失败:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
_programList = new List<ProgramItem>();
}
}
/// <summary>
/// 将当前程序列表数据保存到配置文件
/// 支持JSON格式序列化,确保数据持久化
/// </summary>
private void SaveConfig()
{
try
{
// 按序号排序后序列化为JSON字符串
string jsonContent = JsonConvert.SerializeObject(_programList.OrderBy(item => item.Order));
// 写入配置文件(UTF-8编码)
File.WriteAllText(_configPath, jsonContent, System.Text.Encoding.UTF8);
Program.LogMessage("配置保存", $"成功保存 {_programList.Count} 个程序配置");
}
catch (Exception ex)
{
// 异常处理:提示保存失败信息
Program.LogMessage("配置保存错误", ex.Message);
MessageBox.Show($"配置保存失败:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
#endregion
#region 界面更新模块
/// <summary>
/// 更新列表视图显示
/// 同步程序列表数据到界面,展示序号、名称、备注、路径信息
/// </summary>
private void UpdateProgramList()
{
// 清空现有列表项
lvPrograms.Items.Clear();
// 按序号排序后逐个添加到列表视图
foreach (var programItem in _programList.OrderBy(item => item.Order))
{
// 创建列表项(序号为第一列)
ListViewItem listViewItem = new ListViewItem(programItem.Order.ToString());
// 添加子项:程序名称、备注(无则显示"无")、程序路径
listViewItem.SubItems.Add(programItem.Name);
listViewItem.SubItems.Add(string.IsNullOrEmpty(programItem.Remark) ? "无" : programItem.Remark);
listViewItem.SubItems.Add(programItem.Path);
// 添加到列表视图
lvPrograms.Items.Add(listViewItem);
}
}
#endregion
#region 按钮事件处理模块
/// <summary>
/// 添加程序按钮点击事件
/// 打开添加程序弹窗,获取用户输入的程序路径和备注信息
/// </summary>
private void btnAdd_Click(object sender, EventArgs e)
{
Program.LogMessage("用户操作", "点击添加程序按钮");
// 创建添加程序弹窗(使用using确保自动释放资源)
using (AddProgramForm addProgramForm = new AddProgramForm())
{
#region 弹窗位置优化:设置为相对于主窗体居中显示
// 计算弹窗位置:主窗体中心坐标 - 弹窗一半尺寸
int formLeft = this.Left + (this.Width - addProgramForm.Width) / 2;
int formTop = this.Top + (this.Height - addProgramForm.Height) / 2;
// 设置弹窗位置(确保不超出屏幕边界)
addProgramForm.StartPosition = FormStartPosition.Manual;
addProgramForm.Location = new System.Drawing.Point(
Math.Max(0, formLeft), // 左边界不小于屏幕左边缘
Math.Max(0, formTop) // 上边界不小于屏幕上边缘
);
#endregion
// 显示弹窗(指定主窗体为所有者,确保模态显示)
if (addProgramForm.ShowDialog(this) == DialogResult.OK)
{
// 获取弹窗返回的程序路径和备注
string selectedFilePath = addProgramForm.SelectedPath;
string inputRemark = addProgramForm.InputRemark;
string programName = Path.GetFileNameWithoutExtension(selectedFilePath);
Program.LogMessage("添加程序", $"文件: {programName}, 路径: {selectedFilePath}, 备注: {inputRemark}");
// 重复校验:避免添加相同路径的程序
if (_programList.Any(item => item.Path.Equals(selectedFilePath, StringComparison.OrdinalIgnoreCase)))
{
Program.LogMessage("添加程序", "程序已存在于列表中");
MessageBox.Show("该程序已存在于列表中,无需重复添加!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
// 计算新程序的序号(最大序号+1,无数据时为1)
int newItemOrder = _programList.Any() ? _programList.Max(item => item.Order) + 1 : 1;
// 添加新程序到列表
_programList.Add(new ProgramItem
{
Order = newItemOrder,
Name = programName,
Path = selectedFilePath,
Remark = inputRemark
});
Program.LogMessage("添加程序", $"成功添加程序,新序号: {newItemOrder}");
// 保存配置并更新界面
SaveConfig();
UpdateProgramList();
}
}
}
/// <summary>
/// 删除程序按钮点击事件
/// 删除选中的程序项,并重排序号确保连续性
/// </summary>
private void btnDelete_Click(object sender, EventArgs e)
{
Program.LogMessage("用户操作", "点击删除程序按钮");
// 校验:是否选中程序项
if (lvPrograms.SelectedItems.Count == 0)
{
MessageBox.Show("请先在列表中选择要删除的程序!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
// 确认删除操作
if (MessageBox.Show("确定要删除选中的程序吗?删除后不可恢复!", "确认删除", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
{
// 获取选中项的序号
int selectedItemOrder = int.Parse(lvPrograms.SelectedItems[0].Text);
string programName = lvPrograms.SelectedItems[0].SubItems[1].Text;
Program.LogMessage("删除程序", $"序号: {selectedItemOrder}, 程序: {programName}");
// 从列表中移除对应程序项
_programList.RemoveAll(item => item.Order == selectedItemOrder);
// 重新排序并分配连续序号
var orderedProgramList = _programList.OrderBy(item => item.Order).ToList();
for (int i = 0; i < orderedProgramList.Count; i++)
{
orderedProgramList[i].Order = i + 1;
}
_programList = orderedProgramList;
Program.LogMessage("删除程序", "成功删除并重新排序");
// 保存配置并更新界面
SaveConfig();
UpdateProgramList();
}
}
/// <summary>
/// 上移按钮点击事件
/// 调整选中程序的执行顺序(向上移动一位)
/// </summary>
private void btnMoveUp_Click(object sender, EventArgs e)
{
Program.LogMessage("用户操作", "点击上移按钮");
// 校验:是否选中程序项,且不是第一个项
if (lvPrograms.SelectedItems.Count == 0 || lvPrograms.SelectedItems[0].Index == 0)
{
MessageBox.Show("当前程序已在第一位,无法上移!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
// 获取选中项的序号和对应的程序对象
int selectedItemOrder = int.Parse(lvPrograms.SelectedItems[0].Text);
var selectedProgram = _programList.First(item => item.Order == selectedItemOrder);
var previousProgram = _programList.First(item => item.Order == selectedItemOrder - 1);
Program.LogMessage("移动程序", $"将程序 {selectedProgram.Name} 从位置 {selectedItemOrder} 移动到 {selectedItemOrder - 1}");
// 交换序号(实现位置上移)
int tempOrder = selectedProgram.Order;
selectedProgram.Order = previousProgram.Order;
previousProgram.Order = tempOrder;
// 保存配置并更新界面
SaveConfig();
UpdateProgramList();
// 保持选中状态(上移后选中前一个位置)
lvPrograms.Items[selectedItemOrder - 2].Selected = true;
}
/// <summary>
/// 下移按钮点击事件
/// 调整选中程序的执行顺序(向下移动一位)
/// </summary>
private void btnMoveDown_Click(object sender, EventArgs e)
{
Program.LogMessage("用户操作", "点击下移按钮");
// 校验:是否选中程序项,且不是最后一个项
if (lvPrograms.SelectedItems.Count == 0 || lvPrograms.SelectedItems[0].Index == lvPrograms.Items.Count - 1)
{
MessageBox.Show("当前程序已在最后一位,无法下移!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
// 获取选中项的序号和对应的程序对象
int selectedItemOrder = int.Parse(lvPrograms.SelectedItems[0].Text);
var selectedProgram = _programList.First(item => item.Order == selectedItemOrder);
var nextProgram = _programList.First(item => item.Order == selectedItemOrder + 1);
Program.LogMessage("移动程序", $"将程序 {selectedProgram.Name} 从位置 {selectedItemOrder} 移动到 {selectedItemOrder + 1}");
// 交换序号(实现位置下移)
int tempOrder = selectedProgram.Order;
selectedProgram.Order = nextProgram.Order;
nextProgram.Order = tempOrder;
// 保存配置并更新界面
SaveConfig();
UpdateProgramList();
// 保持选中状态(下移后选中后一个位置)
lvPrograms.Items[selectedItemOrder].Selected = true;
}
/// <summary>
/// 启动按钮点击事件
/// 异步启动所有程序(按序号顺序)
/// </summary>
private async void btnStart_Click(object sender, EventArgs e)
{
Program.LogMessage("用户操作", "点击手动启动按钮");
// 异步执行程序启动逻辑(避免阻塞UI)
await StartProgramsAsync();
}
public async Task StartProgramsAsync()
{
Program.LogMessage("程序启动", $"开始执行程序列表,共 {_programList.Count} 个程序");
// 校验:程序列表是否为空
if (!_programList.Any())
{
Program.LogMessage("程序启动", "程序列表为空");
MessageBox.Show("程序列表为空,请先添加需要启动的程序!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
// 禁用操作按钮(避免并发操作)
SetButtonsEnabled(false);
// 创建列表来记录启动失败的程序
List<string> failedPrograms = new List<string>();
List<string> notFoundPrograms = new List<string>();
try
{
// 按序号顺序遍历程序列表
foreach (var programItem in _programList.OrderBy(item => item.Order))
{
// 构建显示名称(包含备注信息)
string displayName = string.IsNullOrEmpty(programItem.Remark)
? programItem.Name
: $"{programItem.Name}({programItem.Remark})";
// 校验程序文件是否存在
if (File.Exists(programItem.Path))
{
try
{
Program.LogMessage("启动程序", $"正在启动: {displayName} ({programItem.Path})");
// 更新状态提示
lblStatus.Text = $"正在启动:{displayName}...";
Application.DoEvents(); // 刷新UI显示
// 获取文件扩展名
string fileExtension = Path.GetExtension(programItem.Path).ToLower();
// 启动程序进程
using (var process = new System.Diagnostics.Process())
{
// 如果是批处理文件,使用cmd /k保持窗口打开
if (fileExtension == ".bat" || fileExtension == ".cmd")
{
// 使用cmd /k 保持窗口打开
process.StartInfo.FileName = "cmd.exe";
process.StartInfo.Arguments = $"/k \"{programItem.Path}\"";
process.StartInfo.WorkingDirectory = Path.GetDirectoryName(programItem.Path);
process.StartInfo.UseShellExecute = true;
}
else
{
// 其他类型文件按原方式启动
process.StartInfo.FileName = programItem.Path;
process.StartInfo.WorkingDirectory = Path.GetDirectoryName(programItem.Path);
process.StartInfo.UseShellExecute = true;
}
bool started = process.Start(); // 启动进程
if (started)
{
// 更新启动成功状态
lblStatus.Text = $"已启动:{displayName}";
Program.LogMessage("启动程序", $"成功启动: {displayName}");
}
else
{
// 启动失败
failedPrograms.Add(displayName);
Program.LogMessage("启动失败", $"无法启动: {displayName}");
lblStatus.Text = $"启动失败:{displayName}";
}
await Task.Delay(_waitingTime);
}
}
catch (Exception ex)
{
// 启动过程中出现异常
failedPrograms.Add(displayName);
Program.LogMessage("启动异常", $"{displayName}: {ex.Message}");
lblStatus.Text = $"启动异常:{displayName}";
}
}
else
{
// 程序文件不存在的处理
notFoundPrograms.Add(displayName);
Program.LogMessage("启动错误", $"文件不存在: {programItem.Path}");
lblStatus.Text = $"文件不存在:{displayName}";
// 等待短暂时间,让用户看到状态更新
await Task.Delay(500);
}
}
// 所有程序启动完成(或中途终止)
Program.LogMessage("程序启动", "所有程序启动完成");
lblStatus.Text = "所有程序启动完成!";
// 如果有启动失败或文件不存在的程序,显示汇总信息
if (failedPrograms.Count > 0 || notFoundPrograms.Count > 0)
{
string summaryMessage = "";
if (notFoundPrograms.Count > 0)
{
summaryMessage += $"文件不存在的程序({notFoundPrograms.Count}个):\n";
summaryMessage += string.Join("\n", notFoundPrograms.Select(name => $" • {name}"));
summaryMessage += "\n\n";
}
if (failedPrograms.Count > 0)
{
summaryMessage += $"启动失败的程序({failedPrograms.Count}个):\n";
summaryMessage += string.Join("\n", failedPrograms.Select(name => $" • {name}"));
}
// 计算成功启动的程序数量
int successCount = _programList.Count - failedPrograms.Count - notFoundPrograms.Count;
if (successCount > 0)
{
string successMessage = $"\n\n成功启动 {successCount} 个程序!";
if (failedPrograms.Count == 0 && notFoundPrograms.Count == 0)
{
MessageBox.Show("所有程序已按顺序启动完成!" + successMessage, "完成", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
else
{
MessageBox.Show($"{successMessage}\n\n但有部分程序存在问题:\n\n{summaryMessage}",
"部分程序启动完成", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}
else
{
MessageBox.Show($"所有程序启动失败!\n\n{summaryMessage}",
"启动失败", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
else
{
// 所有程序都成功启动
MessageBox.Show("所有程序已按顺序启动完成!", "完成", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
catch (Exception ex)
{
// 异常处理:提示启动失败信息
Program.LogMessage("启动异常", ex.Message);
lblStatus.Text = $"启动失败:{ex.Message}";
MessageBox.Show($"启动程序时发生错误:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
finally
{
// 恢复按钮可用状态
SetButtonsEnabled(true);
}
}
/// <summary>
/// 设置操作按钮的可用状态
/// 用于启动程序时禁用按钮,避免并发操作
/// </summary>
/// <param name="isEnabled">是否可用</param>
private void SetButtonsEnabled(bool isEnabled)
{
btnStart.Enabled = isEnabled;
btnAdd.Enabled = isEnabled;
btnDelete.Enabled = isEnabled;
btnMoveUp.Enabled = isEnabled;
btnMoveDown.Enabled = isEnabled;
}
#endregion
#region 命令行自动执行模块
/// <summary>
/// 命令行自动执行入口
/// 无需界面操作,直接按顺序启动所有程序
/// </summary>
/// <returns>异步任务对象</returns>
public async Task AutoRunPrograms()
{
Program.LogMessage("自动执行", "开始自动执行程序列表");
await StartProgramsAsync();
}
#endregion
}
}
数据模型
csharp
namespace SequentialProgramLauncher
{
/// <summary>
/// 程序项模型
/// 存储单个程序的配置信息(序号、路径、名称、备注)
/// </summary>
public class ProgramItem
{
/// <summary>
/// 序号
/// </summary>
public int Order { get; set; }
/// <summary>
/// 路径
/// </summary>
public string Path { get; set; }
/// <summary>
/// 名称
/// </summary>
public string Name { get; set; }
/// <summary>
/// 备注
/// </summary>
public string Remark { get; set; }
}
}
添加窗口逻辑
csharp
using System;
using System.IO;
using System.Windows.Forms;
namespace SequentialProgramLauncher
{
public partial class AddProgramForm : Form
{
// 对外暴露选择的程序路径和备注
public string SelectedPath { get; private set; }
public string InputRemark { get; private set; }
public AddProgramForm()
{
InitializeComponent();
}
// 选择程序按钮
private void btnBrowse_Click(object sender, EventArgs e)
{
using (OpenFileDialog ofd = new OpenFileDialog())
{
// 扩展筛选器:支持exe和bat文件
ofd.Filter = "可执行文件 (*.exe;*.bat)|*.exe;*.bat|所有文件 (*.*)|*.*";
ofd.Title = "选择要添加的程序(EXE/BAT)";
ofd.Multiselect = false;
if (ofd.ShowDialog() == DialogResult.OK)
{
SelectedPath = ofd.FileName;
txtProgramPath.Text = SelectedPath;
// 自动填充程序名称到备注(可选,方便用户)
if (string.IsNullOrEmpty(txtRemark.Text))
{
txtRemark.Text = Path.GetFileNameWithoutExtension(SelectedPath);
}
}
}
}
// 确认按钮
private void btnConfirm_Click(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(SelectedPath))
{
MessageBox.Show("请选择程序文件!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
InputRemark = txtRemark.Text.Trim();
DialogResult = DialogResult.OK;
Close();
}
// 取消按钮
private void btnCancel_Click(object sender, EventArgs e)
{
DialogResult = DialogResult.Cancel;
Close();
}
}
}
UI
窗口
csharp
namespace SequentialProgramLauncher
{
partial class Form1
{
private System.ComponentModel.IContainer components = null;
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows 窗体设计器生成的代码
/// <summary>
/// 设计器支持所需的方法 - 不要修改
/// 使用代码编辑器修改此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.lvPrograms = new System.Windows.Forms.ListView();
this.columnHeader1 = new System.Windows.Forms.ColumnHeader();
this.columnHeader2 = new System.Windows.Forms.ColumnHeader();
this.columnHeader3 = new System.Windows.Forms.ColumnHeader();
this.panel1 = new System.Windows.Forms.Panel();
this.btnStart = new System.Windows.Forms.Button();
this.btnMoveDown = new System.Windows.Forms.Button();
this.btnMoveUp = new System.Windows.Forms.Button();
this.btnDelete = new System.Windows.Forms.Button();
this.btnAdd = new System.Windows.Forms.Button();
this.lblStatus = new System.Windows.Forms.Label();
this.panel1.SuspendLayout();
this.SuspendLayout();
//
// lvPrograms
//
this.lvPrograms.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.columnHeader1,
this.columnHeader2,
this.columnHeader3});
this.lvPrograms.Dock = System.Windows.Forms.DockStyle.Top;
this.lvPrograms.FullRowSelect = true;
this.lvPrograms.GridLines = true;
this.lvPrograms.Location = new System.Drawing.Point(0, 0);
this.lvPrograms.Name = "lvPrograms";
this.lvPrograms.Size = new System.Drawing.Size(800, 350);
this.lvPrograms.TabIndex = 0;
this.lvPrograms.UseCompatibleStateImageBehavior = false;
this.lvPrograms.View = System.Windows.Forms.View.Details;
//
// columnHeader1
//
this.columnHeader1.Text = "序号";
this.columnHeader1.Width = 60;
//
// columnHeader2
//
this.columnHeader2.Text = "程序名称";
this.columnHeader2.Width = 150;
//
// columnHeader3
//
this.columnHeader3.Text = "程序路径";
this.columnHeader3.Width = 580;
//
// panel1
//
this.panel1.Controls.Add(this.btnStart);
this.panel1.Controls.Add(this.btnMoveDown);
this.panel1.Controls.Add(this.btnMoveUp);
this.panel1.Controls.Add(this.btnDelete);
this.panel1.Controls.Add(this.btnAdd);
this.panel1.Dock = System.Windows.Forms.DockStyle.Bottom;
this.panel1.Location = new System.Drawing.Point(0, 400);
this.panel1.Name = "panel1";
this.panel1.Size = new System.Drawing.Size(800, 50);
this.panel1.TabIndex = 1;
//
// btnStart
//
this.btnStart.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.btnStart.Location = new System.Drawing.Point(650, 10);
this.btnStart.Name = "btnStart";
this.btnStart.Size = new System.Drawing.Size(120, 30);
this.btnStart.TabIndex = 4;
this.btnStart.Text = "启动所有程序";
this.btnStart.UseVisualStyleBackColor = true;
this.btnStart.Click += new System.EventHandler(this.btnStart_Click);
//
// btnMoveDown
//
this.btnMoveDown.Location = new System.Drawing.Point(340, 10);
this.btnMoveDown.Name = "btnMoveDown";
this.btnMoveDown.Size = new System.Drawing.Size(100, 30);
this.btnMoveDown.TabIndex = 3;
this.btnMoveDown.Text = "下移";
this.btnMoveDown.UseVisualStyleBackColor = true;
this.btnMoveDown.Click += new System.EventHandler(this.btnMoveDown_Click);
//
// btnMoveUp
//
this.btnMoveUp.Location = new System.Drawing.Point(230, 10);
this.btnMoveUp.Name = "btnMoveUp";
this.btnMoveUp.Size = new System.Drawing.Size(100, 30);
this.btnMoveUp.TabIndex = 2;
this.btnMoveUp.Text = "上移";
this.btnMoveUp.UseVisualStyleBackColor = true;
this.btnMoveUp.Click += new System.EventHandler(this.btnMoveUp_Click);
//
// btnDelete
//
this.btnDelete.Location = new System.Drawing.Point(120, 10);
this.btnDelete.Name = "btnDelete";
this.btnDelete.Size = new System.Drawing.Size(100, 30);
this.btnDelete.TabIndex = 1;
this.btnDelete.Text = "删除";
this.btnDelete.UseVisualStyleBackColor = true;
this.btnDelete.Click += new System.EventHandler(this.btnDelete_Click);
//
// btnAdd
//
this.btnAdd.Location = new System.Drawing.Point(10, 10);
this.btnAdd.Name = "btnAdd";
this.btnAdd.Size = new System.Drawing.Size(100, 30);
this.btnAdd.TabIndex = 0;
this.btnAdd.Text = "添加程序";
this.btnAdd.UseVisualStyleBackColor = true;
this.btnAdd.Click += new System.EventHandler(this.btnAdd_Click);
//
// lblStatus
//
this.lblStatus.Dock = System.Windows.Forms.DockStyle.Fill;
this.lblStatus.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.lblStatus.ForeColor = System.Drawing.Color.Blue;
this.lblStatus.Location = new System.Drawing.Point(0, 350);
this.lblStatus.Name = "lblStatus";
this.lblStatus.Size = new System.Drawing.Size(800, 50);
this.lblStatus.TabIndex = 2;
this.lblStatus.Text = "就绪";
this.lblStatus.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
//
// MainForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 15F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(800, 450);
this.Controls.Add(this.lblStatus);
this.Controls.Add(this.panel1);
this.Controls.Add(this.lvPrograms);
this.Name = "MainForm";
this.Text = "顺序程序启动器";
this.panel1.ResumeLayout(false);
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.ListView lvPrograms;
private System.Windows.Forms.ColumnHeader columnHeader1;
private System.Windows.Forms.ColumnHeader columnHeader2;
private System.Windows.Forms.ColumnHeader columnHeader3;
private System.Windows.Forms.Panel panel1;
private System.Windows.Forms.Button btnAdd;
private System.Windows.Forms.Button btnDelete;
private System.Windows.Forms.Button btnMoveUp;
private System.Windows.Forms.Button btnMoveDown;
private System.Windows.Forms.Button btnStart;
private System.Windows.Forms.Label lblStatus;
}
}
添加的ui
csharp
namespace SequentialProgramLauncher
{
// 弹窗设计器代码
partial class AddProgramForm
{
private System.ComponentModel.IContainer components = null;
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
private void InitializeComponent()
{
this.label1 = new System.Windows.Forms.Label();
this.txtRemark = new System.Windows.Forms.TextBox();
this.label2 = new System.Windows.Forms.Label();
this.txtProgramPath = new System.Windows.Forms.TextBox();
this.btnBrowse = new System.Windows.Forms.Button();
this.btnConfirm = new System.Windows.Forms.Button();
this.btnCancel = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(15, 20);
this.label1.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(35, 12);
this.label1.TabIndex = 0;
this.label1.Text = "备注:";
//
// txtRemark
//
this.txtRemark.Location = new System.Drawing.Point(46, 18);
this.txtRemark.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.txtRemark.Name = "txtRemark";
this.txtRemark.Size = new System.Drawing.Size(484, 21);
this.txtRemark.TabIndex = 1;
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(15, 52);
this.label2.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(35, 12);
this.label2.TabIndex = 2;
this.label2.Text = "程序:";
//
// txtProgramPath
//
this.txtProgramPath.Location = new System.Drawing.Point(46, 50);
this.txtProgramPath.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.txtProgramPath.Name = "txtProgramPath";
this.txtProgramPath.ReadOnly = true;
this.txtProgramPath.Size = new System.Drawing.Size(406, 21);
this.txtProgramPath.TabIndex = 3;
//
// btnBrowse
//
this.btnBrowse.Location = new System.Drawing.Point(456, 49);
this.btnBrowse.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.btnBrowse.Name = "btnBrowse";
this.btnBrowse.Size = new System.Drawing.Size(74, 40);
this.btnBrowse.TabIndex = 4;
this.btnBrowse.Text = "浏览...";
this.btnBrowse.UseVisualStyleBackColor = true;
this.btnBrowse.Click += new System.EventHandler(this.btnBrowse_Click);
//
// btnConfirm
//
this.btnConfirm.Location = new System.Drawing.Point(86, 78);
this.btnConfirm.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.btnConfirm.Name = "btnConfirm";
this.btnConfirm.Size = new System.Drawing.Size(159, 30);
this.btnConfirm.TabIndex = 5;
this.btnConfirm.Text = "确认";
this.btnConfirm.UseVisualStyleBackColor = true;
this.btnConfirm.Click += new System.EventHandler(this.btnConfirm_Click);
//
// btnCancel
//
this.btnCancel.Location = new System.Drawing.Point(292, 78);
this.btnCancel.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.btnCancel.Name = "btnCancel";
this.btnCancel.Size = new System.Drawing.Size(160, 30);
this.btnCancel.TabIndex = 6;
this.btnCancel.Text = "取消";
this.btnCancel.UseVisualStyleBackColor = true;
this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
//
// AddProgramForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(541, 116);
this.Controls.Add(this.btnCancel);
this.Controls.Add(this.btnConfirm);
this.Controls.Add(this.btnBrowse);
this.Controls.Add(this.txtProgramPath);
this.Controls.Add(this.label2);
this.Controls.Add(this.txtRemark);
this.Controls.Add(this.label1);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "AddProgramForm";
this.Text = "添加程序";
this.ResumeLayout(false);
this.PerformLayout();
}
private System.Windows.Forms.Label label1;
private System.Windows.Forms.TextBox txtRemark;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.TextBox txtProgramPath;
private System.Windows.Forms.Button btnBrowse;
private System.Windows.Forms.Button btnConfirm;
private System.Windows.Forms.Button btnCancel;
}
}