Creazione di un cmdlet per accedere a un archivio datiCreating a Cmdlet to Access a Data Store

In questa sezione viene descritto come creare un cmdlet per accedere ai dati archiviati tramite un provider di Windows PowerShell.This section describes how to create a cmdlet that accesses stored data by way of a Windows PowerShell provider. Questo tipo di cmdlet usa l'infrastruttura del provider di Windows PowerShell del runtime di Windows PowerShell e, di conseguenza, la classe cmdlet deve derivare dalla classe di base System. Management. Automation. PSCmdlet .This type of cmdlet uses the Windows PowerShell provider infrastructure of the Windows PowerShell runtime and, therefore, the cmdlet class must derive from the System.Management.Automation.PSCmdlet base class.

Il cmdlet Select-Str descritto qui può individuare e selezionare le stringhe in un file o in un oggetto.The Select-Str cmdlet described here can locate and select strings in a file or object. I modelli utilizzati per identificare la stringa possono essere specificati in modo esplicito tramite il Path parametro del cmdlet o in modo implicito tramite il Script parametro.The patterns used to identify the string can be specified explicitly through the Path parameter of the cmdlet or implicitly through the Script parameter.

Il cmdlet è progettato per usare qualsiasi provider di Windows PowerShell che deriva da System. Management. Automation. provider. Icontentcmdletprovider.The cmdlet is designed to use any Windows PowerShell provider that derives from System.Management.Automation.Provider.Icontentcmdletprovider. Ad esempio, il cmdlet può specificare il provider FileSystem o il provider di variabili fornito da Windows PowerShell.For example, the cmdlet can specify the FileSystem provider or the Variable provider that is provided by Windows PowerShell. Per ulteriori informazioni sui provider aboutWindows PowerShell, vedere progettazione del provider di Windows PowerShell.For more information aboutWindows PowerShell providers, see Designing Your Windows PowerShell provider.

Definizione della classe cmdletDefining the Cmdlet Class

Il primo passaggio nella creazione di cmdlet è sempre il nome del cmdlet e la dichiarazione della classe .NET che implementa il cmdlet.The first step in cmdlet creation is always naming the cmdlet and declaring the .NET class that implements the cmdlet. Questo cmdlet rileva determinate stringhe, quindi il nome del verbo scelto qui è "Select", definito dalla classe System. Management. Automation. Verbscommon .This cmdlet detects certain strings, so the verb name chosen here is "Select", defined by the System.Management.Automation.Verbscommon class. Il nome del sostantivo "Str" viene usato perché il cmdlet agisce sulle stringhe.The noun name "Str" is used because the cmdlet acts upon strings. Nella dichiarazione seguente si noti che il verbo del cmdlet e il nome del sostantivo sono riflessi nel nome della classe cmdlet.In the declaration below, note that the cmdlet verb and noun name are reflected in the name of the cmdlet class. Per altre informazioni sui verbi di cmdlet approvati, vedere nomi dei verbi di cmdlet.For more information about approved cmdlet verbs, see Cmdlet Verb Names.

La classe .NET per questo cmdlet deve derivare dalla classe di base System. Management. Automation. PSCmdlet , perché fornisce il supporto necessario al runtime di Windows PowerShell per esporre l'infrastruttura del provider di Windows PowerShell.The .NET class for this cmdlet must derive from the System.Management.Automation.PSCmdlet base class, because it provides the support needed by the Windows PowerShell runtime to expose the Windows PowerShell provider infrastructure. Si noti che questo cmdlet usa anche le classi di espressioni regolari .NET Framework, ad esempio System. Text. RegularExpressions. Regex.Note that this cmdlet also makes use of the .NET Framework regular expressions classes, such as System.Text.Regularexpressions.Regex.

Il codice seguente è la definizione della classe per questo cmdlet Select-Str.The following code is the class definition for this Select-Str cmdlet.

[Cmdlet(VerbsCommon.Select, "Str", DefaultParameterSetName="PatternParameterSet")]
public class SelectStringCommand : PSCmdlet

Questo cmdlet definisce un set di parametri predefinito aggiungendo la DefaultParameterSetName parola chiave attribute alla dichiarazione della classe.This cmdlet defines a default parameter set by adding the DefaultParameterSetName attribute keyword to the class declaration. Il set di parametri predefinito PatternParameterSet viene usato quando il Script parametro non è specificato.The default parameter set PatternParameterSet is used when the Script parameter is not specified. Per ulteriori informazioni su questo set di parametri, vedere Pattern la Script Descrizione del parametro e nella sezione seguente.For more information about this parameter set, see the Pattern and Script parameter discussion in the following section.

Definizione di parametri per l'accesso ai datiDefining Parameters for Data Access

Questo cmdlet definisce diversi parametri che consentono all'utente di accedere ed esaminare i dati archiviati.This cmdlet defines several parameters that allow the user to access and examine stored data. Questi parametri includono un Path parametro che indica il percorso dell'archivio dati, un Pattern parametro che specifica il modello da utilizzare nella ricerca e diversi altri parametri che supportano la modalità di esecuzione della ricerca.These parameters include a Path parameter that indicates the location of the data store, a Pattern parameter that specifies the pattern to be used in the search, and several other parameters that support how the search is performed.

Nota

Per ulteriori informazioni sulle nozioni di base sulla definizione dei parametri, vedere aggiunta di parametri che elaborano l'input della riga di comando.For more information about the basics of defining parameters, see Adding Parameters that Process Command Line Input.

Dichiarazione del parametro pathDeclaring the Path Parameter

Per individuare l'archivio dati, questo cmdlet deve usare un percorso di Windows PowerShell per identificare il provider di Windows PowerShell progettato per accedere all'archivio dati.To locate the data store, this cmdlet must use a Windows PowerShell path to identify the Windows PowerShell provider that is designed to access the data store. Pertanto, definisce un Path parametro di tipo matrice di stringhe per indicare la posizione del provider.Therefore, it defines a Path parameter of type string array to indicate the location of the provider.

