context: // DTM submission automation program
  // Author: Michael Goldish <mgoldish@redhat.com>
  // Based on sample code by Microsoft.
  
  // Note: this program has only been tested with DTM version 1.5.
  // It might fail to work with other versions, specifically because it uses
  // a few undocumented methods/attributes.
  
  using System;
  using System.Collections.Generic;
  using System.Text.RegularExpressions;
  using Microsoft.DistributedAutomation.DeviceSelection;
  using Microsoft.DistributedAutomation.SqlDataStore;
  
  namespace automate0
  {
      class AutoJob
      {
          // Wait for a machine to show up in the data store
          static void FindMachine(IResourcePool rootPool, string machineName)
          {
              Console.WriteLine("Looking for machine '{0}'", machineName);
              IResource machine = null;
              while (true)
              {
                  try
                  {
                      machine = rootPool.GetResourceByName(machineName);
                  }
                  catch (Exception e)
                  {
                      Console.WriteLine("Warning: " + e.Message);
                  }
                  // Make sure the machine is valid
                  if (machine != null &&
                      machine.OperatingSystem != null &&
                      machine.OperatingSystem.Length > 0 &&
                      machine.ProcessorArchitecture != null &&
                      machine.ProcessorArchitecture.Length > 0 &&
                      machine.GetDevices().Length > 0)
                      break;
                  System.Threading.Thread.Sleep(1000);
              }
              Console.WriteLine("Client machine '{0}' found ({1}, {2})",
                  machineName, machine.OperatingSystem, machine.ProcessorArchitecture);
          }
  
          // Delete a machine pool if it exists
          static void DeleteResourcePool(IDeviceScript script, string poolName)
          {
              while (true)
              {
                  try
                  {
                      IResourcePool pool = script.GetResourcePoolByName(poolName);
                      if (pool != null)
                          script.DeleteResourcePool(pool);
                      break;
                  }
                  catch (Exception e)
                  {
                      Console.WriteLine("Warning: " + e.Message);
                      System.Threading.Thread.Sleep(1000);
                  }
              }
          }
  
          // Set the machine's status to 'Reset' and optionally wait for it to become ready
          static void ResetMachine(IResourcePool rootPool, string machineName, bool wait)
          {
              Console.WriteLine("Resetting machine '{0}'", machineName);
              IResource machine;
              while (true)
              {
                  try
                  {
                      machine = rootPool.GetResourceByName(machineName);
                      machine.ChangeResourceStatus("Reset");
                      break;
                  }
                  catch (Exception e)
                  {
                      Console.WriteLine("Warning: " + e.Message);
                      System.Threading.Thread.Sleep(5000);
                  }
              }
              if (wait)
              {
                  Console.WriteLine("Waiting for machine '{0}' to be ready", machineName);
                  while (machine.Status != "Ready")
                  {
                      try
                      {
                          machine = rootPool.GetResourceByName(machineName);
                      }
                      catch (Exception e)
                      {
                          Console.WriteLine("Warning: " + e.Message);
                      }
                      System.Threading.Thread.Sleep(1000);
                  }
                  Console.WriteLine("Machine '{0}' is ready", machineName);
              }
          }
  
          // Look for a device in a machine, and if not found, keep trying for 3 minutes
          static IDevice GetDevice(IResourcePool rootPool, string machineName, string regexStr)
          {
              Regex deviceRegex = new Regex(regexStr, RegexOptions.IgnoreCase);
              int numAttempts = 1;
              DateTime endTime = DateTime.Now.AddSeconds(180);
              while (DateTime.Now < endTime)
              {
                  IResource machine = rootPool.GetResourceByName(machineName);
                  Console.WriteLine("Looking for device '{0}' in machine '{1}' (machine has {2} devices)",
                      regexStr, machineName, machine.GetDevices().Length);
                  foreach (IDevice d in machine.GetDevices())
                  {
                      if (deviceRegex.IsMatch(d.FriendlyName))
                      {
                          Console.WriteLine("Found device '{0}'", d.FriendlyName);
                          return d;
                      }
                  }
                  Console.WriteLine("Device not found");
                  if (numAttempts % 5 == 0)
                      ResetMachine(rootPool, machineName, true);
                  else
                      System.Threading.Thread.Sleep(5000);
                  numAttempts++;
              }
              Console.WriteLine("Error: device '{0}' not found", deviceRegex);
              return null;
          }
  
          static int Main(string[] args)
          {
              if (args.Length < 5)
              {
                  Console.WriteLine("Error: incorrect number of command line arguments");
                  Console.WriteLine("Usage: {0} serverName machinePoolName submissionName timeout machineName0 machineName1 ...",
                      System.Environment.GetCommandLineArgs()[0]);
                  return 1;
              }
              string serverName = args[0];
              string machinePoolName = args[1];
              string submissionName = args[2];
              double timeout = Convert.ToDouble(args[3]);
  
              List<string> machines = new List<string>();
              for (int i = 4; i < args.Length; i++)
                  machines.Add(args[i]);
  
              try
              {
                  // Initialize DeviceScript and connect to data store
                  Console.WriteLine("Initializing DeviceScript object");
                  DeviceScript script = new DeviceScript();
                  Console.WriteLine("Connecting to data store");
                  script.ConnectToNamedDataStore(serverName);
  
                  // Wait for client machines to become available
                  IResourcePool rootPool = script.GetResourcePoolByName("$");
                  foreach (string machineName in machines)
                      FindMachine(rootPool, machineName);
  
                  // Delete the machine pool if it already exists
                  DeleteResourcePool(script, machinePoolName);
  
                  // Create the machine pool and add the client machines to it
                  // (this must be done because jobs cannot be scheduled for machines in the
                  // default pool)
                  try
                  {
                      script.CreateResourcePool(machinePoolName, rootPool.ResourcePoolId);
                  }
                  catch (Exception e)
                  {
                      Console.WriteLine("Warning: " + e.Message);
                  }
                  IResourcePool newPool = script.GetResourcePoolByName(machinePoolName);
                  foreach (string machineName in machines)
                  {
                      Console.WriteLine("Moving machine '{0}' to pool '{1}'", machineName, machinePoolName);
                      rootPool.GetResourceByName(machineName).ChangeResourcePool(newPool);
                  }
  
                  // Reset client machine
                  foreach (string machineName in machines)
                      ResetMachine(rootPool, machineName, true);
  
                  // Get requested device regex and look for a matching device in the first machine
                  Console.WriteLine("Device to test:");
                  IDevice device = GetDevice(rootPool, machines[0], Console.ReadLine());
                  if (device == null)
                      return 1;
  
                  // Get requested jobs regex
                  Console.WriteLine("Jobs to run:");
                  Regex jobRegex = new Regex(Console.ReadLine(), RegexOptions.IgnoreCase);
  
                  // Create a submission
                  Object[] existingSubmissions = script.GetSubmissionByName(submissionName);
                  if (existingSubmissions.Length > 0)
                  {
                      Console.WriteLine("Submission '{0}' already exists -- removing it",
                          submissionName);
                      script.DeleteSubmission(((ISubmission)existingSubmissions[0]).Id);
                  }
                  string hardwareId = device.InstanceId.Remove(device.InstanceId.LastIndexOf("\\"));
                  Console.WriteLine("Creating submission '{0}' (hardware ID: {1})", submissionName, hardwareId);
                  ISubmission submission = script.CreateHardwareSubmission(submissionName, newPool.ResourcePoolId, hardwareId);
  
                  // Set submission DeviceData
                  List<Object> deviceDataList = new List<Object>();
                  while (true)
                  {
                      ISubmissionDeviceData dd = script.CreateNewSubmissionDeviceData();
                      Console.WriteLine("DeviceData name:");
                      dd.Name = Console.ReadLine();
                      if (dd.Name.Length == 0)
                          break;
                      Console.WriteLine("DeviceData data:");
                      dd.Data = Console.ReadLine();
                      deviceDataList.Add(dd);
                  }
                  submission.SetDeviceData(deviceDataList.ToArray());
  
                  // Set submission descriptors
                  List<Object> descriptorList = new List<Object>();
                  while (true)
                  {
                      Console.WriteLine("Descriptor path:");
                      string descriptorPath = Console.ReadLine();
                      if (descriptorPath.Length == 0)
                          break;
                      descriptorList.Add(script.GetDescriptorByPath(descriptorPath));
                  }
                  submission.SetLogoDescriptors(descriptorList.ToArray());
  
                  // Set machine dimensions
                  foreach (string machineName in machines)
                  {
                      IResource machine = rootPool.GetResourceByName(machineName);
                      while (true)
                      {
                          Console.WriteLine("Dimension name ({0}):", machineName);
                          string dimName = Console.ReadLine();
                          if (dimName.Length == 0)
                              break;
                          Console.WriteLine("Dimension value ({0}):", machineName);
                          machine.SetDimension(dimName, Console.ReadLine());
                      }
                      // Set the WDKSubmissionId dimension for all machines
                      machine.SetDimension("WDKSubmissionId", submission.Id.ToString() + "_" + submission.Name);
                  }
  
                  // Get job parameters
                  List<string> paramNames = new List<string>();
                  List<string> paramValues = new List<string>();
                  foreach (string machineName in machines)
                  {
                      while (true)
                      {
                          Console.WriteLine("Parameter name ({0}):", machineName);
                          string paramName = Console.ReadLine();
                          if (paramName.Length == 0)
                              break;
                          Console.WriteLine("Device regex ({0}):", machineName);
                          IDevice d = GetDevice(rootPool, machineName, Console.ReadLine());
                          if (d == null)
                              return 1;
                          string deviceName = d.GetAttribute("name")[0].ToString();
                          Console.WriteLine("Setting parameter value to '{0}'", deviceName);
                          paramNames.Add(paramName);
                          paramValues.Add(deviceName);
                      }
                  }
  
                  // Find jobs that match the requested pattern
                  Console.WriteLine("Scheduling jobs:");
  
gt:                 List<IJob> jobs = new List<IJob>();