Unterstützen von Aufträgen

In diesem Beispiel wird gezeigt, wie Aufträge beim Schreiben von Cmdlets unterstützt werden. Wenn Sie möchten, dass Benutzer Ihr Cmdlet als Hintergrundauftrag ausführen, müssen Sie den im folgenden Verfahren beschriebenen Code einfügen. Weitere Informationen zu Hintergrundaufträgen finden Sie unter Hintergrundaufträge.

So unterstützen Sie Aufträge

  1. Definieren Sie einen AsJob switch-Parameter, damit der Benutzer entscheiden kann, ob das Cmdlet als Auftrag ausgeführt werden soll.

    Das folgende Beispiel zeigt eine AsJob-Parameterdeklaration.

    [Parameter()]
    public SwitchParameter AsJob
    {
      get { return asjob; }
      set { asjob = value; }
    }
    private bool asjob;
    
  2. Erstellen Sie ein Objekt, das von der System.Management.Automation.Job-Klasse abgeleitet wird. Dieses Objekt kann ein benutzerdefiniertes Auftragsobjekt oder eines der von Windows PowerShell bereitgestellten Auftragsobjekte sein, z. B. ein System.Management.Automation.Pseventjob-Objekt.

    Das folgende Beispiel zeigt ein benutzerdefiniertes Auftragsobjekt.

    private SampleJob job = new SampleJob("Get-ProcAsJob");
    
  3. Fügen Sie in einer Datensatzverarbeitungsmethode eine -Anweisung hinzu, if um zu ermitteln, ob das Cmdlet als Auftrag ausgeführt werden soll. Im folgenden Code wird die System.Management.Automation.Cmdlet.ProcessRecord-Methode verwendet.

    protected override void ProcessRecord()
    {
      if (asjob)
      {
        // Add the job definition to the job repository,
        // return the job object, and then create the thread
        // used to run the job.
        JobRepository.Add(job);
        WriteObject(job);
        ThreadPool.QueueUserWorkItem(WorkItem);
      }
      else
      {
        job.ProcessJob();
        foreach (PSObject p in job.Output)
        {
          WriteObject(p);
        }
      }
    }
    
  4. Implementieren Sie für benutzerdefinierte Auftragsobjekte die Auftragsklasse.

    private class SampleJob : Job
    {
      internal SampleJob(string command)
          : base(command)
      {
        SetJobState(JobState.NotStarted);
      }
      public override string StatusMessage
      {
        get { throw new NotImplementedException(); }
      }
    
      public override bool HasMoreData
      {
        get
        {
          return hasMoreData;
        }
      }
      private bool hasMoreData = true;
    
      public override string Location
      {
        get { throw new NotImplementedException(); }
      }
    
      public override void StopJob()
      {
        throw new NotImplementedException();
      }
    
      internal void ProcessJob()
      {
        SetJobState(JobState.Running);
        DoProcessLogic();
        SetJobState(JobState.Completed);
      }
    
      // Retrieve the processes of the local computer.
      void DoProcessLogic()
      {
        Process[] p = Process.GetProcesses();
    
        foreach (Process pl in p)
        {
          Output.Add(PSObject.AsPSObject(pl));
        }
        Output.Complete();
      } // End DoProcessLogic.
    } // End SampleJob class.
    
  5. Wenn das Cmdlet die Arbeit ausführt, rufen Sie die System.Management.Automation.Cmdlet.WriteObject-Methode auf, um ein Prozessobjekt an die Pipeline zurückzugeben. Wenn die Arbeit als Auftrag ausgeführt wird, fügen Sie dem Auftrag einen untergeordneten Auftrag hinzu.

    void DoProcessLogic(bool asJob)
    {
      Process[] p = Process.GetProcesses();
    
      foreach (Process pl in p)
      {
        if (!asjob)
        {
          WriteObject(pl);
        }
        else
        {
          job.ChildJobs[0].Output.Add(PSObject.AsPSObject(pl));
        }
      }
    } // End DoProcessLogic.
    

Beispiel

Der folgende Beispielcode zeigt den Code für ein Get-Proc Cmdlet, das Prozesse intern oder mithilfe eines Hintergrundauftrags abrufen kann.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Management.Automation;  // Windows PowerShell namespace.
using System.Threading;              // Thread pool namespace for posting work.
using System.Diagnostics;            // Diagnostics namespace for retrieving
                                     // process objects.