[Parameter(
           Position = 0,
           ParameterSetName = "ScriptParameterSet",
           Mandatory = true)]
[Parameter(
           Position = 0,
           ParameterSetName = "PatternParameterSet",
           ValueFromPipeline = true,
           Mandatory = true)]
           [Alias("PSPath")]
public string[] Path
{
  get { return paths; }
  set { paths = value; }
}
private string[] paths;

Si noti che questo parametro appartiene a due set di parametri diversi e che dispone di un alias.Note that this parameter belongs to two different parameter sets and that it has an alias.

Due attributi System. Management. Automation. ParameterAttribute dichiarano che il Path parametro appartiene a ScriptParameterSet e a PatternParameterSet .Two System.Management.Automation.Parameterattribute attributes declare that the Path parameter belongs to the ScriptParameterSet and the PatternParameterSet. Per ulteriori informazioni sui set di parametri, vedere aggiunta di set di parametri a un cmdlet.For more information about parameter sets, see Adding Parameter Sets to a Cmdlet.

L'attributo System. Management. Automation. AliasAttribute dichiara un PSPath alias per il Path parametro.The System.Management.Automation.Aliasattribute attribute declares a PSPath alias for the Path parameter. La dichiarazione di questo alias è fortemente consigliata per coerenza con gli altri cmdlet che accedono ai provider di Windows PowerShell.Declaring this alias is strongly recommended for consistency with other cmdlets that access Windows PowerShell providers. Per ulteriori informazioni sui percorsi di PowerShell per aboutWindows, vedere "concetti relativi ai percorsi di PowerShell" nel funzionamento di Windows PowerShell.For more information aboutWindows PowerShell paths, see "PowerShell Path Concepts" in How Windows PowerShell Works.

Dichiarazione del parametro patternDeclaring the Pattern Parameter

Per specificare i criteri di ricerca, questo cmdlet dichiara un Pattern parametro costituito da una matrice di stringhe.To specify the patterns to search for, this cmdlet declares a Pattern parameter that is an array of strings. Un risultato positivo viene restituito quando uno dei modelli viene trovato nell'archivio dati.A positive result is returned when any of the patterns are found in the data store. Si noti che questi modelli possono essere compilati in una matrice di espressioni regolari compilate o una matrice di modelli di caratteri jolly usati per le ricerche letterali.Note that these patterns can be compiled into an array of compiled regular expressions or an array of wildcard patterns used for literal searches.

[Parameter(
           Position = 1,
           ParameterSetName = "PatternParameterSet",
           Mandatory = true)]
public string[] Pattern
{
  get { return patterns; }
  set { patterns = value; }
}
private string[] patterns;
private Regex[] regexPattern;
private WildcardPattern[] wildcardPattern;

Quando si specifica questo parametro, il cmdlet usa il set di parametri predefinito PatternParameterSet .When this parameter is specified, the cmdlet uses the default parameter set PatternParameterSet. In questo caso, il cmdlet usa i criteri specificati qui per selezionare le stringhe.In this case, the cmdlet uses the patterns specified here to select strings. Al contrario, il Script parametro può essere usato anche per fornire uno script che contiene i modelli.In contrast, the Script parameter could also be used to provide a script that contains the patterns. I Script Pattern parametri e definiscono due set di parametri distinti, quindi si escludono a vicenda.The Script and Pattern parameters define two separate parameter sets, so they are mutually exclusive.

Dichiarazione dei parametri di supporto per la ricercaDeclaring Search Support Parameters

Questo cmdlet definisce i parametri di supporto seguenti che possono essere utilizzati per modificare le funzionalità di ricerca del cmdlet.This cmdlet defines the following support parameters that can be used to modify the search capabilities of the cmdlet.

Il Script parametro specifica un blocco di script che può essere utilizzato per fornire un meccanismo di ricerca alternativo per il cmdlet.The Script parameter specifies a script block that can be used to provide an alternate search mechanism for the cmdlet. Lo script deve contenere i modelli usati per la corrispondenza e restituire un oggetto System. Management. Automation. PSObject .The script must contain the patterns used for matching and return a System.Management.Automation.PSObject object. Si noti che questo parametro è anche il parametro univoco che identifica il ScriptParameterSet set di parametri.Note that this parameter is also the unique parameter that identifies the ScriptParameterSet parameter set. Quando il runtime di Windows PowerShell Visualizza questo parametro, vengono usati solo i parametri che appartengono al ScriptParameterSet set di parametri.When the Windows PowerShell runtime sees this parameter, it uses only parameters that belong to the ScriptParameterSet parameter set.

[Parameter(
           Position = 1,
           ParameterSetName = "ScriptParameterSet",
           Mandatory = true)]
public ScriptBlock Script
{
  set { script = value; }
  get { return script; }
}
ScriptBlock script;

Il SimpleMatch parametro è un parametro switch che indica se il cmdlet deve corrispondere in modo esplicito ai modelli Man mano che vengono specificati.The SimpleMatch parameter is a switch parameter that indicates whether the cmdlet is to explicitly match the patterns as they are supplied. Quando l'utente specifica il parametro nella riga di comando ( true ), il cmdlet usa i modelli così come sono specificati.When the user specifies the parameter at the command line (true), the cmdlet uses the patterns as they are supplied. Se il parametro non viene specificato ( false ), il cmdlet utilizza espressioni regolari.If the parameter is not specified (false), the cmdlet uses regular expressions. Il valore predefinito per questo parametro è false .The default for this parameter is false.

[Parameter]
public SwitchParameter SimpleMatch
{
  get { return simpleMatch; }
  set { simpleMatch = value; }
}
private bool simpleMatch;

