Scheduler.NET for UltraDefrag
使用 PInvoke 向 Windows 添加计划任务
介绍
之前,我一直在寻找一个适用于 Windows 的开源磁盘碎片整理程序。 但是没有一个具有我想要的功能,即一个可以在启动时运行的本机可执行文件。 但是,我可以说服UltraDefrag的作者实现此功能,以换取编写手册。 之后不久,我决定贡献一个实用程序,将 UltraDefrag 配置为作为计划任务运行。 这是一个非常简单的 WinForms 应用程序,需要执行两个独特的任务。 首先是将服务添加到任务计划程序服务。 第二是获取可用驱动器的列表。
代码如何工作
从磁盘驱动器的角度来看,我有两个问题:首先是获取计算机上的驱动器盘符列表,其次是确定哪些驱动器盘符代表硬盘驱动器。这都是通过调用 .NET API 实现的,如下所示:
DriveInfo[] driveInfo = DriveInfo.GetDrives();
List<string> drives = new List<string>();
foreach (DriveInfo drive in driveInfo) {
DriveType driveType = Native.GetDriveType(drive.Name);
if(
driveType != DriveType.Fixed
&&
driveType != DriveType.Removable
&&
driveType != DriveType.RAMDisk
) continue;
if(!is_virtual(drive.Name[0]))
drives.Add(drive.Name);
}
cmbDrives.DataSource = drives;
获取驱动器盘符列表后,必须进行 API 调用以添加计划任务。 用于此操作的 API 调用是 NetScheduleJobAdd。 此 API 调用使用一个复杂的数据类型,该类型非常简单。 我已在前一个链接中的 PInvoke.NET 页面上记录了如何使用此类型。 下图说明了对 NetScheduleJobAdd
的应用程序调用。 请注意,下面的函数是 ok 按钮的单击事件的委托。
private void cmdOk_Click(object sender, EventArgs e)
{
IntPtr ptr;
AT_INFO atInfo = new AT_INFO();
atInfo.Command = string.Format("udefrag {0}", cmbDrives.SelectedValue);
atInfo.DaysOfMonth = 0;
atInfo.DaysOfWeek = 0;
atInfo.Flags = AT_JobFlags.JOB_RUN_PERIODICALLY | AT_JobFlags.JOB_NONINTERACTIVE;
atInfo.JobTime = (uint) timePicker.Value.TimeOfDay.TotalMilliseconds;
int jobId;
if (radDaily.Checked)
{
atInfo.DaysOfWeek = 0x7F;
}
else if (radWeekly.Checked)
{
if (chkMonday.Checked) atInfo.DaysOfWeek |= 0x1;
if (chkTuesday.Checked) atInfo.DaysOfWeek |= 0x2;
if (chkWednesday.Checked) atInfo.DaysOfWeek |= 0x4;
if (chkThursday.Checked) atInfo.DaysOfWeek |= 0x8;
if (chkFriday.Checked) atInfo.DaysOfWeek |= 0x10;
if (chkSaturday.Checked) atInfo.DaysOfWeek |= 0x20;
if (chkSunday.Checked) atInfo.DaysOfWeek |= 0x40;
}
ptr = Marshal.AllocHGlobal(Marshal.SizeOf(atInfo));
Marshal.StructureToPtr(atInfo, ptr, true);
Native.NetScheduleJobAdd(null, ptr, out jobId);
}
兴趣点
最初,我是在 http://www.dotnet247.com/247reference/msgs/47/239675.aspx 找到了 NetScheduleJobAdd()
的 PInvoke 代码。 但是,该 URL 不再有效,并且互联网时光机没有任何引用。 我在 PInvoke.NET 上记录了 PInvoke 调用。
进一步开发
该程序当前被硬编码为与 ultra defrag 一起使用。 但是,很容易使它可配置为与任何在硬盘驱动器上运行的应用程序一起使用。 这只是用从 *config* 文件加载的 string
替换一个硬编码的 string
就可以实现此功能。 必须添加一些其他配置选项,才能适当地重新命名其他应用程序的配置实用程序。 例如,必须更改标题栏。
不幸的是,我没有时间进行此类更改。 但是,如果您认为此代码可以很好地与 UltraDefrag 以外的程序一起使用,我很乐意将您的更改包含在 UltraDefrag 附带的版本中,但需要经过 UltraDefrag 作者 Dmitri 的批准。
链接
历史
- 2009 年 1 月 7 日:本文的第一个版本