Vytvoření rutiny pro přístup k úložišti dat

tato část popisuje, jak vytvořit rutinu, která přistupuje k uloženým datům způsobem poskytovatele Windows PowerShell. tento typ rutiny používá infrastrukturu poskytovatele Windows PowerShell Windows PowerShell runtime a proto třída rutiny musí být odvozená od základní třídy System. Management. Automation. PSCmdlet .

Zde popsaná rutina Select-Str může vyhledat a vybrat řetězce v souboru nebo objektu. Vzory použité k identifikaci řetězce lze zadat explicitně prostřednictvím Path parametru rutiny nebo implicitně prostřednictvím Script parametru.

rutina je navržená tak, aby používala jakéhokoli poskytovatele Windows PowerShell, který je odvozený od System. Management. Automation. provider. Icontentcmdletprovider. Například rutina může určit poskytovatele systému souborů nebo poskytovatele proměnných, který je poskytován Windows PowerShell. další informace o aboutWindows poskytovatelích prostředí PowerShell najdete v tématu návrh poskytovatele Windows PowerShell.

Definování třídy rutiny

První krok při vytváření rutiny vždy pojmenovává rutinu a deklaruje třídu .NET, která implementuje rutinu. Tato rutina rozpoznává určité řetězce, takže název příkazu zvolený tady je "SELECT" definovaný třídou System. Management. Automation. Verbscommon . Název podstatného jména "str" se používá, protože rutina funguje na řetězcích. V deklaraci níže si všimněte, že operace rutiny a název podstatné jméno se projeví v názvu třídy rutiny. Další informace o schválených operacích rutin najdete v tématu názvy operací rutiny.

třída .net pro tuto rutinu musí být odvozená od základní třídy System. Management. Automation. PSCmdlet , protože poskytuje podporu potřebnou modulem runtime Windows PowerShell k vystavení infrastruktury poskytovatele Windows PowerShell. všimněte si, že tato rutina také využívá .NET Framework třídy regulárních výrazů, jako je System. Text. Regularexpressions. Regex.

Následující kód je definicí třídy pro tuto Select-Str rutinu.

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

Tato rutina definuje výchozí sadu parametrů přidáním DefaultParameterSetName klíčového slova atributu do deklarace třídy. Výchozí sada parametrů PatternParameterSet se používá, pokud není Script zadán parametr. Další informace o této sadě parametrů naleznete Pattern Script v popisu parametru a v následující části.

Definování parametrů pro přístup k datům

Tato rutina definuje několik parametrů, které umožní uživateli přístup k uloženým datům a jejich prohlížení. Mezi tyto parametry patří Path parametr, který označuje umístění úložiště dat, Pattern parametr, který určuje vzor, který má být použit ve vyhledávání, a několik dalších parametrů, které podporují, jak je hledání prováděno.

Poznámka

Další informace o základech definování parametrů naleznete v tématu Přidání parametrů, které zpracovávají vstup z příkazového řádku.

Deklarace parametru cesty

chcete-li vyhledat úložiště dat, tato rutina musí použít cestu Windows PowerShell k identifikaci poskytovatele Windows PowerShell, který je určen pro přístup do úložiště dat. Proto definuje Path parametr typu pole řetězců k označení umístění poskytovatele.

[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;

Všimněte si, že tento parametr patří do dvou různých sad parametrů a že má alias.

Dva atributy System. Management. Automation. ParameterAttribute deklarují, že Path parametr patří do ScriptParameterSet a PatternParameterSet . Další informace o sadách parametrů naleznete v tématu Přidání sad parametrů do rutiny.

Atribut System. Management. Automation. Aliasattribute deklaruje PSPath alias pro Path parametr. při deklaraci tohoto aliasu se důrazně doporučuje konzistence s jinými rutinami, které přistupují k poskytovatelům Windows PowerShell. další informace o cestách powershellu aboutWindows najdete v článku koncepty "powershell Path" v tématu How to Windows PowerShell.

Deklarace parametru vzoru

Chcete-li určit vzorce, které chcete vyhledat, tato rutina deklaruje Pattern parametr, který je polem řetězců. Pokud se některý ze vzorů nachází v úložišti dat, vrátí se kladný výsledek. Všimněte si, že tyto vzory lze zkompilovat do pole zkompilovaných regulárních výrazů nebo pole vzorových zástupných znaků používaných pro vyhledávání literálů.

[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;

Pokud je tento parametr zadán, použije rutina výchozí sadu parametrů PatternParameterSet . V tomto případě rutina používá pro výběr řetězců vzory, které jsou zde uvedené. Naproti tomu Script parametr může být také použit k poskytnutí skriptu, který obsahuje vzory. ScriptParametry a Pattern definují dvě samostatné sady parametrů, takže se vzájemně vylučují.

Deklarování parametrů podpory hledání

Tato rutina definuje následující parametry podpory, které lze použít k úpravě možností vyhledávání rutiny.

ScriptParametr určuje blok skriptu, který lze použít k poskytnutí alternativního vyhledávacího mechanismu pro rutinu. Skript musí obsahovat vzory používané pro porovnání a vrácení objektu System. Management. Automation. PSObject . Všimněte si, že tento parametr je také jedinečný parametr, který identifikuje ScriptParameterSet sadu parametrů. když modul runtime Windows PowerShell uvidí tento parametr, používá pouze parametry, které patří do ScriptParameterSet sady parametrů.

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

SimpleMatchParametr je parametr přepínače, který označuje, zda má rutina explicitně odpovídat vzorům, které jsou zadány. Když uživatel zadá parametr na příkazovém řádku ( true ), rutina použije vzorce, jak jsou dodány. Pokud parametr není zadán ( false ), rutina používá regulární výrazy. Výchozí hodnota pro tento parametr je false .

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

CaseSensitiveParametr je parametr Switch, který označuje, zda je prováděno vyhledávání citlivé na velká a malá písmena. Když uživatel zadává parametr na příkazovém řádku ( true ), rutina při porovnávání vzorů kontroluje velká a malá písmena znaků. Pokud parametr není zadán ( false ), rutina nerozlišuje mezi velkými a malými písmeny. Například "MyFile" a "MyFile" by se měly vracet jako kladné přístupy. Výchozí hodnota pro tento parametr je false .

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

ExcludeParametry a Include identifikují položky, které jsou explicitně vyloučeny z nebo zahrnuty ve vyhledávání. Ve výchozím nastavení bude rutina Hledat všechny položky v úložišti dat. Chcete-li však omezit vyhledávání provedené rutinou, můžete tyto parametry použít k explicitnímu označení položek, které mají být zahrnuty do hledání nebo vynechány.

[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;

Deklarace sad parametrů

Tato rutina používá dvě sady parametrů ( ScriptParameterSet a PatternParameterSet , což je výchozí) jako názvy dvou sad parametrů používaných při přístupu k datům. PatternParameterSet je výchozí sada parametrů, která se používá při Pattern zadání parametru. ScriptParameterSet se používá v případě, že uživatel určí alternativní vyhledávací mechanismus prostřednictvím Script parametru. Další informace o sadách parametrů naleznete v tématu Přidání sad parametrů do rutiny.

Přepsání metod zpracování vstupu

Rutiny musí přepsat jednu nebo více metod zpracování vstupu pro třídu System. Management. Automation. PSCmdlet . Další informace o metodách zpracování vstupu najdete v tématu Vytvoření první rutiny.

Tato rutina přepisuje metodu System. Management. Automation. rutina. BeginProcessing pro sestavení pole zkompilovaných regulárních výrazů při spuštění. Tím se zvyšuje výkon při hledání, které nepoužívají jednoduché porovnání.

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().

Tato rutina také přepisuje metodu System. Management. Automation. rutina. ProcessRecord pro zpracování výběrů řetězců, které uživatel provede na příkazovém řádku. Zapisuje výsledky výběru řetězce ve formě vlastního objektu voláním metody private MatchString .

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().

Přístup k obsahu

rutina musí otevřít poskytovatele označeného Windows PowerShell cestou, aby mohl přistupovat k datům. Objekt System. Management. Automation. SessionState pro prostředí runspace se používá pro přístup k poskytovateli, zatímco vlastnost System. Management. Automation. PSCmdlet. Invokeprovider * rutiny slouží k otevření poskytovatele. Přístup k obsahu je k dispozici prostřednictvím načtení objektu System. Management. Automation. Providerintrinsics pro poskytovatele, který byl otevřen.

Tato ukázková Select-Str rutina používá vlastnost System. Management. Automation. Providerintrinsics. Content * k zpřístupnění obsahu, který se má prohledat. pak může volat metodu System. Management. Automation. Contentcmdletproviderintrinsics. getreader * , která předává požadovanou cestu Windows PowerShell.

Vzorek kódu

Následující kód ukazuje implementaci této verze této rutiny Select-Str. všimněte si, že tento kód obsahuje třídu rutiny, soukromé metody používané rutinou a kód modulu snap-in Windows PowerShell, který se používá k registraci rutiny. Další informace o registraci rutiny naleznete v tématu Vytvoření rutiny.

//
// 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;

Sestavení rutiny

po implementaci rutiny je nutné ji zaregistrovat pomocí Windows PowerShell prostřednictvím modulu snap-in Windows PowerShell. Další informace o registraci rutin najdete v tématu jak registrovat rutiny, zprostředkovatele a hostitelské aplikace.

Testování rutiny

když je vaše rutina zaregistrovaná ve službě Windows PowerShell, můžete ji otestovat spuštěním na příkazovém řádku. Následující postup lze použít k otestování ukázkové Select-Str rutiny.

  1. spusťte Windows PowerShell a vyhledejte v souboru poznámek výskyty řádků s výrazem ".net". Všimněte si, že uvozovky kolem názvu cesty jsou požadovány pouze v případě, že cesta obsahuje více než jedno slovo.

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

    Zobrazí se následující výstup.

    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. V souboru s poznámkami vyhledejte výskyty řádků se slovem "" nad "a následným dalším textem. SimpleMatchParametr používá výchozí hodnotu false . Hledání rozlišuje malá a velká písmena, protože CaseSensitive parametr je nastaven na hodnotu false .

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

    Zobrazí se následující výstup.

    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. Vyhledejte soubor poznámky pomocí regulárního výrazu jako vzoru. Rutina vyhledává abecední znaky a prázdné mezery uzavřené v závorkách.

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

    Zobrazí se následující výstup.

    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. Pro výskyty slova "Parameter" vyhledá v souboru poznámek rozlišování velkých a malých písmen.

    select-str -Path notes -Pattern Parameter -CaseSensitive
    

    Zobrazí se následující výstup.

    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. V poskytovateli proměnných dodávaném s Windows PowerShell proměnné, které mají číselné hodnoty od 0 do 9.

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

    Zobrazí se následující výstup.

    IgnoreCase   : True
    LineNumber   : 1
    Line         : 64
    Path         : Variable:\MaximumHistoryCount
    Pattern      : [0-9]
    
  6. Blok skriptu použijte k vyhledání řetězce "Pos" v souboru SelectStrCommandSample.cs. Funkce cmatch pro skript provádí porovnávání vzoru bez rozlišení velkých a malých písmen.

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

    Zobrazí se následující výstup.

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

Viz také

Vytvoření rutiny Windows PowerShell rutinu

Vytvoření první rutiny

Vytvoření rutiny, která upravuje systém

Návrh poskytovatele Windows PowerShell

Jak Windows PowerShell funguje

Registrace rutin, poskytovatelů a hostitelských aplikací

Sada SDK Windows PowerShellu