// This sample shows a cmdlet whose work can be done by the cmdlet or by using
// a background job. Background jobs are executed in their own thread,
// independent of the pipeline thread in which the cmdlet is executed.
//
// To load this cmdlet, create a module folder and copy the GetProcessSample06.dll
// assembly into the module folder. Make sure that the path to the module folder
// is added to the $PSModulePath environment variable.
// Module folder path:
//    user/documents/WindowsPowerShell/modules/GetProcessSample06
//
// To import the module, run the following command: Import-Module GetProcessSample06.
// To test the cmdlet, run the following command: Get-Proc -name <process name>
//

//
namespace Microsoft.Samples.PowerShell.Commands
{
  /// <summary>
  ///  This cmdlet retrieves process internally or returns
  ///  a job that retrieves the processes.
  /// </summary>
  [Cmdlet(VerbsCommon.Get, "Proc")]
  public sealed class GetProcCommand : PSCmdlet
  {

    #region Parameters
    /// <summary>
    /// Specify the Name parameter. This parameter accepts
    /// process names from the command line.
    /// </summary>
    [Parameter(
               Position = 0,
               ValueFromPipeline = true,
               ValueFromPipelineByPropertyName = true)]
    [ValidateNotNullOrEmpty]
    public string[] Name
    {
      get { return processNames; }
      set { processNames = value; }
    }
    private string[] processNames;

    /// <summary>
    /// Specify the AsJob parameter. This parameter indicates
    /// whether the cmdlet should retrieve the processes internally
    /// or return a Job object that retrieves the processes.
    /// </summary>
    [Parameter()]
    public SwitchParameter AsJob
    {
      get { return asjob; }
      set { asjob = value; }
    }
    private bool asjob;

    #endregion Parameters

    #region Cmdlet Overrides

    // Create a custom job object.
    private SampleJob job = new SampleJob("Get-ProcAsJob");

    /// <summary>
    /// Determines if the processes should be retrieved
    /// internally or if a Job object should be returned.
    /// </summary>
    protected override void ProcessRecord()
    {
      if (asjob)
      {
        // Add the job definition to the job repository,
        // return the job object, and then create the thread
        // used to run the job.
        JobRepository.Add(job);
        WriteObject(job);
        ThreadPool.QueueUserWorkItem(WorkItem);
      }
      else
      {
        job.ProcessJob();
        foreach (PSObject p in job.Output)
        {
          WriteObject(p);
        }
      }
    }
    #endregion Overrides

    // Implement a custom job that derives
    // from the System.Management.Automation.Job class.
    private class SampleJob : Job
    {
      internal SampleJob(string command)
          : base(command)
      {
        SetJobState(JobState.NotStarted);
      }
      public override string StatusMessage
      {
        get { throw new NotImplementedException(); }
      }

      public override bool HasMoreData
      {
        get
        {
          return hasMoreData;
        }
      }
      private bool hasMoreData = true;

      public override string Location
      {
        get { throw new NotImplementedException(); }
      }

      public override void StopJob()
      {
        throw new NotImplementedException();
      }

      internal void ProcessJob()
      {
        SetJobState(JobState.Running);
        DoProcessLogic();
        SetJobState(JobState.Completed);
      }

      // Retrieve the processes of the local computer.
      void DoProcessLogic()
      {
        Process[] p = Process.GetProcesses();

        foreach (Process pl in p)
        {
          Output.Add(PSObject.AsPSObject(pl));
        }
        Output.Complete();
      } // End DoProcessLogic.
    } // End SampleJob class.

    void WorkItem(object dummy)
    {
       job.ProcessJob();
    }

    // Display the results of the work. If not a job,
    // process objects are returned. If a job, the
    // output is added to the job as a child job.
    void DoProcessLogic(bool asJob)
    {
      Process[] p = Process.GetProcesses();

      foreach (Process pl in p)
      {
        if (!asjob)
        {
          WriteObject(pl);
        }
        else
        {
          job.ChildJobs[0].Output.Add(PSObject.AsPSObject(pl));
        }
      }
    } // End DoProcessLogic.
  } //End GetProcCommand
}