Running Tasks
I've had some questions regarding how to run tasks via the SDK so I thought I would post an example here. The code below shows the various ways of executing tasks in the SDK. The underlying implementation relies on query notifications from SQL 2005 to notify us whenever the status of a particular batch changes; we actually register a new notification for every batch, but since the format of the notification is the same and only parameters change, the performance is not overly affected.
The code is pretty self-explanatory. I don't recommend using the synchronous version of the API because if something unexpected happens to the task your application will be stuck on the call until it times out (30 minutes) OR if you actually expect your task to take longer than 30 minutes, this version will timeout prior to your task completing. Also, if you don't care about getting notified of the results immediately, you can use the SubmitTask(s) API without providing a callback and simply query for results at a later time using the batch id you get from the call and the GetMonitoringTaskResults method available on both ManagementGroup and MonitoringObject.
using System;
using System.Collections.ObjectModel;
using Microsoft.EnterpriseManagement;
using Microsoft.EnterpriseManagement.Configuration;
using Microsoft.EnterpriseManagement.Monitoring;
namespace Jakub_WorkSamples
{
partial class Program
{
static void RunningTasks()
{
// Connect to the local management group
ManagementGroup mg = new ManagementGroup("localhost");
// First lets get the task we are going to execute
// Note: Indexing the result like this is not necessarily the best
// practice here, since there could be more than one task with this
// name.
MonitoringTaskCriteria taskCriteria = new MonitoringTaskCriteria(
"Name = 'Microsoft.SystemCenter.GetAllFailedWorkflows'");
MonitoringTask failedWorkflowTask =
mg.GetMonitoringTasks(taskCriteria)[0];
// Configuration allows you to specify credentials to use different
// from the default. It also allows you to specify overrides, if
// any are available
MonitoringTaskConfiguration failedWorkflowTaskConfiguration =
new MonitoringTaskConfiguration();
// Now we need to get an instance of a health service
// First get the class
MonitoringClass healthServiceClass =
mg.GetMonitoringClass(SystemMonitoringClass.HealthService);
// Next get the object (we'll just pick the first one)
MonitoringObject healthServiceObject =
mg.GetMonitoringObjects(healthServiceClass)[0];
// Object centric task execution
// Synchronous
ReadOnlyCollection<MonitoringTaskResult> results =
healthServiceObject.ExecuteMonitoringTask(failedWorkflowTask,
failedWorkflowTaskConfiguration);
// Asynchronous (standard .Net implementation)
IAsyncResult asyncTaskResult =
healthServiceObject.BeginExecuteMonitoringTask(
failedWorkflowTask,
failedWorkflowTaskConfiguration,
null, // You can specify a callback
null); // And additional context
results = healthServiceObject.EndExecuteMonitoringTask(asyncTaskResult);
// Asynchronous (more advanced SCOM specific implementation)
Guid batchId = healthServiceObject.SubmitMonitoringTask(failedWorkflowTask,
failedWorkflowTaskConfiguration,
MyTaskCallback);
// Task execution off ManagementGroup (for multiple targets)
PartialMonitoringObject[] targets =
new PartialMonitoringObject[] { healthServiceObject };
// Synchronous
results = mg.ExecuteMonitoringTask(targets, failedWorkflowTask,
failedWorkflowTaskConfiguration);
// Asynchronous (standard .Net implementation)
asyncTaskResult =
mg.BeginExecuteMonitoringTask(
targets,
failedWorkflowTask,
failedWorkflowTaskConfiguration,
null, // You can specify a callback
null); // And additional context
results = mg.EndExecuteMonitoringTask(asyncTaskResult);
// Asynchronous (more advanced SCOM specific implementation)
batchId = mg.SubmitMonitoringTask(targets,
failedWorkflowTask,
failedWorkflowTaskConfiguration,
MyTaskCallback);
// Wait for the task to complete
System.Threading.Thread.Sleep(5000);
}
private static void MyTaskCallback(Guid batchId,
ReadOnlyCollection<MonitoringTaskResult> results,
bool completed)
{
if (completed)
{
Console.WriteLine("Batch Id {0} is done!", batchId);
}
}
}
}
Comments
Anonymous
June 27, 2007
The comment has been removedAnonymous
June 27, 2007
The UI usually queries using Name = 'blah' OR DisplayName = 'blah'. If you know which the name is, you can exclude the other. If there is a space, it is for sure the Name, but otherwise it could be either.Anonymous
June 27, 2007
I found that , if the task in dbo.task , I can get it , if it is in dbo.ConsoleTask , I cannot get it ? Right?Anonymous
June 27, 2007
For console task use GetMonitoringConsoleTasks. Also in my previous comment I meant that if there is a space it is for sure the DISPLAY Name.Anonymous
March 27, 2015
Great Article By the Way. I am using SCOM 2012 and trying to call a task ASYNC which works fine but I cannot seem to be able to grab the SCOM BatchId and ManagementGroup from the IAsyncResult (even though I can see it in the debug visualizer). Any suggestions on how I can get the BatchId and ManagementGroup while still calling the task asynchronously? Thanks in advance for your help IASyncResult Result = mgManagementGroup.TaskRuntime.BeginExecuteTask(moSCOMTargets, mptSCOMTask, tcTaskConfiguration, null, null)Anonymous
April 01, 2015
The comment has been removedAnonymous
April 03, 2015
The comment has been removedAnonymous
April 05, 2015
Hi, Jakub Thank you for the quick reply. I have one more question. Can you tell how to configure to specify credentials to use instead of default. Thank youAnonymous
April 05, 2015
You can set it as part of the configuration you submit: msdn.microsoft.com/.../hh327529.aspxAnonymous
April 06, 2015
Hi, Jakub Since "TaskCredentials" is abstract, cannot directly assign as instance.Credentials = value. Is there any other possible ways to do this. Thank youAnonymous
April 07, 2015
You want this one: msdn.microsoft.com/.../hh327756.aspx