寫程式執行 Windows 工作排程
假設大家都做過功課了,就依照微軟 CodePlex 教學指示下載所需檔案,本文的範例只需用到 TaskScheduler.zip,目前我下載到的最新版本是 1.5 Beta 2,解壓縮後可以得到 Microsoft.Win32.TaskScheduler.dll(核心元件)、Microsoft.Win32.TaskSchedule.xml(註解文件),以及 TaskScheduler.chm(說明文件),需引用 dll 檔:
本例仍然寫 ASP.NET 程式來示範,動線規劃是這樣:
- 頁面載入時取得主機上的所有排程塞到下拉選單裡,選取之後可以看到基本排程資訊;
- 放置一個按鈕,可用來執行選取的排程。
<div>
Root folder tasks:<asp:DropDownList ID="TasksDropDownList" runat="server" AutoPostBack="True"
OnSelectedIndexChanged="TasksDropDownList_SelectedIndexChanged">
<asp:ListItem> - 請選擇 - </asp:ListItem>
</asp:DropDownList>
<br />
<asp:Literal ID="InfoLiteral" runat="server"></asp:Literal>
<hr />
<asp:Button ID="RunButton" runat="server" Text=">> Run, Forrest. Run!" OnClick="RunButton_Click"
OnClientClick="return confirm('您確定要執行 Windows 工作排程?');" />
<br />
<asp:Literal ID="ResultLiteral" runat="server" EnableViewState="false"></asp:Literal>
</div>
</form>
const string workstation = "server";
const string domain = "domain";
const string userName = "hunterpo";
const string password = "P@ssW0rd";
const bool forceV1 = true;
/// <summary>
/// 取得主機上所有的工作排程
/// </summary>
private void GetTasks()
{
using (TaskService ts = new TaskService(workstation, userName, domain, password, forceV1))
{
// 保留預設選項 "- 請選擇 -"
if (TasksDropDownList.Items.Count > 1)
{
int startIndex = TasksDropDownList.Items.Count - 1;
for (int i = startIndex; i > 0; i--)
{
TasksDropDownList.Items.RemoveAt(i);
}
}
// Windows Vista 之前內建的都是 Task Scheduler 1.0
// 這情況下 Root Folder 是唯一的存放目錄
TaskFolder root = ts.RootFolder;
foreach (Task t in root.Tasks)
{
ListItem item = new ListItem(t.Name);
TasksDropDownList.Items.Add(item);
}
}
}
/// <summary>
/// 擷取工作排程內容
/// </summary>
/// <param name="taskName">排程名稱</param>
private string GetTaskInfo(string taskName)
{
StringBuilder sb = new StringBuilder();
using (TaskService ts = new TaskService(workstation, userName, domain, password, forceV1))
{
try
{
Task t = ts.GetTask(taskName);
sb.AppendFormat(
"<ul><li>工作排程:{0}</li><li>建立者:{1}</li><li>狀態:{2}</li>",
t.Name,
t.Definition.RegistrationInfo.Author,
t.State);
foreach (Trigger trg in t.Definition.Triggers)
sb.AppendFormat("<li>執行時間:{0}</li>", trg);
foreach (Action act in t.Definition.Actions)
sb.AppendFormat("<li>執行動作:{0}</li>", act);
sb.Append("</ul>");
}
catch (Exception ex)
{
sb.AppendFormat(
"取回 Windows 排程資訊發生例外:<br /><span style='color: #ff0000;'>{0}</span>",
ex.Message);
}
}
return sb.ToString();
}
/// <summary>
/// 立即執行工作排程
/// </summary>
/// <param name="taskName">排程名稱</param>
/// <returns></returns>
private int RunTask(string taskName)
{
using (TaskService ts = new TaskService(workstation, userName, domain, password, forceV1))
{
Task t = ts.GetTask(taskName);
t.Run();
return t.LastTaskResult;
}
}
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
GetTasks();
}
protected void TasksDropDownList_SelectedIndexChanged(object sender, EventArgs e)
{
if (TasksDropDownList.SelectedIndex > 0)
{
string taskName = TasksDropDownList.SelectedValue;
InfoLiteral.Text = GetTaskInfo(taskName);
}
else
{
InfoLiteral.Text = String.Empty;
}
}
protected void RunButton_Click(object sender, EventArgs e)
{
if (TasksDropDownList.SelectedIndex > 0)
{
string taskName = TasksDropDownList.SelectedValue;
int rc = RunTask(taskName);
ResultLiteral.Text = String.Format(
"<span style='color: #0000ff;'>***執行結果:{0}***</span><br /><br />",
rc);
}
else
{
ResultLiteral.Text = "<span style='color: #ff0000;'>選取的項目無效。</span>";
}
}
執行的效果如下:
這裡有個經驗不得不提,原本我的開發環境是運行在 Windows XP Pro 64-bit 上,而我們公司伺服器目前都還是停留在 Windows Server 2003,所以用 Task Sechduler 1.0 的物件模型存取 Windows 工作排程(本機或遠端)是沒有問題的,後來我把相同程式碼移到 Windows 7 上以取得本機的排程,然後將 forceV1 改為 false,單純的認為改用 Task Scheduler 2.0 物件模型應該行得通,沒想到卻發生例外狀況:
令人不解的地方是我只要將指定的驗證資料去掉,改用 TaskService 預設建構式去做就能順利存取,例如:
/// 取得主機上所有的工作排程
/// </summary>
private void GetTasks()
{
using (TaskService ts = new TaskService())
{
// 以下省略...
}
}
但 TaskService 預設建構式是以當前使用者的 Windows 驗證資料去存取本機工作排程(我用隨附於 VWD 的 Web 開發伺服器測試),跟我一開始強制指定的帳號密碼其實是同一個,離奇的是執行結果卻不一樣,不知道是不是遺漏了什麼細節…,這點若有找到答案再更新上來好了。(實在是待辦事項太多,讓我苟且一下吧 XD)
好啦,本篇稍微小試了一下,這個函式庫其實相當完整,可以操作的動作還很多,若對於用程式控制 Windows 工作排程有需要的人,可以發揮想像力去研究更進一步的應用,應該是滿 powerful 滴!
參考連結: