4

I'm making a wrapper around a server application I'm developing, that displays debug information such as memory, cpu usage, threads and tasks, heap information etc, and provides some way to start and stop the server.

Visual Studio has a handy Task Window for debugging asynchronous apps. It provides the following information: Id, Status, Start time, Duration and Location, as well as position. Is it possible to get the same information from inside my application? I'm open to all kinds of reflection, hacks and undocumented dirty stuff to get this information as it's not production code.

I tried to execute the internal method GetScheduledTasksForDebugger on the TaskScheduler.Default object (Which is a ThreadPoolTaskScheduler object), but that returned 0 tasks, even though the Visual Studio Task Window shows that at least two tasks are scheduled.

Visual Studio Task Window: Visual Studio Task Window

AkselK
  • 2,563
  • 21
  • 39
  • You probably can't do that. – SLaks May 17 '16 at 21:32
  • Visual Studio obviously can, so I believe it's possible. It just might require some obscene P/Invoke, COM wrapping, Roslyn magic, or the Microsoft.Diagnostics.Runtime project. – AkselK May 17 '16 at 21:42
  • 1
    If anything, it would require a debugger (which must be a separate process) – SLaks May 17 '16 at 21:52
  • This seems to be a tutorial on writing a debugger. It might point you down the right path? http://www.codeproject.com/Articles/43682/Writing-a-basic-Windows-debugger – Ranger May 17 '16 at 21:54
  • Could this be a way to go? I tried to implement the listener, but I got no event callbacks. http://stackoverflow.com/questions/28540728/how-do-i-listen-to-tpl-taskstarted-taskcompleted-etw-events – AkselK May 18 '16 at 13:18

1 Answers1

0

There is a managed wrapper for the TaskScheduler found on CodePlex.

And using that wrapper it is possible to enumerate the tasks:

using System;
using Microsoft.Win32.TaskScheduler;

namespace ListTasks
{
    class Program
    {
        static void EnumFolderTasks(TaskFolder fld)
        {
            foreach (Task task in fld.Tasks)
                DisplayTask(task);

            foreach (TaskFolder sfld in fld.SubFolders)
                EnumFolderTasks(sfld);
        }

        static void DisplayTask(Task t)
        {
            Console.WriteLine("Task: {0, -60} Active: {1, -5} Enabled: {2, -5}", 
                              t.Name, t.IsActive, t.Enabled);
        }

        static void Main(string[] args)
        {
            using (TaskService ts = new TaskService())
            {
                EnumFolderTasks(ts.RootFolder);
            }
        }
    }
}

As to whether the Id, Status, Start time, Duration and Location information is available, I'm not sure.

But looking at the definition of the Task object it does contain lots of information and at first glance most of that information does seem to be available:

EDIT: Added namespace to remove some confusion about the Task object.

namespace Microsoft.Win32.TaskScheduler
{ 
    public class Task : IDisposable
    {
        public TaskDefinition Definition { get; }
        public bool Enabled { get; set; }
        public TaskFolder Folder { get; }
        public bool IsActive { get; }
        public DateTime LastRunTime { get; }
        public int LastTaskResult { get; }
        public string Name { get; }
        public DateTime NextRunTime { get; }
        public int NumberOfMissedRuns { get; }
        public string Path { get; }
        public bool ReadOnly { get; }
        public GenericSecurityDescriptor SecurityDescriptor { get; set; }
        public virtual TaskState State { get; }
        public TaskService TaskService { get; }
        public string Xml { get; }
        public void Dispose();
        public void Export(string outputFileName);
        public TaskSecurity GetAccessControl();
        public TaskSecurity GetAccessControl(AccessControlSections includeSections);
        public RunningTaskCollection GetInstances();
        public DateTime GetLastRegistrationTime();
        public DateTime[] GetRunTimes(DateTime start, DateTime end, uint count = 0);
        public string GetSecurityDescriptorSddlForm(SecurityInfos includeSections = SecurityInfos.Owner | SecurityInfos.Group | SecurityInfos.DiscretionaryAcl);
        public void RegisterChanges();
        public RunningTask Run(params string[] parameters);
        public RunningTask RunEx(TaskRunFlags flags, int sessionID, string user, params string[] parameters);
        public void SetAccessControl(TaskSecurity taskSecurity);
        public void SetSecurityDescriptorSddlForm(string sddlForm, TaskSetSecurityOptions options = TaskSetSecurityOptions.None);
        public void ShowPropertyPage();
        public void Stop();
        public override string ToString();
    }
}    
jussij
  • 10,370
  • 1
  • 33
  • 49
  • I'm sorry, but I'm not asking about the Windows Task Scheduler, but the C# Task API, which is a completely different thing. – AkselK May 18 '16 at 07:22
  • That is not the Task object found in the C# Task API (in particular the TPL library). It's just the Task object which is part of the C# managed project that I linked to. That managed library is just a C# wrapper around the Windows Task Scheduler layer that you are referring to. – jussij May 18 '16 at 07:33
  • 1
    @jussij you've got it backward, the op is not refering to the Windows task scheduler but to the task view (for running tasks for the task api) in visual studio. He knows what you refer to is the task object for the scheduler and not the task api but was mentioning the whole answer was off topic – Ronan Thibaudau May 18 '16 at 08:23