Creating a Cmdlet to Access a Data Store (Criar um Cmdlet para Aceder a um Arquivo de Dados)
Esta secção descreve como criar um cmdlet que acede aos dados armazenados através de um fornecedor Windows PowerShell. Este tipo de cmdlet utiliza a infraestrutura de prestadores de Windows PowerShell do tempo de funcionação Windows PowerShell e, portanto, a classe cmdlet deve derivar da classe base System.Management.Automation.PSCmdlet.
O Select-Str cmdlet descrito aqui pode localizar e selecionar cordas num ficheiro ou objeto. Os padrões utilizados para identificar a cadeia podem ser especificados explicitamente através Path
do parâmetro do cmdlet ou implicitamente através do Script
parâmetro.
O cmdlet foi concebido para utilizar qualquer fornecedor de Windows PowerShell que deriva do System.Management.Automation.Provider.Icontentcmdletprovider. Por exemplo, o cmdlet pode especificar o fornecedor FileSystem ou o fornecedor Variável que é fornecido por Windows PowerShell. Para obter mais informações sobre os fornecedores PowerShell daWindows, consulte designar o seu fornecedor Windows PowerShell.
Definição da Classe Cmdlet
O primeiro passo na criação de cmdlet é sempre nomear o cmdlet e declarar a classe .NET que implementa o cmdlet. Este cmdlet deteta certas cordas, pelo que o nome verbo escolhido aqui é "Select", definido pela classe System.Management.Automation.Verbscommon. O nome substantivo "Str" é usado porque o cmdlet age sobre cordas. Na declaração abaixo, note-se que o verbo cmdlet e o nome do substantivo refletem-se no nome da classe cmdlet. Para obter mais informações sobre verbos de cmdlet aprovados, consulte o Cmdlet Verb Names.
A classe .NET para este cmdlet deve derivar da classe base System.Management.Automation.PSCmdlet, pois fornece o suporte necessário pelo Windows PowerShell tempo de execução para expor a infraestrutura do fornecedor Windows PowerShell. Note que este cmdlet também faz uso das classes de expressões regulares .NET Framework, tais como System.Text.Regularexpressions.Regex.
O seguinte código é a definição de classe para este Select-Str cmdlet.
[Cmdlet(VerbsCommon.Select, "Str", DefaultParameterSetName="PatternParameterSet")]
public class SelectStringCommand : PSCmdlet
Este cmdlet define um parâmetro padrão definido adicionando a DefaultParameterSetName
palavra-chave do atributo à declaração de classe. O parâmetro padrão PatternParameterSet
é utilizado quando o parâmetro não é Script
especificado. Para obter mais informações sobre este parâmetro definido, consulte a Pattern
discussão e Script
a discussão dos parâmetros na secção seguinte.
Definição de parâmetros para o acesso a dados
Este cmdlet define vários parâmetros que permitem ao utilizador aceder e examinar os dados armazenados. Estes parâmetros incluem um Path
parâmetro que indica a localização da loja de dados, um parâmetro que especifica o Pattern
padrão a ser usado na pesquisa, e vários outros parâmetros que suportam a forma como a pesquisa é realizada.
Nota
Para obter mais informações sobre os fundamentos da definição de parâmetros, consulte adicionar parâmetros que processam a entrada da linha de comando.
Declarando o Parâmetro do Caminho
Para localizar a loja de dados, este cmdlet deve utilizar um caminho Windows PowerShell para identificar o Windows PowerShell fornecedor que se encontra projetado para aceder à loja de dados. Portanto, define um Path
parâmetro de matriz de tipo de cadeia para indicar a localização do fornecedor.
[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;
Note que este parâmetro pertence a dois conjuntos de parâmetros diferentes e que tem um pseudónimo.
Dois atributos System.Management.Automation.Parameterattribute declaram que o Path
parâmetro pertence ao ScriptParameterSet
. PatternParameterSet
Para obter mais informações sobre conjuntos de parâmetros, consulte conjuntos de parâmetros adicionais a um cmdlet.
O atributo System.Management.Automation.Aliasattribute declara PSPath
um pseudónimo para o Path
parâmetro. Declarar este pseudónimo é fortemente recomendado para a consistência com outros cmdlets que acedem Windows PowerShell fornecedores. Para obter mais informações sobre os caminhos powershell daWindows, consulte "PowerShell Path Concepts" em Como funciona Windows PowerShell.
Declarando o parâmetro do padrão
Para especificar os padrões a procurar, este cmdlet declara um Pattern
parâmetro que é uma matriz de cordas. Um resultado positivo é devolvido quando qualquer um dos padrões é encontrado na loja de dados. Note que estes padrões podem ser compilados em uma variedade de expressões regulares compiladas ou uma variedade de padrões wildcard usados para pesquisas literais.
[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 este parâmetro é especificado, o cmdlet utiliza o parâmetro padrão definido PatternParameterSet
. Neste caso, o cmdlet utiliza os padrões especificados aqui para selecionar cordas. Em contraste, o Script
parâmetro também poderia ser usado para fornecer um script que contém os padrões. Os Script
Pattern
parâmetros e parâmetros definem dois parâmetros separados, por isso são mutuamente exclusivos.
Declarar parâmetros de suporte à pesquisa
Este cmdlet define os seguintes parâmetros de suporte que podem ser usados para modificar as capacidades de pesquisa do cmdlet.
O Script
parâmetro especifica um bloco de scripts que pode ser usado para fornecer um mecanismo de pesquisa alternativo para o cmdlet. O script deve conter os padrões utilizados para combinar e devolver um objeto System.Management.Automation.PSObject. Note que este parâmetro é também o parâmetro único que identifica o ScriptParameterSet
conjunto de parâmetros. Quando o tempo de execução Windows PowerShell vê este parâmetro, utiliza apenas parâmetros que pertencem ao ScriptParameterSet
parâmetro definido.
[Parameter(
Position = 1,
ParameterSetName = "ScriptParameterSet",
Mandatory = true)]
public ScriptBlock Script
{
set { script = value; }
get { return script; }
}
ScriptBlock script;
O SimpleMatch
parâmetro é um parâmetro de comutação que indica se o cmdlet deve corresponder explicitamente aos padrões à medida que são fornecidos. Quando o utilizador especificar o parâmetro na linha de comando true
(), o cmdlet utiliza os padrões à medida que são fornecidos. Se o parâmetro não for especificado false
(), o cmdlet utiliza expressões regulares. O padrão para este parâmetro é false
.
[Parameter]
public SwitchParameter SimpleMatch
{
get { return simpleMatch; }
set { simpleMatch = value; }
}
private bool simpleMatch;
O CaseSensitive
parâmetro é um parâmetro de comutação que indica se é realizada uma pesquisa sensível ao caso. Quando o utilizador especificar o parâmetro na linha de comando true
(), o cmdlet verifica se a maiúscula e minúscula dos caracteres ao comparar padrões. Se o parâmetro não for especificado false
(), o cmdlet não distingue entre maiúsculas e minúsculas. Por exemplo, "MyFile" e "myfile" seriam ambos devolvidos como sucessos positivos. O padrão para este parâmetro é false
.
[Parameter]
public SwitchParameter CaseSensitive
{
get { return caseSensitive; }
set { caseSensitive = value; }
}
private bool caseSensitive;
Os Exclude
Include
parâmetros e parâmetros identificam itens explicitamente excluídos ou incluídos na pesquisa. Por predefinição, o cmdlet procurará todos os itens na loja de dados. No entanto, para limitar a pesquisa realizada pelo cmdlet, estes parâmetros podem ser usados para indicar explicitamente itens a serem incluídos na pesquisa ou omitidos.
[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;
Conjuntos de parâmetros declarados
Este cmdlet utiliza dois conjuntos de parâmetros ScriptParameterSet
PatternParameterSet
(e, que é o padrão) como os nomes de dois conjuntos de parâmetros utilizados no acesso aos dados. PatternParameterSet
é o parâmetro padrão definido e é usado quando o Pattern
parâmetro é especificado. ScriptParameterSet
é utilizado quando o utilizador especifica um mecanismo de pesquisa alternativo através do Script
parâmetro. Para obter mais informações sobre conjuntos de parâmetros, consulte conjuntos de parâmetros adicionais a um cmdlet.
Métodos de processamento de entradas dominantes
Os cmdlets devem sobrepor-se a um ou mais dos métodos de processamento de entrada para a classe System.Management.Automation.PSCmdlet. Para obter mais informações sobre os métodos de processamento de entrada, consulte Criar o Seu Primeiro Comandante.
Este cmdlet substitui o método System.Management.Automation.Cmdlet.BeginProcessing para construir uma série de expressões regulares compiladas no arranque. Isto aumenta o desempenho durante pesquisas que não usam correspondência simples.
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().
Este cmdlet também substitui o método System.Management.Automation.Cmdlet.ProcessRecord para processar as seleções de cadeias que o utilizador faz na linha de comando. Escreve os resultados da seleção de cordas sob a forma de um objeto personalizado, chamando um método de MatchString privado.
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().
Aceder ao Conteúdo
O seu cmdlet deve abrir o fornecedor indicado pelo caminho Windows PowerShell para que possa aceder aos dados. O objeto System.Management.Automation.Sessionstate para o espaço de funcionação é utilizado para o acesso ao fornecedor, enquanto a propriedade System.Management.Automation.PSCmdlet.Invokeprovider* do cmdlet é utilizada para abrir o fornecedor. O acesso aos conteúdos é fornecido através da recuperação do objeto System.Management.Automation.Providerintrinsics para o fornecedor aberto.
Esta amostra Select-Str cmdlet utiliza a propriedade System.Management.Automation.Providerintrinsics.Content* para expor o conteúdo à digitalização. Pode então chamar o método System.Management.Automation.Contentcmdletproviderintrits.Getreader*, passando o caminho Windows PowerShell exigido.
Amostra de código
O código que se segue mostra a implementação desta versão deste Select-Str cmdlet. Note que este código inclui a classe cmdlet, métodos privados utilizados pelo cmdlet, e o código de encaixe Windows PowerShell utilizado para registar o cmdlet. Para obter mais informações sobre o registo do cmdlet, consulte a Construção do 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;
Construção do Comandante
Depois de implementar um cmdlet, deve registá-lo com Windows PowerShell através de um encaixe Windows PowerShell. Para obter mais informações sobre o registo de cmdlets, consulte Como Registar Cmdlets, Fornecedores e Aplicações de Anfitrião.
Testar o Cmdlet
Quando o seu cmdlet estiver registado com Windows PowerShell, pode testá-lo executando-o na linha de comando. Pode utilizar-se o procedimento seguinte para testar a amostra Select-Str cmdlet.
Comece Windows PowerShell e procure no ficheiro Notas ocorrências de linhas com a expressão ".NET". Note que as aspas em torno do nome do caminho só são necessárias se o caminho consistir em mais de uma palavra.
select-str -Path "notes" -Pattern ".NET" -SimpleMatch=$false
Aparece a seguinte saída.
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
Pesse o ficheiro Notas para ver se há ocorrências de linhas com a palavra "mais", seguida de qualquer outro texto. O
SimpleMatch
parâmetro está a utilizar o valor predefinido defalse
. A procura é insensidora porque oCaseSensitive
parâmetro está definido parafalse
.select-str -Path notes -Pattern "over*" -SimpleMatch -CaseSensitive:$false
Aparece a seguinte saída.
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*
Pesse o ficheiro Notas utilizando uma expressão regular como padrão. O cmdlet procura caracteres alfabéticos e espaços em branco fechados em parênteses.
select-str -Path notes -Pattern "\([A-Za-z:blank:]" -SimpleMatch:$false
Aparece a seguinte saída.
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:]
Efetuar uma pesquisa sensível a casos no ficheiro Notas para ocorrências da palavra "Parâmetro".
select-str -Path notes -Pattern Parameter -CaseSensitive
Aparece a seguinte saída.
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
Pesquise o fornecedor variável enviado com Windows PowerShell para obter variáveis que tenham valores numéricos de 0 a 9.
select-str -Path * -Pattern "[0-9]"
Aparece a seguinte saída.
IgnoreCase : True LineNumber : 1 Line : 64 Path : Variable:\MaximumHistoryCount Pattern : [0-9]
Utilize um bloco de scripts para pesquisar o ficheiro SelectStrCommandSample.cs para a cadeia "Pos". A função cmatch para o script executa um padrão-insensível caso.
select-str -Path "SelectStrCommandSample.cs" -Script { if ($args[0] -cmatch "Pos"){ return $true } return $false }
Aparece a seguinte saída.
IgnoreCase : True LineNumber : 37 Line : Position = 0. Path : C:\PowerShell-Progs\workspace\Samples\SelectStr\SelectStrCommandSample.cs Pattern :
Consulte também
Como criar um Windows PowerShell Cmdlet
Criando o seu primeiro Comandante
Creating a Cmdlet that Modifies the System (Criar um Cmdlet que Modifica o Sistema)
Desenhe o seu fornecedor de Windows PowerShell
Como funciona Windows PowerShell
Como registar cmdlets, fornecedores e aplicações de anfitrião
Comentários
https://aka.ms/ContentUserFeedback.
Brevemente: Ao longo de 2024, vamos descontinuar progressivamente o GitHub Issues como mecanismo de feedback para conteúdos e substituí-lo por um novo sistema de feedback. Para obter mais informações, veja:Submeter e ver comentários