Il CaseSensitive parametro è un parametro switch che indica se viene eseguita una ricerca con distinzione tra maiuscole e minuscole.The CaseSensitive parameter is a switch parameter that indicates whether a case-sensitive search is performed. Quando l'utente specifica il parametro nella riga di comando ( true ), il cmdlet controlla la presenza di caratteri maiuscoli e minuscoli quando si confrontano i modelli.When the user specifies the parameter at the command line (true), the cmdlet checks for the uppercase and lowercase of characters when comparing patterns. Se il parametro non viene specificato ( false ), il cmdlet non distingue tra lettere maiuscole e minuscole.If the parameter is not specified (false), the cmdlet does not distinguish between uppercase and lowercase. Ad esempio, "MyFile" e "MyFile" verrebbero restituiti come risultati positivi.For example "MyFile" and "myfile" would both be returned as positive hits. Il valore predefinito per questo parametro è false .The default for this parameter is false.

[Parameter]
public SwitchParameter CaseSensitive
{
  get { return caseSensitive; }
  set { caseSensitive = value; }
}
private bool caseSensitive;

I Exclude Include parametri e identificano gli elementi che sono esclusi esplicitamente da o inclusi nella ricerca.The Exclude and Include parameters identify items that are explicitly excluded from or included in the search. Per impostazione predefinita, il cmdlet eseguirà la ricerca di tutti gli elementi nell'archivio dati.By default, the cmdlet will search all items in the data store. Tuttavia, per limitare la ricerca eseguita dal cmdlet, questi parametri possono essere usati per indicare in modo esplicito gli elementi da includere nella ricerca o da omettere.However, to limit the search performed by the cmdlet, these parameters can be used to explicitly indicate items to be included in the search or omitted.

[Parameter]
public SwitchParameter CaseSensitive
{
  get { return caseSensitive; }
  set { caseSensitive = value; }
}
private bool caseSensitive;
[Parameter]
[ValidateNotNullOrEmpty]
public string[] Include
{
  get
  {
    return includeStrings;
  }
  set
  {
    includeStrings = value;

    this.include = new WildcardPattern[includeStrings.Length];
    for (int i = 0; i < includeStrings.Length; i++)
    {
      this.include[i] = new WildcardPattern(includeStrings[i], WildcardOptions.IgnoreCase);
    }
  }
}

internal string[] includeStrings = null;
internal WildcardPattern[] include = null;

Dichiarazione di set di parametriDeclaring Parameter Sets

