/* NOTICE OF CHANGES: date of change: 6/12/2007 change: Exposed ITask interface and task name from the ScheduledTasks.cs for easy consumption . */ using System; using System.IO; using System.Runtime.InteropServices; using TaskSchedulerInterop; using SMStrings; using System.DirectoryServices; namespace TaskScheduler { /// /// ScheduledTasks represents the a computer's Scheduled Tasks folder. Using a ScheduledTasks /// object, you can discover the names of the tasks in the folder and you can open a task /// to work with it. You can also create or delete tasks. /// /// /// A ScheduledTasks object holds a COM interface that can be released by calling . /// public class ScheduledTasks : IDisposable { /// /// Underlying COM interface. /// private ITaskScheduler its = null; private ITask iTask = null; private string name = null; // --- Contructors --- /// /// Constructor to use Scheduled tasks of a remote computer identified by a UNC /// name. The calling process must have administrative privileges on the remote machine. /// May throw exception if the computer's task scheduler cannot be reached, and may /// give strange results if the argument is not in UNC format. /// /// The remote computer's UNC name, e.g. "\\DALLAS". /// The Task Scheduler could not be accessed. public ScheduledTasks(string computer) : this() { its.SetTargetComputer(computer); } /// /// Constructor to use Scheduled Tasks of the local computer. /// public ScheduledTasks() { CTaskScheduler cts = new CTaskScheduler(); its = (ITaskScheduler)cts; } // --- Methods --- private string[] GrowStringArray(string[] s, uint n) { string[] sl = new string[s.Length + n]; for (int i=0; i /// Return the names of all scheduled tasks. The names returned include the file extension ".job"; /// methods requiring a task name can take the name with or without the extension. /// /// The names in a string array. public string[] GetTaskNames() { const int TASKS_TO_FETCH = 10; string[] taskNames = {}; int nTaskNames = 0; IEnumWorkItems ienum; its.Enum(out ienum); uint nFetchedTasks; IntPtr pNames; //venua: BURT 718868 string sComputer; its.GetTargetComputer(out sComputer); sComputer = sComputer.TrimStart('\\'); DirectoryEntry rootDSE = new DirectoryEntry("LDAP://rootDSE"); string configNaming = (string)rootDSE.Properties["configurationNamingContext"].Value; string rootPath = "LDAP://" + configNaming; rootDSE.Dispose(); DirectoryEntry root = new DirectoryEntry(rootPath); DirectorySearcher searcher = new DirectorySearcher(root); searcher.Filter = "(objectCategory=msExchMDBAvailabilityGroup)"; SearchResultCollection results = searcher.FindAll(); bool bflag = false; foreach (SearchResult result in results) { if (result.Properties.Contains("name")) { if (sComputer == (string)result.Properties["name"][0]) //venua: BURT 718868 if the node is dag then skip checking for schedules { bflag = true; break; } } } //venua: BURT 718868skip get schedules for dag node //since ienum.Next is returning after 1 min when trying to connect to dag node if (!bflag) { while (ienum.Next(TASKS_TO_FETCH, out pNames, out nFetchedTasks) >= 0 && nFetchedTasks > 0) { taskNames = GrowStringArray(taskNames, nFetchedTasks); while (nFetchedTasks > 0) { IntPtr name = Marshal.ReadIntPtr(pNames, (int)--nFetchedTasks * IntPtr.Size); taskNames[nTaskNames++] = Marshal.PtrToStringUni(name); Marshal.FreeCoTaskMem(name); } Marshal.FreeCoTaskMem(pNames); } } root.Dispose(); searcher.Dispose(); return taskNames; } // BURT273450: 1-22-2006 4:00pm PST, Crood, detect invalid job name /w msg class TaskNameInvalidException : Exception { // Validate the name public static bool IsValid(string taskName) { return (!string.IsNullOrEmpty(taskName) && (-1 == taskName.IndexOfAny(new char[] { '*', '?', '/', '\\', '<', '>', '|' }))); } // Create a more meaningful message public TaskNameInvalidException(Exception exInner): base(string.Format(SMSharedStringTable.GetString("SMSCHEDULER_INVALIDJOBNAME_14"), System.Runtime.InteropServices.Marshal.GetHRForException(exInner)), exInner) { } } /// /// Creates a new task on the system with the given . /// /// Task names follow normal filename character restrictions. The name /// will be come the name of the file used to store the task (with .job added). /// Name for the new task. /// Instance of new task. /// There is an existing task with the given name. public Task CreateTask(string name) { Task tester = OpenTask(name); if (tester != null) { throw new ArgumentException(string.Format(SMSharedStringTable.GetString("SMSCHEDULER_THETASK0ALREAD_1"), name)); } try { this.name = name; object o; its.NewWorkItem(name, ref CTaskGuid, ref ITaskGuid, out o); this.iTask = (ITask)o; return new Task(this.iTask, this.name); } catch (Exception ex) { // BURT273450: 1-22-2006 4:00pm PST, Crood, detect invalid job name /w msg if (!TaskNameInvalidException.IsValid(name)) throw new TaskNameInvalidException(ex); throw; } } public void SaveTask(Task task) { try { if (task.Name == this.name) its.AddWorkItem(this.name, this.iTask); return; } catch(Exception ex) { return; } } /// /// Deletes the task of the given . /// /// If you delete a task that is open, a subsequent save will throw an /// exception. You can save to a filename, however, to create a new task. /// Name of task to delete. /// True if the task was deleted, false if the task wasn't found. public bool DeleteTask(string name) { try { Task tester = OpenTask(name); if (tester != null) { tester.Triggers.Clear(); tester.Close(); its.Delete(name); } return true; } catch { return false; } } /// /// Opens the task with the given . An open task holds COM interfaces /// which are released by the Task's Close() method. /// /// If the task does not exist, null is returned. /// Name of task to open. /// An instance of a Task, or null if the task name couldn't be found. public Task OpenTask(string name) { try { object o; its.Activate(name, ref ITaskGuid, out o); ITask iTask = (ITask)o; return new Task(iTask, name); } catch { return null; } } #region Implementation of IDisposable /// /// The internal COM interface is released. Further access to the /// object will throw null reference exceptions. /// public void Dispose() { Marshal.ReleaseComObject(its); its = null; } #endregion // Two Guids for calls to ITaskScheduler methods Activate(), NewWorkItem(), and IsOfType() internal static Guid ITaskGuid; internal static Guid CTaskGuid; static ScheduledTasks() { ITaskGuid = Marshal.GenerateGuidForType(typeof(ITask)); CTaskGuid = Marshal.GenerateGuidForType(typeof(CTask)); } } }