Questo cmdlet usa due set di parametri ( ScriptParameterSet e PatternParameterSet , che è l'impostazione predefinita) come nomi di due set di parametri usati nell'accesso ai dati.This cmdlet uses two parameter sets (ScriptParameterSet and PatternParameterSet, which is the default) as the names of two parameter sets used in data access. PatternParameterSet è il set di parametri predefinito e viene utilizzato quando Pattern si specifica il parametro.PatternParameterSet is the default parameter set and is used when the Pattern parameter is specified. ScriptParameterSet viene utilizzato quando l'utente specifica un meccanismo di ricerca alternativo tramite il Script parametro.ScriptParameterSet is used when the user specifies an alternate search mechanism through the Script parameter. Per ulteriori informazioni sui set di parametri, vedere aggiunta di set di parametri a un cmdlet.For more information about parameter sets, see Adding Parameter Sets to a Cmdlet.

Override dei metodi di elaborazione degli inputOverriding Input Processing Methods

I cmdlet devono eseguire l'override di uno o più metodi di elaborazione dell'input per la classe System. Management. Automation. PSCmdlet .Cmdlets must override one or more of the input processing methods for the System.Management.Automation.PSCmdlet class. Per ulteriori informazioni sui metodi di elaborazione dell'input, vedere creazione del primo cmdlet.For more information about the input processing methods, see Creating Your First Cmdlet.

Questo cmdlet esegue l'override del metodo System. Management. Automation. cmdlet. BeginProcessing per compilare una matrice di espressioni regolari compilate all'avvio.This cmdlet overrides the System.Management.Automation.Cmdlet.BeginProcessing method to build an array of compiled regular expressions at startup. In questo modo si aumentano le prestazioni durante le ricerche che non utilizzano semplici corrispondenze.This increases performance during searches that do not use simple matching.

protected override void BeginProcessing()
{
  WriteDebug("Validating patterns.");
  if (patterns != null)
  {
    foreach(string pattern in patterns)
    {
      if (pattern == null)
      ThrowTerminatingError(new ErrorRecord(
                            new ArgumentNullException(
                            "Search pattern cannot be null."),
                            "NullSearchPattern",
                            ErrorCategory.InvalidArgument,
                            pattern)
                            );
    }

    WriteVerbose("Search pattern(s) are valid.");

    // If a simple match is not specified, then
    // compile the regular expressions once.
    if (!simpleMatch)
    {
      WriteDebug("Compiling search regular expressions.");

      RegexOptions regexOptions = RegexOptions.Compiled;
      if (!caseSensitive)
         regexOptions |= RegexOptions.Compiled;
      regexPattern = new Regex[patterns.Length];

      for (int i = 0; i < patterns.Length; i++)
      {
        try
        {
          regexPattern[i] = new Regex(patterns[i], regexOptions);
        }
        catch (ArgumentException ex)
        {
          ThrowTerminatingError(new ErrorRecord(
                        ex,
                        "InvalidRegularExpression",
                        ErrorCategory.InvalidArgument,
                        patterns[i]
                     ));
        }
      } //Loop through patterns to create RegEx objects.

      WriteVerbose("Pattern(s) compiled into regular expressions.");
    }// If not a simple match.

    // If a simple match is specified, then compile the
    // wildcard patterns once.
    else
    {
      WriteDebug("Compiling search wildcards.");

      WildcardOptions wildcardOptions = WildcardOptions.Compiled;

      if (!caseSensitive)
      {
        wildcardOptions |= WildcardOptions.IgnoreCase;
      }

      wildcardPattern = new WildcardPattern[patterns.Length];
      for (int i = 0; i < patterns.Length; i++)
      {
        wildcardPattern[i] =
                     new WildcardPattern(patterns[i], wildcardOptions);
      }

      WriteVerbose("Pattern(s) compiled into wildcard expressions.");
    }// If match is a simple match.
  }// If valid patterns are available.
}// End of function BeginProcessing().

Questo cmdlet esegue anche l'override del metodo System. Management. Automation. cmdlet. ProcessRecord per elaborare le selezioni di stringa che l'utente esegue nella riga di comando.This cmdlet also overrides the System.Management.Automation.Cmdlet.ProcessRecord method to process the string selections that the user makes on the command line. Scrive i risultati della selezione di stringa sotto forma di oggetto personalizzato chiamando un metodo corrispondenza privato.It writes the results of string selection in the form of a custom object by calling a private MatchString method.

protected override void ProcessRecord()
{
  UInt64 lineNumber = 0;
  MatchInfo result;
  ArrayList nonMatches = new ArrayList();

  // Walk the list of paths and search the contents for
  // any of the specified patterns.
  foreach (string psPath in paths)
  {
    // Once the filepaths are expanded, we may have more than one
    // path, so process all referenced paths.
    foreach(PathInfo path in
            SessionState.Path.GetResolvedPSPathFromPSPath(psPath)
           )
    {
      WriteVerbose("Processing path " + path.Path);

      // Check if the path represents one of the items to be
      // excluded. If so, continue to next path.
      if (!MeetsIncludeExcludeCriteria(path.ProviderPath))
         continue;

      // Get the content reader for the item(s) at the
      // specified path.
      Collection<IContentReader> readerCollection = null;
      try
      {
        readerCollection =
                    this.InvokeProvider.Content.GetReader(path.Path);
      }
      catch (PSNotSupportedException ex)
      {
        WriteError(new ErrorRecord(ex,
                   "ContentAccessNotSupported",
                    ErrorCategory.NotImplemented,
                    path.Path)
                   );
        return;
      }

      foreach(IContentReader reader in readerCollection)
      {
        // Reset the line number for this path.
        lineNumber = 0;

        // Read in a single block (line in case of a file)
        // from the object.
        IList items = reader.Read(1);

        // Read and process one block(line) at a time until
        // no more blocks(lines) exist.
        while (items != null && items.Count == 1)
        {
          // Increment the line number each time a line is
          // processed.
          lineNumber++;

          String message = String.Format("Testing line {0} : {1}",
                                        lineNumber, items[0]);

          WriteDebug(message);

          result = SelectString(items[0]);

          if (result != null)
          {
            result.Path = path.Path;
            result.LineNumber = lineNumber;

            WriteObject(result);
          }
          else
          {
            // Add the block(line) that did not match to the
            // collection of non matches , which will be stored
            // in the SessionState variable $NonMatches
            nonMatches.Add(items[0]);
          }

          // Get the next line from the object.
          items = reader.Read(1);

        }// While loop for reading one line at a time.
      }// Foreach loop for reader collection.
    }// Foreach loop for processing referenced paths.
  }// Foreach loop for walking of path list.

  // Store the list of non-matches in the
  // session state variable $NonMatches.
  try
  {
    this.SessionState.PSVariable.Set("NonMatches", nonMatches);
  }
  catch (SessionStateUnauthorizedAccessException ex)
  {
    WriteError(new ErrorRecord(ex,
               "CannotWriteVariableNonMatches",
               ErrorCategory.InvalidOperation,
               nonMatches)
              );
  }

}// End of protected override void ProcessRecord().

Accesso al contenutoAccessing Content

Il cmdlet deve aprire il provider indicato dal percorso di Windows PowerShell in modo che possa accedere ai dati.Your cmdlet must open the provider indicated by the Windows PowerShell path so that it can access the data. L'oggetto System. Management. Automation. SessionState per spazio viene usato per l'accesso al provider, mentre la proprietà System. Management. Automation. PSCmdlet. Invokeprovider * del cmdlet viene usata per aprire il provider.The System.Management.Automation.Sessionstate object for the runspace is used for access to the provider, while the System.Management.Automation.PSCmdlet.Invokeprovider* property of the cmdlet is used to open the provider. L'accesso al contenuto viene fornito tramite il recupero dell'oggetto System. Management. Automation. Providerintrinsics per il provider aperto.Access to content is provided by retrieval of the System.Management.Automation.Providerintrinsics object for the provider opened.

Questo cmdlet di esempio Select-Str usa la proprietà System. Management. Automation. Providerintrinsics. Content * per esporre il contenuto da analizzare.This sample Select-Str cmdlet uses the System.Management.Automation.Providerintrinsics.Content* property to expose the content to scan. Può quindi chiamare il metodo System. Management. Automation. Contentcmdletproviderintrinsics. GetReader * , passando il percorso necessario di Windows PowerShell.It can then call the System.Management.Automation.Contentcmdletproviderintrinsics.Getreader* method, passing the required Windows PowerShell path.

Codice di esempioCode Sample

Nel codice seguente viene illustrata l'implementazione di questa versione di questo cmdlet Select-Str.The following code shows the implementation of this version of this Select-Str cmdlet. Si noti che questo codice include la classe cmdlet, i metodi privati utilizzati dal cmdlet e il codice di snap-in di Windows PowerShell utilizzato per registrare il cmdlet.Note that this code includes the cmdlet class, private methods used by the cmdlet, and the Windows PowerShell snap-in code used to register the cmdlet. Per ulteriori informazioni sulla registrazione del cmdlet, vedere compilazione del cmdlet.For more information about registering the cmdlet, see Building the Cmdlet.

//
// Copyright (c) 2006 Microsoft Corporation. All rights reserved.
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
using System;
using System.Text.RegularExpressions;
using System.Collections;
using System.Collections.ObjectModel;
using System.Management.Automation;
using System.Management.Automation.Provider;
using System.ComponentModel;

namespace Microsoft.Samples.PowerShell.Commands
{
  #region SelectStringCommand
  /// <summary>
  /// This cmdlet searches through PSObjects for particular patterns.
  /// </summary>
  /// <remarks>
  /// This cmdlet can be used to search any object, such as a file or a
  /// variable, whose provider exposes methods for reading and writing
  /// content.
  /// </remarks>
  [Cmdlet(VerbsCommon.Select, "Str", DefaultParameterSetName="PatternParameterSet")]
  public class SelectStringCommand : PSCmdlet
  {
    #region Parameters
    /// <summary>
    /// Declare a Path parameter that specifies where the data is stored.
    /// This parameter must specify a PowerShell that indicates the
    /// PowerShell provider that is used to access the objects to be
    /// searched for matching patterns. This parameter should also have
    /// a PSPath alias to provide consistency with other cmdlets that use
    /// PowerShell providers.
    /// </summary>
    /// <value>Path of the object(s) to search.</value>
    [Parameter(
               Position = 0,
               ParameterSetName = "ScriptParameterSet",
               Mandatory = true)]
    [Parameter(
               Position = 0,
               ParameterSetName = "PatternParameterSet",
               ValueFromPipeline = true,
               Mandatory = true)]
               [Alias("PSPath")]
    public string[] Path
    {
      get { return paths; }
      set { paths = value; }
    }
    private string[] paths;

    /// <summary>
    /// Declare a Pattern parameter that specifies the pattern(s)
    /// used to find matching patterns in the string representation
    /// of the objects. A positive result will be returned
    /// if any of the patterns are found in the objects.
    /// </summary>
    /// <remarks>
    /// The patterns will be compiled into an array of wildcard
    /// patterns for a simple match (literal string matching),
    /// or the patterns will be converted into an array of compiled
    /// regular expressions.
    /// </remarks>
    /// <value>Array of patterns to search.</value>
    [Parameter(
               Position = 1,
               ParameterSetName = "PatternParameterSet",
               Mandatory = true)]
    public string[] Pattern
    {
      get { return patterns; }
      set { patterns = value; }
    }
    private string[] patterns;
    private Regex[] regexPattern;
    private WildcardPattern[] wildcardPattern;

    /// <summary>
    /// Declare a Script parameter that specifies a script block
    /// that is called to perform the matching operations
    /// instead of the matching performed by the cmdlet.
    /// </summary>
    /// <value>Script block that will be called for matching</value>
    [Parameter(
               Position = 1,
               ParameterSetName = "ScriptParameterSet",
               Mandatory = true)]
    public ScriptBlock Script
    {
      set { script = value; }
      get { return script; }
    }
    ScriptBlock script;

    /// <summary>
    /// Declare a switch parameter that specifies if the pattern(s) are used
    /// literally. If not (default), searching is
    /// done using regular expressions.
    /// </summary>
    /// <value>If True, a literal pattern is used.</value>
    [Parameter]
    public SwitchParameter SimpleMatch
    {
      get { return simpleMatch; }
      set { simpleMatch = value; }
    }
    private bool simpleMatch;

    /// <summary>
    /// Declare a switch parameter that specifies if a case-sensitive
    /// search is performed.  If not (default), a case-insensitive search
    /// is performed.
    /// </summary>
    /// <value>If True, a case-sensitive search is made.</value>
    [Parameter]
    public SwitchParameter CaseSensitive
    {
      get { return caseSensitive; }
      set { caseSensitive = value; }
    }
    private bool caseSensitive;

    /// <summary>
    /// Declare an Include parameter that species which
    /// specific items are searched.  When this parameter
    /// is used, items that are not listed here are omitted
    /// from the search.
    /// </summary>
    [Parameter]
    [ValidateNotNullOrEmpty]
    public string[] Include
    {
      get
      {
        return includeStrings;
      }
      set
      {
        includeStrings = value;

        this.include = new WildcardPattern[includeStrings.Length];
        for (int i = 0; i < includeStrings.Length; i++)
        {
          this.include[i] = new WildcardPattern(includeStrings[i], WildcardOptions.IgnoreCase);
        }
      }
    }

    internal string[] includeStrings = null;
    internal WildcardPattern[] include = null;

    /// <summary>
    /// Declare an Exclude parameter that species which
    /// specific items are omitted from the search.
    /// </summary>
    ///
    [Parameter]
    [ValidateNotNullOrEmpty]
    public string[] Exclude
    {
      get
      {
        return excludeStrings;
      }
      set
      {
        excludeStrings = value;

        this.exclude = new WildcardPattern[excludeStrings.Length];
        for (int i = 0; i < excludeStrings.Length; i++)
        {
          this.exclude[i] = new WildcardPattern(excludeStrings[i], WildcardOptions.IgnoreCase);
        }
      }
    }
    internal string[] excludeStrings;
    internal WildcardPattern[] exclude;

    #endregion Parameters

    #region Overrides
    /// <summary>
    /// If regular expressions are used for pattern matching,
    /// then build an array of compiled regular expressions
    /// at startup. This increases performance during scanning
    /// operations when simple matching is not used.
    /// </summary>
    protected override void BeginProcessing()
    {
      WriteDebug("Validating patterns.");
      if (patterns != null)
      {
        foreach(string pattern in patterns)
        {
          if (pattern == null)
          ThrowTerminatingError(new ErrorRecord(
                                new ArgumentNullException(
                                "Search pattern cannot be null."),
                                "NullSearchPattern",
                                ErrorCategory.InvalidArgument,
                                pattern)
                                );
        }

        WriteVerbose("Search pattern(s) are valid.");

        // If a simple match is not specified, then
        // compile the regular expressions once.
        if (!simpleMatch)
        {
          WriteDebug("Compiling search regular expressions.");

          RegexOptions regexOptions = RegexOptions.Compiled;
          if (!caseSensitive)
             regexOptions |= RegexOptions.Compiled;
          regexPattern = new Regex[patterns.Length];

          for (int i = 0; i < patterns.Length; i++)
          {
            try
            {
              regexPattern[i] = new Regex(patterns[i], regexOptions);
            }
            catch (ArgumentException ex)
            {
              ThrowTerminatingError(new ErrorRecord(
                            ex,
                            "InvalidRegularExpression",
                            ErrorCategory.InvalidArgument,
                            patterns[i]
                         ));
            }
          } //Loop through patterns to create RegEx objects.

          WriteVerbose("Pattern(s) compiled into regular expressions.");
        }// If not a simple match.

        // If a simple match is specified, then compile the
        // wildcard patterns once.
        else
        {
          WriteDebug("Compiling search wildcards.");

          WildcardOptions wildcardOptions = WildcardOptions.Compiled;

          if (!caseSensitive)
          {
            wildcardOptions |= WildcardOptions.IgnoreCase;
          }

          wildcardPattern = new WildcardPattern[patterns.Length];
          for (int i = 0; i < patterns.Length; i++)
          {
            wildcardPattern[i] =
                         new WildcardPattern(patterns[i], wildcardOptions);
          }

          WriteVerbose("Pattern(s) compiled into wildcard expressions.");
        }// If match is a simple match.
      }// If valid patterns are available.
    }// End of function BeginProcessing().

    /// <summary>
    /// Process the input and search for the specified patterns.
    /// </summary>
    protected override void ProcessRecord()
    {
      UInt64 lineNumber = 0;
      MatchInfo result;
      ArrayList nonMatches = new ArrayList();

      // Walk the list of paths and search the contents for
      // any of the specified patterns.
      foreach (string psPath in paths)
      {
        // Once the filepaths are expanded, we may have more than one
        // path, so process all referenced paths.
        foreach(PathInfo path in
                SessionState.Path.GetResolvedPSPathFromPSPath(psPath)
               )
        {
          WriteVerbose("Processing path " + path.Path);

          // Check if the path represents one of the items to be
          // excluded. If so, continue to next path.
          if (!MeetsIncludeExcludeCriteria(path.ProviderPath))
             continue;

          // Get the content reader for the item(s) at the
          // specified path.
          Collection<IContentReader> readerCollection = null;
          try
          {
            readerCollection =
                        this.InvokeProvider.Content.GetReader(path.Path);
          }
          catch (PSNotSupportedException ex)
          {
            WriteError(new ErrorRecord(ex,
                       "ContentAccessNotSupported",
                        ErrorCategory.NotImplemented,
                        path.Path)
                       );
            return;
          }

          foreach(IContentReader reader in readerCollection)
          {
            // Reset the line number for this path.
            lineNumber = 0;

            // Read in a single block (line in case of a file)
            // from the object.
            IList items = reader.Read(1);

            // Read and process one block(line) at a time until
            // no more blocks(lines) exist.
            while (items != null && items.Count == 1)
            {
              // Increment the line number each time a line is
              // processed.
              lineNumber++;

              String message = String.Format("Testing line {0} : {1}",
                                            lineNumber, items[0]);

              WriteDebug(message);

              result = SelectString(items[0]);

              if (result != null)
              {
                result.Path = path.Path;
                result.LineNumber = lineNumber;

                WriteObject(result);
              }
              else
              {
                // Add the block(line) that did not match to the
                // collection of non matches , which will be stored
                // in the SessionState variable $NonMatches
                nonMatches.Add(items[0]);
              }

              // Get the next line from the object.
              items = reader.Read(1);

            }// While loop for reading one line at a time.
          }// Foreach loop for reader collection.
        }// Foreach loop for processing referenced paths.
      }// Foreach loop for walking of path list.

      // Store the list of non-matches in the
      // session state variable $NonMatches.
      try
      {
        this.SessionState.PSVariable.Set("NonMatches", nonMatches);
      }
      catch (SessionStateUnauthorizedAccessException ex)
      {
        WriteError(new ErrorRecord(ex,
                   "CannotWriteVariableNonMatches",
                   ErrorCategory.InvalidOperation,
                   nonMatches)
                  );
      }

    }// End of protected override void ProcessRecord().
    #endregion Overrides

    #region PrivateMethods
    /// <summary>
    /// Check for a match using the input string and the pattern(s)
    /// specified.
    /// </summary>
    /// <param name="input">The string to test.</param>
    /// <returns>MatchInfo object containing information about
    /// result of a match</returns>
    private MatchInfo SelectString(object input)
    {
      string line = null;

      try
      {
        // Convert the object to a string type
        // safely using language support methods
        line = (string)LanguagePrimitives.ConvertTo(
                                                    input,
                                                    typeof(string)
                                                    );
        line = line.Trim(' ','\t');
      }
      catch (PSInvalidCastException ex)
      {
        WriteError(new ErrorRecord(
                   ex,
                   "CannotCastObjectToString",
                   ErrorCategory.InvalidOperation,
                   input)
                   );

        return null;
      }

      MatchInfo result = null;

      // If a scriptblock has been specified, call it
      // with the path for processing.  It will return
      // one object.
      if (script != null)
      {
        WriteDebug("Executing script block.");

        Collection<PSObject> psObjects =
                             script.Invoke(
                                           line,
                                           simpleMatch,
                                           caseSensitive
                                          );

        foreach (PSObject psObject in psObjects)
        {
          if (LanguagePrimitives.IsTrue(psObject))
          {
            result = new MatchInfo();
            result.Line = line;
            result.IgnoreCase = !caseSensitive;

            break;
          } //End of If.
        } //End ForEach loop.
      } // End of If if script exists.

      // If script block exists, see if this line matches any
      // of the match patterns.
      else
      {
        int patternIndex = 0;

        while (patternIndex < patterns.Length)
        {
          if ((simpleMatch &&
              wildcardPattern[patternIndex].IsMatch(line))
              || (regexPattern != null
              && regexPattern[patternIndex].IsMatch(line))
             )
          {
            result = new MatchInfo();
            result.IgnoreCase = !caseSensitive;
            result.Line = line;
            result.Pattern = patterns[patternIndex];

            break;
          }

          patternIndex++;

        }// While loop through patterns.
      }// Else for no script block specified.

      return result;

    }// End of SelectString

    /// <summary>
    /// Check whether the supplied name meets the include/exclude criteria.
    /// That is - it's on the include list if the include list was
    /// specified, and not on the exclude list if the exclude list was specified.
    /// </summary>
    /// <param name="path">path to validate</param>
    /// <returns>True if the path is acceptable.</returns>
    private bool MeetsIncludeExcludeCriteria(string path)
    {
      bool ok = false;

      // See if the file is on the include list.
      if (this.include != null)
      {
        foreach (WildcardPattern patternItem in this.include)
        {
          if (patternItem.IsMatch(path))
          {
            ok = true;
            break;
          }
        }
      }
      else
      {
        ok = true;
      }

      if (!ok)
         return false;

      // See if the file is on the exclude list.
      if (this.exclude != null)
      {
        foreach (WildcardPattern patternItem in this.exclude)
        {
          if (patternItem.IsMatch(path))
          {
            ok = false;
            break;
          }
        }
      }

      return ok;
    } //MeetsIncludeExcludeCriteria
    #endregion Private Methods

  }// class SelectStringCommand

  #endregion SelectStringCommand

  #region MatchInfo

  /// <summary>
  /// Class representing the result of a pattern/literal match
  /// that is passed through the pipeline by the Select-Str cmdlet.
  /// </summary>
  public class MatchInfo
  {
    /// <summary>
    /// Indicates if the match was done ignoring case.
    /// </summary>
    /// <value>True if case was ignored.</value>
    public bool IgnoreCase
    {
      get { return ignoreCase; }
      set { ignoreCase = value; }
    }
    private bool ignoreCase;

    /// <summary>
    /// Specifies the number of the matching line.
    /// </summary>
    /// <value>The number of the matching line.</value>
    public UInt64 LineNumber
    {
      get { return lineNumber; }
      set { lineNumber = value; }
    }
    private UInt64 lineNumber;

    /// <summary>
    /// Specifies the text of the matching line.
    /// </summary>
    /// <value>The text of the matching line.</value>
    public string Line
    {
      get { return line; }
      set { line = value; }
    }
    private string line;

    /// <summary>
    /// Specifies the full path of the object(file) containing the
    /// matching line.
    /// </summary>
    /// <remarks>
    /// It will be "inputStream" if the object came from the input
    /// stream.
    /// </remarks>
    /// <value>The path name</value>
    public string Path
    {
      get { return path; }
      set
      {
        pathSet = true;
        path = value;
      }
    }
    private string path;
    private bool pathSet;

    /// <summary>
    /// Specifies the pattern that was used in the match.
    /// </summary>
    /// <value>The pattern string</value>
    public string Pattern
    {
      get { return pattern; }
      set { pattern = value; }
    }
    private string pattern;

    private const string MatchFormat = "{0}:{1}:{2}";

    /// <summary>
    /// Returns the string representation of this object. The format
    /// depends on whether a path has been set for this object or
    /// not.
    /// </summary>
    /// <remarks>
    /// If the path component is set, as would be the case when
    /// matching in a file, ToString() returns the path, line
    /// number and line text.  If path is not set, then just the
    /// line text is presented.
    /// </remarks>
    /// <returns>The string representation of the match object.</returns>
    public override string ToString()
    {
      if (pathSet)
         return String.Format(
         System.Threading.Thread.CurrentThread.CurrentCulture,
         MatchFormat,
         this.path,
         this.lineNumber,
         this.line
         );
      else
         return this.line;
    }
  }// End class MatchInfo

  #endregion

  #region PowerShell snap-in

  /// <summary>
  /// Create a PowerShell snap-in for the Select-Str cmdlet.
  /// </summary>
  [RunInstaller(true)]
  public class SelectStringPSSnapIn : PSSnapIn
  {
    /// <summary>
    /// Create an instance of the SelectStrPSSnapin class.
    /// </summary>
    public SelectStringPSSnapIn()
           : base()
    {
    }

    /// <summary>
    /// Specify the name of the PowerShell snap-in.
    /// </summary>
    public override string Name
    {
      get
      {
        return "SelectStrPSSnapIn";
      }
    }

    /// <summary>
    /// Specify the vendor of the PowerShell snap-in.
    /// </summary>
    public override string Vendor
    {
      get
      {
        return "Microsoft";
      }
    }

    /// <summary>
    /// Specify the localization resource information for the vendor.
    /// Use the format: SnapinName,VendorName.
    /// </summary>
    public override string VendorResource
    {
      get
      {
        return "SelectStrSnapIn,Microsoft";
      }
    }

    /// <summary>
    /// Specify the description of the PowerShell snap-in.
    /// </summary>
    public override string Description
    {
      get
        {
          return "This is a PowerShell snap-in for the Select-Str cmdlet.";
        }
    }

    /// <summary>
    /// Specify the localization resource information for the description.
    /// Use the format: SnapinName,Description.

    /// </summary>
    public override string DescriptionResource
    {
      get
      {
          return "SelectStrSnapIn,This is a PowerShell snap-in for the Select-Str cmdlet.";
      }
    }
  }
  #endregion PowerShell snap-in

} //namespace Microsoft.Samples.PowerShell.Commands;

Compilazione del cmdletBuilding the Cmdlet

Dopo l'implementazione di un cmdlet, è necessario registrarlo con Windows PowerShell tramite uno snap-in di Windows PowerShell.After implementing a cmdlet, you must register it with Windows PowerShell through a Windows PowerShell snap-in. Per ulteriori informazioni sulla registrazione dei cmdlet, vedere come registrare i cmdlet, i provider e le applicazioni host.For more information about registering cmdlets, see How to Register Cmdlets, Providers, and Host Applications.

Test del cmdletTesting the Cmdlet

Quando il cmdlet è stato registrato con Windows PowerShell, è possibile testarlo eseguendolo nella riga di comando.When your cmdlet has been registered with Windows PowerShell, you can test it by running it on the command line. È possibile utilizzare la procedura seguente per testare il cmdlet di esempio Select-Str.The following procedure can be used to test the sample Select-Str cmdlet.

  1. Avviare Windows PowerShell ed eseguire una ricerca nel file delle note per individuare le occorrenze delle righe con l'espressione ".NET".Start Windows PowerShell, and search the Notes file for occurrences of lines with the expression ".NET". Si noti che le virgolette intorno al nome del percorso sono necessarie solo se il percorso è costituito da più di una parola.Note that the quotation marks around the name of the path are required only if the path consists of more than one word.

    select-str -Path "notes" -Pattern ".NET" -SimpleMatch=$false
    

    Viene visualizzato l'output seguente.The following output appears.

    IgnoreCase   : True
    LineNumber   : 8
    Line         : Because Windows PowerShell works directly with .NET objects, there is often a .NET object
    Path         : C:\PowerShell-Progs\workspace\Samples\SelectStr\notes
    Pattern      : .NET
    IgnoreCase   : True
    LineNumber   : 21
    Line         : You should normally define the class for a cmdlet in a .NET namespace
    Path         : C:\PowerShell-Progs\workspace\Samples\SelectStr\notes
    Pattern      : .NET
    
  2. Cercare nel file delle note le occorrenze di righe con la parola "over", seguita da qualsiasi altro testo.Search the Notes file for occurrences of lines with the word "over", followed by any other text. Il SimpleMatch parametro usa il valore predefinito di false .The SimpleMatch parameter is using the default value of false. La ricerca non fa distinzione tra maiuscole e minuscole perché il CaseSensitive parametro è impostato su false .The search is case-insensitive because the CaseSensitive parameter is set to false.

    select-str -Path notes -Pattern "over*" -SimpleMatch -CaseSensitive:$false
    

    Viene visualizzato l'output seguente.The following output appears.

    IgnoreCase   : True
    LineNumber   : 45
    Line         : Override StopProcessing
    Path         : C:\PowerShell-Progs\workspace\Samples\SelectStr\notes
    Pattern      : over*
    IgnoreCase   : True
    LineNumber   : 49
    Line         : overriding the StopProcessing method
    Path         : C:\PowerShell-Progs\workspace\Samples\SelectStr\notes
    Pattern      : over*
    
  3. Eseguire una ricerca nel file delle note usando un'espressione regolare come modello.Search the Notes file using a regular expression as the pattern. Tramite il cmdlet viene eseguita la ricerca di caratteri alfabetici e spazi vuoti racchiusi tra parentesi.The cmdlet searches for alphabetical characters and blank spaces enclosed in parentheses.

    select-str -Path notes -Pattern "\([A-Za-z:blank:]" -SimpleMatch:$false
    

    Viene visualizzato l'output seguente.The following output appears.

    IgnoreCase   : True
    LineNumber   : 1
    Line         : Advisory Guidelines (Consider Following)
    Path         : C:\PowerShell-Progs\workspace\Samples\SelectStr\notes
    Pattern      : \([A-Za-z:blank:]
    IgnoreCase   : True
    LineNumber   : 53
    Line         : If your cmdlet has objects that are not disposed of (written to the pipeline)
    Path         : C:\PowerShell-Progs\workspace\Samples\SelectStr\notes
    Pattern      : \([A-Za-z:blank:]
    
  4. Eseguire una ricerca con distinzione tra maiuscole e minuscole del file di note per le occorrenze della parola "Parameter".Perform a case-sensitive search of the Notes file for occurrences of the word "Parameter".

    select-str -Path notes -Pattern Parameter -CaseSensitive
    

    Viene visualizzato l'output seguente.The following output appears.

    IgnoreCase   : False
    LineNumber   : 6
    Line         : Support an InputObject Parameter
    Path         : C:\PowerShell-Progs\workspace\Samples\SelectStr\notes
    Pattern      : Parameter
    IgnoreCase   : False
    LineNumber   : 30
    Line         : Support Force Parameter
    Path         : C:\PowerShell-Progs\workspace\Samples\SelectStr\notes
    Pattern      : Parameter
    
  5. Eseguire una ricerca nel provider di variabili fornito con Windows PowerShell per le variabili con valori numerici compresi tra 0 e 9.Search the variable provider shipped with Windows PowerShell for variables that have numerical values from 0 through 9.

    select-str -Path * -Pattern "[0-9]"
    

    Viene visualizzato l'output seguente.The following output appears.

    IgnoreCase   : True
    LineNumber   : 1
    Line         : 64
    Path         : Variable:\MaximumHistoryCount
    Pattern      : [0-9]
    
  6. Usare un blocco di script per cercare il file SelectStrCommandSample.cs per la stringa "pos".Use a script block to search the file SelectStrCommandSample.cs for the string "Pos". La funzione cmatch per lo script esegue una corrispondenza del modello senza distinzione tra maiuscole e minuscole.The cmatch function for the script performs a case-insensitive pattern match.

    select-str -Path "SelectStrCommandSample.cs" -Script { if ($args[0] -cmatch "Pos"){ return $true } return $false }
    

    Viene visualizzato l'output seguente.The following output appears.

    IgnoreCase   : True
    LineNumber   : 37
    Line         :    Position = 0.
    Path         : C:\PowerShell-Progs\workspace\Samples\SelectStr\SelectStrCommandSample.cs
    Pattern      :
    

Vedere ancheSee Also

Come creare un cmdlet di Windows PowerShellHow to Create a Windows PowerShell Cmdlet

Creazione del primo cmdletCreating Your First Cmdlet

Creazione di un cmdlet che modifica il sistemaCreating a Cmdlet that Modifies the System

Progettare il provider di Windows PowerShellDesign Your Windows PowerShell Provider

Funzionamento di Windows PowerShellHow Windows PowerShell Works

Come registrare cmdlet, provider e applicazioni hostHow to Register Cmdlets, Providers, and Host Applications

Windows PowerShell SDKWindows PowerShell SDK